Module: ActsAsStaticRecord::DefineFinderMethods

Defined in:
lib/acts_as_static_record.rb

Overview

This module is designed to define finder methods such as find_by_id to search through the cache if no additional arguments are specified The likelyhood of this working with < Rails 2.3 is pretty low.

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_id, *arguments, &block) ⇒ Object

Method missing is overridden to use cache calls for finder methods



485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# File 'lib/acts_as_static_record.rb', line 485

def method_missing(method_id, *arguments, &block)#:nodoc:

  # If the missing method is  XXX_without_static_rc, define XXX
  # using the superclass ActiveRecord::Base method_missing then
  # Finally, alias chain it to XXX_with_static_rc
  if ((match = method_id.to_s.match(/(.*)_without_static_rc$/)) &&
      (base_method_id = match[1]))
    begin
      return super(base_method_id, *arguments, &block)
    ensure
      define_static_rc_alias(base_method_id)
    end
  end

  # If the missing method is a finder like find_by_name
  # Define on the class then invoke find_by_name_with_static_rc
  if match = ActiveRecord::DynamicFinderMatch.match(method_id)
    attribute_names = match.attribute_names
    if all_attributes_exists?(attribute_names) &&  match.finder?
      attributes = construct_attributes_from_arguments(attribute_names, arguments)
      method_name = define_static_record_finder_method(method_id, match.finder, match.bang?, attributes)
      return self.send method_name, *arguments
    end
  end

  #If nothing matches, invoke the super
  super(method_id, *arguments, &block)
end

Instance Method Details

#define_static_rc_alias(base_method_id) ⇒ Object

alias chain the finder method to the static_rc method base_method_id would be like find_by_name



435
436
437
438
439
440
441
442
# File 'lib/acts_as_static_record.rb', line 435

def define_static_rc_alias(base_method_id)#:nodoc:
  if !respond_to?("#{base_method_id}_without_static_rc") &&
      respond_to?(base_method_id) && respond_to?("#{base_method_id}_with_static_rc")

      klass = class << self; self; end
      klass.class_eval "alias_method_chain :#{base_method_id}, :static_rc"
  end
end

#define_static_record_finder_method(method_id, finder, bang, attributes) ⇒ Object

Define the finder method on the class, and return the name of the method Ex. find_by_id will define find_by_id_with_static_rc

The cache is searched if no additional arguments (:conditions, :joins, etc) are specified If additional arguments do exist find_by_id_without_static_rc is invoked



465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/acts_as_static_record.rb', line 465

def define_static_record_finder_method(method_id, finder, bang, attributes)#:nodoc:
  method_to_call = static_record_finder_method_name(finder, attributes)
  method_with_static_record = "#{method_id}_with_static_rc"

  #override the method to search memory if there are no args
  class_eval %{
    def self.#{method_with_static_record}(*args)
      if (args.dup.extract_options!).any?
         #{method_id}_without_static_rc(*args)
      else
        result = #{method_to_call}
        #{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(\', \')}")' if bang}
      end
    end
  }, __FILE__, __LINE__

  method_with_static_record
end

#static_record_finder_method_name(finder, attributes) ⇒ Object

Retrieve the method name to call based on the attributes Single attributes on primary key or the specified key call directly to the cache All other methods iterate through the cache



447
448
449
450
451
452
453
454
455
456
457
458
# File 'lib/acts_as_static_record.rb', line 447

def static_record_finder_method_name(finder, attributes)#:nodoc:
  method_to_call = "find_in_static_record_cache(#{finder.inspect}, #{attributes.inspect})"
  if attributes.length == 1
    key_value = case attributes.keys.first.to_s
      when self.primary_key then [:primary_key, attributes.values.first.to_i]
      when acts_as_static_record_options[:key] then [:key, attributes.values.first.to_s]
    end

    method_to_call = "static_record_cache[#{key_value[0].inspect}][#{key_value[1].inspect}]" if key_value
  end
  method_to_call
end