我第一次使用has_many,尽管在guide中阅读了大量内容,但我并不了解访问通过表中属性的正确方法。我的表与另一篇文章中的这个例子相同。
class Product < ActiveRecord::Base
has_many :collaborators
has_many :users, :through => :collaborators
end
class User < ActiveRecord::Base
has_many :collaborators
has_many :products, :through => :collaborators
end
class Collaborator < ActiveRecord::Base
belongs_to :product
belongs_to :user
end
假设协作者表有其他属性,比如hours_spent,从协作者表中为特定用户和产品查找hours_spent的正确方法是什么?
当我通过产品找到我的用户,并按照
进行迭代 @product.users.each do |user|
这似乎有效
user.collaborator[0].hours_spent
我得到了正确的值,但由于每个用户/产品对只应该有一个协作者记录,索引会让我失望,让我觉得我做错了。
感谢您的阅读!
修改
也许我没有通过概念获得has_many。也许MySQL的例子会有所帮助。
我在想的是,如果我做了
SELECT * FROM collaborators where user_id = 1;
我希望得到一组(零或更多)作为结果。同样
SELECT * FROM collaborators where product_id = 1;
也会给我一套,但是
SELECT * FROM collaborators where user_id = 1 and product_id = 1;
最多会给出1行。
如果我理解正确,则所有3个查询都返回一组。所以我想我需要某种唯一性约束,但这必须是两种属于键的复合键。这甚至可能吗?有没有更好的模型这个结构?
非常感谢快速而有用的回复!
答案 0 :(得分:0)
每对可能只有一个数据库行,但在考虑单个用户时,该用户可以与许多产品相关联,因此用户可以在协作者表中拥有多行。同样,在考虑单个产品时,该产品可以与许多用户关联,因此产品可以在协作者表中包含许多行。
此外,如果您只想要第一个协作者花费的时间,请使用user.collaborators[0].hours_spent
(可能会返回null),而不是使用user.collaborators.first.try(:hours_spent)
。
如果一个用户只能拥有一个产品,而一个产品只能拥有一个用户,那么就可以将has_many的所有内容切换为has_one's。
更新:前面是原始问题的答案,后来通过评论澄清了。请参阅注释以获取详细信息,并查看Peter对其他答案的评论。
答案 1 :(得分:0)
也许您应该使用 has_and_belongs_to_many 。如果您的Collaborator仅用于在用户和产品之间建立链接而不需要更多字段。
class Product < ActiveRecord::Base
has_and_belongs_to_many :users
end
class User < ActiveRecord::Base
has_and_belongs_to_many :products
end
迁移之间的beet:
class CreateUsersProducts < ActiveRecord::Migration
def change
create_table "users_products", :id => false do |t|
t.integer :user_id
t.integer :product_id
end
end
end
答案 2 :(得分:0)
实现之后,我发现我认为我有正确的关系设置,我不得不使用has_many:虽然用户可能有很多产品,但它需要:通过因为还有其他属性合作者表。关键是如何实现每个用户/产品对的单一协作者记录,然后我如何保证得到它。到目前为止,我发现答案是必须在代码中完成。
为了确保每对只有一条记录,我使用了
class Collaborator < ActiveRecord::Base
validates :product_id, :presence => true, :uniqueness => {:scope => [:user_id], :message => "This is a duplicate join"}
然后再加倍确定我找到了正确的记录,我有一个范围
scope :collaboration_instance, lambda {|p_id, u_id| where("collaborations.product_id = ? && collaborations.user_id = ?", p_id, u_id)}
如果某人有更优雅的解决方案,或者只想改进这个解决方案,请发帖,我会将您的更改为所选答案。