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.