Module: SugarCRM::FinderMethods::ClassMethods
- Defined in:
- lib/sugarcrm/finders/finder_methods.rb
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_id, *arguments, &block) ⇒ Object (private)
Enables dynamic finders like find_by_user_name(user_name)
and find_by_user_name_and_password(user_name, password)
that are turned into find(:first, :conditions => ["user_name = ?", user_name])
and find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password])
respectively. Also works for find(:all)
by using find_all_by_amount(50)
that is turned into find(:all, :conditions => ["amount = ?", 50])
.
It’s even possible to use all the additional parameters to find
. For example, the full interface for find_all_by_amount
is actually find_all_by_amount(amount, options)
.
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.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/sugarcrm/finders/finder_methods.rb', line 161 def method_missing(method_id, *arguments, &block) if match = DynamicFinderMatch.match(method_id) attribute_names = match.attribute_names super unless all_attributes_exists?(attribute_names) if match.finder? finder = match.finder bang = match.bang? self.class_eval " def self.\#{method_id}(*args)\n options = args.extract_options!\n attributes = construct_attributes_from_arguments(\n [:\#{attribute_names.join(',:')}],\n args\n )\n finder_options = { :conditions => attributes }\n validate_find_options(options)\n\n \#{'result = ' if bang}if options[:conditions]\n with_scope(:find => finder_options) do\n find(:\#{finder}, options)\n end\n else\n find(:\#{finder}, options.merge(finder_options))\n end\n \#{'result || raise(RecordNotFound, \"Couldn\\'t find \#{name} with \#{attributes.to_a.collect {|pair| \"\#{pair.first} = \#{pair.second}\"}.join(\\', \\')}\")' if bang}\n end\n EOS\n send(method_id, *arguments)\n elsif match.instantiator?\n instantiator = match.instantiator\n self.class_eval <<-EOS, __FILE__, __LINE__ + 1\n def self.\#{method_id}(*args)\n attributes = [:\#{attribute_names.join(',:')}]\n protected_attributes_for_create, unprotected_attributes_for_create = {}, {}\n args.each_with_index do |arg, i|\n if arg.is_a?(Hash)\n protected_attributes_for_create = args[i].with_indifferent_access\n else\n unprotected_attributes_for_create[attributes[i]] = args[i]\n end\n end\n\n find_attributes = (protected_attributes_for_create.merge(unprotected_attributes_for_create)).slice(*attributes)\n\n options = { :conditions => find_attributes }\n\n record = find(:first, options)\n\n if record.nil?\n record = self.new(unprotected_attributes_for_create)\n \#{'record.save' if instantiator == :create}\n record\n else\n record\n end\n end\n EOS\n send(method_id, *arguments, &block)\n end\n else\n super\n end\nend\n", __FILE__, __LINE__ + 1 |