Rails:仅使用连接表进行多对多展平 [英] Rails: Many-to-many flattening with only the join table
问题描述
我有一个模型对象,它以多对多关系链接到国家/地区列表.这些国家/地区以它们的 ISO 3166 alpha-2 代码为键.
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.
我想要完成的事情是保存使用 Country 类和表,并且只有我的对象具有 object.countries
形式的访问器,它将返回一个数组字符串,例如:["IL", "US", "IT", ... ]
.
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", ... ]
.
本质上,一种只有连接表的 has_and_belongs_to_many
操作.这可能吗?
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?
推荐答案
这就是我最终解决的方法,我在数据库中创建了一个国家表,因为我更喜欢 HABTM 关系.
This is how I eventually solved it, I created a countries table in the database, as I preferred a HABTM relationship.
但为了简化事情,我覆盖了集合上的 <<
操作符,这样我就可以将国家代码作为字符串或字符串数组推送 (object.country <<'IL'
):
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
您可能会认出 此处.
传递 concat(*countries)
还可以让 Rails 在单个事务中插入所有行,这是一个很好的奖励.
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.
这篇关于Rails:仅使用连接表进行多对多展平的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!