Difficulties in understanding Rail-Plugins in depth

Hi,

i try to understand how plugins work in detail.

Often you see stuff like:

class Post < ActiveRecord::Base
acts_as_commentable
end

I wonder what's happen all there.

What kind of language-feature is behind this call "acts_as_commentable" ?
In my opinion you need some kind of extend or include to extend the
functionality of a model. And exactly this is which i found in a file
of the plugin.

http://github.com/jackdempsey/acts_as_commentable/blob/master/lib/commentable_methods.rb

I have found this part:
module Juixe
  module Acts #:nodoc:
    module Commentable #:nodoc:
module ClassMethods
def acts_as_commentable
has_many :comments, :as => :commentable, :dependent => :destroy
include Juixe::Acts::Commentable::InstanceMethods
extend Juixe::Acts::Commentable::SingletonMethods
end
end

Is this where the magic happens? I think so. This is really
ingeniously because you have to just write one line of code to extend
your other Class.

But now - on the core of the whole thing - there is my question: Why
does the Class which calls acts_as_commentable now that he has to
chose exactly this method within module Juixe, within Acts, within
Commentable modules?

Is there a convention for this?

Greetings
Klaus

You'll see why at the bottom of the same file:

    ActiveRecord::Base.send(:include, Juixe::Acts::Commentable)

That module is being included into ActiveRecord::Base, which is the
superclass of Post above, making the method available in that context.
There's nothing particularly special about the name or location of the
module - it's the fact that it's being included that is important.

- James

"What he said" :slight_smile:

Basically it adds an instance method to the ActiveRecord base class, which
in turn lazy-loads the extentions when needed.

I haven't seen a good in-depth treatise on developing plugins. There is
some info in Agile Web Development with Rails, and some in The Rails Way
(Both are excellent books, but I wouldn't buy either for just this -- it's
too high level)

There is a $9 ebook from peepcode that gives some guidelines for building
different kinds of plugins. Again, it's not in depth but it provides the
"pattern" to follow to build different kinds of plugins.

I did one recently to generate CSS rounded divs, it was really
instructional. Generating the CSS and images was easy, figuring out how to
properly extend "stylesheet_link_tag" and the generator commands (and in
fact that I had to do that to get the right behavior) was a fun puzzle to
work out.

Best bet would be to try writing one yourself. You'll end up reading
helpful bits on stackoverflow and other places, poking into existing plugins
and eventually learning how some of Rails works internally.

Joe

The techniques used fall into what tends to be called Ruby Metaprogramming.

The pragmatic programmers have a series of screen casts by Dave Thomas
on this subject as well as a book called Metaprogramming Ruby which is
either in the late stages of beta or already released.

Actually not exactly. The crucial missing piece is this which comes
just before the module ClassMethods line:

    def self.included(base)
        base.extend ClassMethods
     end

This overrides the Module#included 'hook' method, which gets called
when another class or module includes Juixe::Acts::Commentable, the
extend makes methods defined in ClassMethods just that class methods
of the including class. In this case that's the acts_as_commentable
method.

That method when called to make a particular subclass of
ActiveRecord::Base act as commentable

  * calls the class method has_many to 'declare' the needed
association, note that the Rails/ActiveRecord internal dsl statements
are implemented using the same pattern.
  * includes a module which defines the two instance methods
comments_ordered_by_submitted, and add_comment
  * uses extend to add the find_comments_for and find_comments_by_user
as class methods.

So any subclass of ActiveRecord::Base can use acts_as_commentable, and
those that do get additional instance and class methods, and an
association.

This overrides the Module#included 'hook' method, which gets called
when another class or module includes Juixe::Acts::Commentable, the
extend makes methods defined in ClassMethods just that class methods
of the including class. In this case that's the acts_as_commentable
method.

That method when called to make a particular subclass of
ActiveRecord::Base act as commentable

Thank you very much! This was more explanation as I hoped to get :slight_smile:

Thanks also everybody else and thanks for the book-advice. This pdf is
exactly what I am looking for.