How to get more informations about an association at runtime


#1

Hi all

I’m working on a Custom Formbuilder. I want it to create me with a
single method call checkboxes for a given HABTM association.

My model looks like this:

class Member < ActiveRecord::Base has_and_belongs_to_many :preferred_music_styles, :class_name => 'MusicStyle', :join_table => 'members_have_preferred_music_styles' end

In my view I’d like to do the following:

<%= form.checkboxes :preferred_music_styles %>

The method checkboxes() should now create a set of checkboxes; one for
each music style.

But for doing this I have to get more informations about the
“preferred_music_styles” association:

  1. Does the association exist anyway?
  2. Is it a HABTM association anyway?
  3. If so, which class (MusicStyle) does it connect to?

I sadly have no idea how to accomplish this task. I’d be very happy if
some could give me a useful hint where to achieve this information. :slight_smile:

Thanks
Josh


#2

On Mar 18, 2007, at 10:49 AM, Joshua M. wrote:

  1. Does the association exist anyway?
  2. Is it a HABTM association anyway?
  3. If so, which class (MusicStyle) does it connect to?

I sadly have no idea how to accomplish this task. I’d be very happy if
some could give me a useful hint where to achieve this
information. :slight_smile:

The key is

model.class.reflect_on_association(association)

Have a look at the classes

ActiveRecord::Reflection::MacroReflection
ActiveRecord::Reflection::AggregateReflection
ActiveRecord::Reflection::AssociationReflection

for API to query the association, they live in

activerecord/lib/active_record/reflection.rb

– fxn


#3

The key is

model.class.reflect_on_association(association)

Thanks a lot, that’s very helpful. :slight_smile:
What’s the difference between @class_name=“MusicStyle” and
@klass=MusicStyle though?

I’m stuck right now with another problem:
I need to access the @member object from within my form builder method.
Using self.object_name I get “member”, but self.object returns nil. Am I
looking at the wrong place?


#4

On Mar 18, 2007, at 2:17 PM, Joshua M. wrote:

The key is

model.class.reflect_on_association(association)

Thanks a lot, that’s very helpful. :slight_smile:
What’s the difference between @class_name=“MusicStyle” and
@klass=MusicStyle though?

In the first assignement there’s a string that holds the name of a
class. In the second one there’s a constant whose value is the very
class, that is, an instance of the class Class.

I’m stuck right now with another problem:
I need to access the @member object from within my form builder
method.
Using self.object_name I get “member”, but self.object returns nil.
Am I
looking at the wrong place?

The incantation is:

real_object = @template.instance_variable_get("@#{@object_name}")

– fxn


#5

The incantation is:

real_object = @template.instance_variable_get("@#{@object_name}")

– fxn

I am really thankful for your help. I’ve got my method so far:

def checkboxes(assoc_name, options = {})
model = @template.instance_variable_get("@#{@object_name}")
association = model.class.reflect_on_association(assoc_name)
raise “A has_and_belongs_to_many association is needed
(#{association.macro} given)!” unless association.macro ==
:has_and_belongs_to_many
src = [] # Will hold the HTML code for a checkbox per entry
MusicStyle.find(:all).each do |r|
name_param = @object_name.to_s + ‘[’ + assoc_name.to_s + ‘_ids][]’
value_param = r.id
checked_param = model.send(assoc_name).include?®
src << # What to do here?
end
src.join
end

I don’t know if all the xxx_param vars have a correct value, but anyway
I don’t know how to create the checkbox in a clean way…

A method “check_box_tag” is not recognized by the form builder, so what
to do? I have modified the “check_box” method so it outputs some HTML,
but I don’t want to use it because I need just plain checkboxes.

What to do?


#6

On Mar 18, 2007, at 4:00 PM, Xavier N. wrote:

I’m stuck right now with another problem:
I need to access the @member object from within my form builder
method.
Using self.object_name I get “member”, but self.object returns
nil. Am I
looking at the wrong place?

The incantation is:

real_object = @template.instance_variable_get("@#{@object_name}")

Let me add a comment to that.

The object the form builder is acting upon is not known by the form
builder itself, I see no API for that in the current implementation.
The default form builder is just a thin wrapper over regular form
helper methods, and the logic to figure that out is encapsulated there.

Form builders can optionally receive a second argument with the
object itself (passed to form helpers via :object), so the logic to
get the actual object would be

actual_object = object.nil? ?
@template.instance_variable_get("@#{object_name}") :
object

– fxn


#7

Oh, yet another small question:

I just realized that the checkbox needs a name in the following style:

member[preferred_music_style_ids][]

But whether do I really get why the habtm-name (preferred_music_styles)
is singularized here nor do I see where to get this required form of the
name from.

At the moment I hacked it together using

name_param = @object_name.to_s + ‘[’ + assoc_name.to_s.singularize +
‘_ids][]’

(using the singularize method), but I guess this is not very clean, is
it? Or is it always just the singularized form, also when e.g. the
singular and plural forms are the same?


#8

Well that’s interesting. Why is the object itself not mandatory and the
form could evaluate the type class of the object itself? Supplying the
type AND the object both seems a bit redundant to me…?