9

Wondering if there is an easy way to determine dynamically if a model's association is a "has_one" or "has_many" relationship (i.e. is this an association to one object or many).

I'm using MongoMapper, so I am able to check if a class klass has an associated model assoc with a one or many relationship via

klass.associations[:assoc].is_a? MongoMapper::Plugins::Associations::OneAssociation
klass.associations[:assoc].is_a? MongoMapper::Plugins::Associations::ManyAssociation

but this seems rather clunky, and isn't generic (i.e. won't work for ActiveRecord associations as well). I'd also like to avoid loading any objects, so I'm pretty sure that instance.assoc.is_a? Array is out too.

Any ideas?

pariser
  • 275
  • 3
  • 10
  • Ever figure this one out? I just came to find the same thing, but just for `ActiveRecord` – MCB Nov 21 '13 at 20:20

1 Answers1

12

UPDATE: So, I happened upon the Reflections Class methods http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html

You can get all the has_many, belongs_to, etc. with reflect_on_all_associations method. It's all in there. Or you can put in an association into reflect_on_association and it will tell you if it is a has_many, has_one, etc. Specifically:

Model.reflect_on_association(:assoc).macro

This should be sufficient for all cases. It doesn't actually solve the problem I'm currently working on, but it should solve this.

MCB
  • 2,021
  • 1
  • 18
  • 32
  • It's not perfect, but it can work depending on your class names. Consider a class `User` which `has_one` of another class named `UserAttributes`. Unfortunately you'd access this via `user.user_attributes` which returns false to the `respond_to?(assoc_name.singularize)` call. You might argue (and you'd probably be correct) that you should rename this class `UserAttributeSet` or something similar, in which case `singularize` would work, but there's no guarantee that you'll get the association type correct just by whether the instance name is singular or plural. – pariser Nov 22 '13 at 19:33
  • Well, having a pluralized model name would go against Rails naming convention (http://itsignals.cascadia.com.au/?p=7), so you should never have a model UserAttributes. It should always be UserAttribute. So singular or plural should reflect a has_one or has_many relationship. Any other concerns should be handled in whatever logic gets the input to begin with. – MCB Nov 22 '13 at 21:59
  • 1
    Indeed you're right - here's the better way to demonstrate that this doesn't cover every case: Consider the model `Fish` where the association name `"fish"` is uncountable. This means that the word "fish" is both the singular and plural form of the noun (i.e. `"fish".singularize == "fish".pluralize`), so via this means you don't know whether a model `has_one :fish` or `has_many :fish`. – pariser Dec 04 '13 at 17:06
  • Yeah, but that's a pretty unique case. You have that and deer and I can't even think of another example off the top of my head. And as a rule of thumb I wouldn't name a table with an irregular word that is the same singular or plural unless I absolutely had to just to avoid edge cases. – MCB Dec 04 '13 at 21:04