On Friday 02 March 2007, Eric Northam wrote:> I was looking through the code of attachment_fu and came across the
> following block pulled from attachment_fu:60
>
> with_options :foreign_key => ''parent_id'' do |m|
> m.has_many :thumbnails, :dependent => :destroy, :class_name =>
> options[:thumbnail_class].to_s
> m.belongs_to :parent, :class_name => base_class.to_s
> end
>
> I''ve never seen with_options called without being tied to a map,
e.g.
> map.with_options, so I opened up the with_options code to see what
> was going on and with my newbie Ruby knowledge can''t seem to
figure
> this one out.
with_options is general, not tied to map/routes. Think of it as a
decorator (http://en.wikipedia.org/wiki/Decorator_pattern) or AOP-style
before advice. Its sole assumption is that the last argument of any
method of the decorated object takes an options hash.
When used as map.with_options { ... } it is the map object that is
decorated. When no receiver is explicitly given, self is decorated in
the block.
> Here''s the object extension in ActiveSupport that gets called
>
> def with_options(options)
> yield ActiveSupport::OptionMerger.new(self, options)
> end
>
> That seems straight forward but the OptionMerger boggles me.
Here''s
> the full module
>
> module ActiveSupport
> class OptionMerger #:nodoc:
> instance_methods.each do |method|
> undef_method(method) if method !~ /^(__|instance_eval|class)/
> end
>
> def initialize(context, options)
> @context, @options = context, options
> end
>
> private
> def method_missing(method, *arguments, &block)
> merge_argument_options! arguments
> @context.send(method, *arguments, &block)
> end
>
> def merge_argument_options!(arguments)
> arguments << if arguments.last.respond_to? :to_hash
> @options.merge(arguments.pop)
> else
> @options.dup
> end
> end
> end
> end
>
> I take it that the object is initialized and then the instance
> methods are iterated over undeffing methods that don''t match the
give
> regex. Why? I don''t know.
Because that ensures that the existing instance methods that plain Ruby
objects come with don''t get in the way. Therefore, when you call a
method on an OptionMerger instance, its method_missing method is
called, which in turn merges the common options, defined in the
enclosing with_options call, into the options of the current call and
delegates to the real receiver.
> The instance_methods method would also just
> apply to the OptionMerger class methods right?
Yes.
> I also don''t see how the private methods are called.
method_missing is called by the Ruby runtime, not explicitly.
HTH,
Michael
--
Michael Schuerig
mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org
http://www.schuerig.de/michael/
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---