This prevents having a very large number of anonymous modules attached to a model. All these anonymous models harm performance because of slower method lookup. It also makes the behavior when reopening a model and redefining a property more consistent. The latter actually happens a lot in the specs. This was found wheni debugging the JIT issue with Rubinius.
* Using a case statement here won't necessarily work because the OneToMany object is a proxy object, and the Relation#=== methods are inherited from Class#===, and don't know anything about the proxy object. The best approach is to use kind_of? and only handle the 3 distinct cases: 1. The relationship is m:1 2. The relationship is m:m (or 1:1 wrapping a m:m) 3. The relationship is 1:m (or 1:1 wrapping a 1:m)
* On some platforms, where the specs are run in a different order, this was causing problems because the specs that didn't require spec_helper were being executed first, and the environment wasn't setup properly for them. However, on OSX (where I test primarily) the spec_helper is required at some earlier point in time. This should never happen. A spec should be able to run stand-alone, and in any order and always return the same results.
Tested 2.3.3 and 2.3.11 (latest as of this commit): ruby> ActiveSupport::VERSION::STRING => "2.3.11" ruby> "2010-01-01 00:00:00 -0800".to_datetime => Fri, 01 Jan 2010 00:00:00 +0000 # TZ gone ruby> DateTime.parse("2010-01-01 00:00:00 -0800") => Fri, 01 Jan 2010 00:00:00 -0800 # TZ preserved
This method is mainly used inside DM to generate anonymous join models. It was never really meant to be public API and we actually already started questioning the meaning of semipublic API. If a method is intended to be called by clients, it's public API, if not it should be private API.
…n this case they are equivalent
example: Post.all( :order => author.full_name, :links => [Post.relationships['author'].links] )
the base model, for example: Post.all( :order => Author.full_name, :links => Post.relationships['author'].links] )
Background: Property class lookups are triggered through const_missing, typically when defining a property in the Model DSL and referring to it by innermost class name (e.g. "Serial"). This in turn maps to Property#find_class, which uses an algorithm that effectively relegates lookups inside the descendants tree to a flat namespace of demodulized names. The algorithm returns the most-recently-defined property of the same name, which is incorrect in the case where a custom property with the same class name as a DM built-in is present, but not relevant in all contexts. (FYI this problem was present before the demodulized_names optimization was introduced.) We solve this problem by only ever adding to the lookup table (not allowing overrides). Given that DM typically gets its property classes loaded first, this means its types are always "reserved", and anything externally-derived will be included for indirect lookups only when they don't override built-in type names. For the common case, this should be fine. For external property authors who want to provide "replacements" for builtins (e.g. in a non-DM-supported adapter), they should follow the convention of wrapping those (or all) properties in a module, and include'ing the module on the model class directly. This bypasses the const_missing lookup that would normally check the Property descendant tree/table, ensuring the correct property class mapping in the context of a given model.
[#1336 state:fixed] [#1411 state:fixed]