问题
I have a model object which is linked to a list of countries in a many-to-many relationship. The countries are keyed by their ISO 3166 alpha-2 codes.
The thing I'd like to accomplish is to save to use of a Country class and table, and only have my object have an accessor in the form of object.countries that will return an array of strings, e.g: ["IL", "US", "IT", ... ].
Essentially, a sort of has_and_belongs_to_many action with only the join table.
Is this possible?
Is there a best practice in the case of country lists?
回答1:
This is how I eventually solved it, I created a countries table in the database, as I preferred a HABTM relationship.
But to simplify things, I overrode the << operator on the collection so I could just push country codes as string or array of strings (object.country << 'IL'):
has_and_belongs_to_many(:countries) do
def <<(country)
if [*country].all? {|c| c.is_a?(String) }
countries = Country.where(:code => country)
concat(*countries)
else
concat(country)
end
end
end
You might recognize that [*...] trick from here.
Passing concat(*countries) also makes Rails insert all the rows in a single transaction, which is a nice bonus.
And added a function to return a simplified hash of codes to countries:
def countries_hash
return self.countries.map {|c| { c.code => c.name }}.inject({}) {|hash, elem| hash.merge!(elem)}
end
Of course I'd be glad to hear any suggestions.
来源:https://stackoverflow.com/questions/7970965/rails-many-to-many-flattening-with-only-the-join-table