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.
160 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 |
# File 'lib/sugarcrm/finders/finder_methods.rb', line 160 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 <<-EOS, __FILE__, __LINE__ + 1 def self.#{method_id}(*args) options = args.extract_options! attributes = construct_attributes_from_arguments( [:#{attribute_names.join(',:')}], args ) finder_options = { :conditions => attributes } validate_find_options(options) #{'result = ' if bang}if options[:conditions] with_scope(:find => finder_options) do find(:#{finder}, options) end else find(:#{finder}, options.merge(finder_options)) end #{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(\', \')}")' if bang} end EOS send(method_id, *arguments) elsif match.instantiator? instantiator = match.instantiator self.class_eval <<-EOS, __FILE__, __LINE__ + 1 def self.#{method_id}(*args) attributes = [:#{attribute_names.join(',:')}] protected_attributes_for_create, unprotected_attributes_for_create = {}, {} args.each_with_index do |arg, i| if arg.is_a?(Hash) protected_attributes_for_create = args[i].with_indifferent_access else unprotected_attributes_for_create[attributes[i]] = args[i] end end find_attributes = (protected_attributes_for_create.merge(unprotected_attributes_for_create)).slice(*attributes) options = { :conditions => find_attributes } record = find(:first, options) if record.nil? record = self.new(unprotected_attributes_for_create) #{'record.save' if instantiator == :create} record else record end end EOS send(method_id, *arguments, &block) end else super end end |