警告:这是一本小小说。
第 1 部分:建立协会
我建议彻底阅读有关关联的 Rails 指南,将其添加为书签,然后再阅读一遍,因为这是正确理解的关键,并且可能有点棘手 - 一旦超出了基本关联,就有很多选择。
关于您的应用需要注意的一件事是,您的用户有两个角色,买家和卖家。您将需要小心关联的名称 - 是@user.offers
返回用户提供的报价,还是用户收到的报价?您可能希望能够将这两件事的列表放入用户的个人资料中。
您描述的基本关系相当简单:
一个用户可以销售许多产品,所以User has_many :products
和Product belongs_to :user
一个用户可以提供许多报价,因此User has_many :offers
和Offer belongs_to :user
Product has_many :offers
一个产品可能会收到很多报价Offer belongs_to :product
这一切都很好,你当然可以这样做——在这种情况下,你可以跳到第 2 部分 :)
但是,一旦您开始尝试添加through
关系,水就会变得浑浊。毕竟,
啊,混乱!
这就是您需要:class_name
选项的时候,它可以让您以不同的方式命名关联到它所引用的类,以及该:source
选项,它可以让您在“from”模型上以与“through”模型不同的方式命名关联。
因此,您可能会像这样形成您的关联:
# User
has_many :products_selling, class_name: 'Product'
has_many :offers_received, class_name: 'Offer',
through: :products_selling, source: :offers
has_many :offers_made, class_name: 'Offer'
has_many :products_buying, class_name: 'Product',
through: :offers_made, source: :product
# Product
belongs_to :seller, class_name: 'User', foreign_key: :user_id
has_many :offers
has_many :buyers, class_name: 'User', through: :offers
# Offer
belongs_to :product
belongs_to :buyer, class_name: 'User', foreign_key: :user_id
has_one :seller, class_name: 'User', through: :product
尽管如果您将user_id
列重命名为seller_id
in the products
table 和buyer_id
in the offers
table,则不需要这些:foreign_key
选项。
第 2 部分:接受/拒绝报价
有很多方法可以解决这个问题。我会放一个布尔字段accepted
,Offer
然后你可以有类似的东西
# Offer
def accept
self.accepted = true
save
end
def reject
self.accepted = false
save
end
并且您可以找到未完成的优惠(其中accepted
为空)
scope :outstanding, where(accepted: nil)
要让控制器中发生接受/拒绝逻辑,您可以考虑添加新的 RESTful 操作(链接指南是另一个值得彻底阅读的指南!)。你应该找到像这样的一行
resources :offers
在 config/routes.rb 中,它提供了标准操作index
、show
、edit
等。您可以将其更改为
resources :offers do
member do
post :accept
post :reject
end
end
并把这样的东西放在你的OffersController
def accept
offer = current_user.offers_received.find(params[:id])
offer.accept
end
# similarly for reject
然后你可以发出一个 POST 请求offers/3/accept
,它会导致 id 为 3 的提议被接受。视图中这样的事情应该这样做:
link_to "Accept this offer", accept_offer_path(@offer), method: :post
请注意,我不只是写信Offer.find(params[:id])
,因为狡猾的用户可以代表卖家接受报价。请参阅Rails 最佳实践。