Metaprogramming, define_method, and class_eval issues

I have a 2-part question here that’s a little tricky and starting to
make my head hurt.

I’m working on a plugin for personal use, where I have an rclients
table (not named clients because of conflicts with another plugin),
and several other models that can have Rclients (polymorphic
association). I’ve defined a method acts_as_client_entity that will
set up the necessary associations.

Let me first give my functioning code:

############### join model:
class ClientEntityAssociation < ActiveRecord::Base
belongs_to :rclient
belongs_to :entity, :polymorphic=>true
end

################ plugin:
module ClientEntity
module ClassMethods
def acts_as_client_entity

has_many :client_entity_associations, :as=>:entity,
:dependent=>:destroy

has_many :rclients, :through=>
:client_entity_associations

has_one :primary_client, :through=>
:client_entity_associations,
:source
=> :rclient, :conditions=>[“client_entity_associations.primary
= ?”,true]

    klass = self.name.tableize
    Rclient.class_eval

“has_many :#{klass}, :through=>:client_entity_associations”

    define_method("primary_client=") do |rclient|
      client_entity_associations.update_all("`primary` = false")
      assoc =

client_entity_associations.find_by_rclient_id(rclient.id)
if assoc && !assoc.primary
assoc.update_attribute :primary,true
else

client_entity_associations.create(:rclient_id=>rclient.id,:primary=>true)
end
end
end
end
end

The first part of my question is whether there is a way to pass in a
reference to the calling class (klass) without first setting it as a
variable. My understand is that if I used self directly in the
class_eval statement, it would evaluate to Rclient.

The second part of my questions is why I had to use define_method for
primary_client= (as opposed to def primary_client=). I kept getting
conflicts with the dynamic methods rails created from the statement

has_one :primary_client . . .

I would just like to know why define_method seems to be a little more
forceful.

My apologies if this is a little unwieldy of a question, and I’m open
to any comments/criticism on the general approach.

  • kevin

The first part of my question is whether there is a way to pass in a
reference to the calling class (klass) without first setting it as a
variable. My understand is that if I used self directly in the
class_eval statement, it would evaluate to Rclient.

You should use the included callback which includes the class it’s being
included into

http://ruby-doc.org/core/classes/Module.html#M001660

So your acts_as_client_entity should include the module in to the
current
class, then you should do your initialisation in the included method.

The second part of my questions is why I had to use define_method for
primary_client= (as opposed to def primary_client=). I kept getting
conflicts with the dynamic methods rails created from the statement

has_one :primary_client . . .

I would just like to know why define_method seems to be a little more
forceful.

No idea, sorry.

Cheers,

Andy

On Apr 8, 10:32 pm, klochner [email protected] wrote:

The first part of my question is whether there is a way to pass in a
reference to the calling class (klass) without first setting it as a
variable. My understand is that if I used self directly in the
class_eval statement, it would evaluate to Rclient.

Maybe, don’t know off hand.

The second part of my questions is why I had to use define_method for
primary_client= (as opposed to def primary_client=). I kept getting
conflicts with the dynamic methods rails created from the statement

I think the def method is scoping it inside the proc whereas
define_method is actually evaluating it within the context of the
class_eval (and therefore getting defined as an instance method of the
class).

I highly recommend the O’Reilly book, The Ruby P.ming Language
since it gives details about metaprogramming that’s rarely found
elsewhere and organized in the same place. There are stuff about how
to access the variable bindings and may answer your first question as
well.

Ho-Sheng H.
http://hosheng.blogspot.com