diff options
Diffstat (limited to 'activerecord/lib/active_record')
-rwxr-xr-x | activerecord/lib/active_record/base.rb | 25 | ||||
-rw-r--r-- | activerecord/lib/active_record/dynamic_scope_match.rb | 25 |
2 files changed, 49 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 4c9ad24ea3..cca012ed55 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1456,7 +1456,10 @@ module ActiveRecord #:nodoc: def respond_to?(method_id, include_private = false) if match = DynamicFinderMatch.match(method_id) return true if all_attributes_exists?(match.attribute_names) + elsif match = DynamicScopeMatch.match(method_id) + return true if all_attributes_exists?(match.attribute_names) end + super end @@ -1809,7 +1812,11 @@ module ActiveRecord #:nodoc: # This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount) # or find_or_create_by_user_and_password(user, password). # - # Each dynamic finder or initializer/creator is also defined in the class after it is first invoked, so that future + # Also enables dynamic scopes like scoped_by_user_name(user_name) and scoped_by_user_name_and_password(user_name, password) that + # are turned into scoped(:conditions => ["user_name = ?", user_name]) and scoped(:conditions => ["user_name = ? AND password = ?", user_name, password]) + # respectively. + # + # Each dynamic finder, scope or initializer/creator is also defined in the class after it is first invoked, so that future # attempts to use it do not run through method_missing. def method_missing(method_id, *arguments, &block) if match = DynamicFinderMatch.match(method_id) @@ -1914,6 +1921,22 @@ module ActiveRecord #:nodoc: }, __FILE__, __LINE__ send(method_id, *arguments, &block) end + elsif match = DynamicScopeMatch.match(method_id) + attribute_names = match.attribute_names + super unless all_attributes_exists?(attribute_names) + if match.scope? + self.class_eval %{ + def self.#{method_id}(*args) # def self.scoped_by_user_name_and_password(*args) + options = args.extract_options! # options = args.extract_options! + attributes = construct_attributes_from_arguments( # attributes = construct_attributes_from_arguments( + [:#{attribute_names.join(',:')}], args # [:user_name, :password], args + ) # ) + # + scoped(:conditions => attributes) # scoped(:conditions => attributes) + end # end + }, __FILE__, __LINE__ + send(method_id, *arguments) + end else super end diff --git a/activerecord/lib/active_record/dynamic_scope_match.rb b/activerecord/lib/active_record/dynamic_scope_match.rb new file mode 100644 index 0000000000..f796ba669a --- /dev/null +++ b/activerecord/lib/active_record/dynamic_scope_match.rb @@ -0,0 +1,25 @@ +module ActiveRecord + class DynamicScopeMatch + def self.match(method) + ds_match = self.new(method) + ds_match.scope ? ds_match : nil + end + + def initialize(method) + @scope = true + case method.to_s + when /^scoped_by_([_a-zA-Z]\w*)$/ + names = $1 + else + @scope = nil + end + @attribute_names = names && names.split('_and_') + end + + attr_reader :scope, :attribute_names + + def scope? + !@scope.nil? + end + end +end |