Module: QueryableArray::DynamicFinder

Included in:
QueryableArray
Defined in:
lib/queryable_array/dynamic_finder.rb

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *arguments) ⇒ Object

If method_name is a finder? then it creates a search hash by zipping the names of attributes parsed from method_name as keys and arguments as expected values. The search hash is then passed to find_all or find_by depending on what type of method was called.

users = QueryableArray.new User.all, :username

users.find_by_name 'bob'              # => #<User @name='bob'>
users.find_by_name_and_age 'jim', 23  # => #<User @name='jim' @age=23>
users.find_all_by_age 27              # => [#<User @age=27>, #<User @age=27>, ...]

38
39
40
41
42
43
44
45
# File 'lib/queryable_array/dynamic_finder.rb', line 38

def method_missing(method_name, *arguments)
  if query = finder?(method_name)
    search = Hash[query[:attributes].split('_and_').zip(arguments)]
    send "find_#{query[:type].downcase}", search
  else
    super
  end
end

Class Method Details

.included(base) ⇒ Object

Allows objects to be searched by dynamic finders thru method_missing similar to the ActiveRecord dynamic attribute-based finders e.g. find_by_email or find_all_by_last_name


6
7
8
# File 'lib/queryable_array/dynamic_finder.rb', line 6

def self.included(base)
  base.send :alias_method, :find_all_by, :find_all
end

Instance Method Details

#finder?(method_name) ⇒ Boolean

Determines if the method_name passed to it can be parsed into a search hash for finder.

finder? :find_by_name                      # => true
finder? :find_by_first_name_and_last_name  # => true
finder? :find_all_by_last_name             # => true
finder? :find_all_by_last_name_and_city    # => true
finder? :find_by_name_or_age               # => false
finder? :find_first_by_name                # => false
finder? :find_name                         # => false
finder? :some_method                       # => false

Returns:

  • (Boolean)

21
22
23
24
25
26
# File 'lib/queryable_array/dynamic_finder.rb', line 21

def finder?(method_name)
  if match = method_name.to_s.match(/^(find_(by|all_by))_(.+?)([\?\!])?$/i)
    keys = [:method_name, :prefix, :type, :attributes, :suffix]
    Hash[keys.zip match.to_a]
  end
end

#respond_to_missing?(method_name, include_super) ⇒ Boolean

Determines if method_name is a finder? and delegates the call to its superclass Array if it's not.

Returns:

  • (Boolean)

49
50
51
# File 'lib/queryable_array/dynamic_finder.rb', line 49

def respond_to_missing?(method_name, include_super)
  !!finder?(method_name) || super
end