2个用户之间的产品订单

Ale*_*ara 5 ruby ruby-on-rails relationship belongs-to

我有三个模型:用户,产品,优惠以及这些模型之间关系的问题.

场景:

用户1发布产品

用户2可以向用户1发送价格为10美元的报价

用户1可以接受或拒绝该优惠

我现在的问题是:

用户,产品和优惠之间的正确关系是什么?

我该如何处理这些"接受或拒绝"的行为?

可能有更好的解决方案吗?

用户模型:

class User < ActiveRecord::Base
    attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :avatar, :screen_name
    has_many :products
    has_many :offers,:through => :products
end
Run Code Online (Sandbox Code Playgroud)

产品型号:

class Product < ActiveRecord::Base
    attr_accessible :content, :price, :title, :tag_list, :productimage, :user_id
    belongs_to :user
    has_many :offers, :through => :users
end
Run Code Online (Sandbox Code Playgroud)

优惠型号:

class Offer < ActiveRecord::Base
    attr_accessible :offer_price, :status, :user_id, :product_id
    has_many :products
    has_many :users, through: :products
end
Run Code Online (Sandbox Code Playgroud)

提前致谢 :)

编辑:

我正在使用Rails 3.2.8

And*_*nes 6

警告:这是一本小小说.

第1部分:建立关联

我建议彻底阅读关于关联Rails指南,给它添加书签,然后重新阅读,因为这是正确理解的关键,并且可能有点棘手 - 一旦超出基本关联,有很多选项.

关于您的应用,需要注意的一点是,您的用户有两个角色,买家和卖家.你将需要小心你的协会的名称-不@user.offers返回用户的提议作出,或用户已经报价收到?您可能希望能够将这两个列表放在用户的配置文件中.

您描述的基本关系非常简单:

  • 用户可以销售许多产品,User has_many :products以及Product belongs_to :user

  • 用户可以提供很多优惠,User has_many :offers以及Offer belongs_to :user

  • 产品可以得到很多优惠,让Product has_many :offersOffer belongs_to :product

这一切都很好,你可以做到这一点 - 在这种情况下,你可以跳到第2部分:)

但是,一旦你开始尝试添加through关系,水就会变得混乱.毕竟,

  • Offer belongs_to :user (买方),但它也有用户通过产品(卖方)

  • User has_many :products (他们正在销售),但他们也有许多产品通过报价(他们正在购买 - 好吧,试图购买).

Aargh,令人困惑!

当您需要该: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
Run Code Online (Sandbox Code Playgroud)

但如果你重新命名user_idseller_idproducts表,buyer_idoffers表中,你就不需要这些:foreign_key选项.

第2部分:接受/拒绝要约

有很多方法可以解决这个问题.我会把一个布尔字段accepted打开Offer,然后你可以有类似的东西

# Offer
def accept
  self.accepted = true
  save
end

def reject
  self.accepted = false
  save
end
Run Code Online (Sandbox Code Playgroud)

你可以找到优秀的报价(哪里accepted是null)

scope :outstanding, where(accepted: nil)
Run Code Online (Sandbox Code Playgroud)

要在控制器中发生接受/拒绝逻辑,您可以考虑添加新的RESTful操作(链接指南是另一个值得仔细阅读的指南!).你应该找到像这样的一行

resources :offers
Run Code Online (Sandbox Code Playgroud)

在配置/ routes.rb中,它提供了标准的动作index,show,edit,等,您可以将其更改为

resources :offers do
  member do
    post :accept
    post :reject
  end
end
Run Code Online (Sandbox Code Playgroud)

并把这样的东西放在你的 OffersController

def accept
  offer = current_user.offers_received.find(params[:id])
  offer.accept
end

# similarly for reject
Run Code Online (Sandbox Code Playgroud)

然后,您可以发出POST请求offers/3/accept,这将导致接受ID为3的商品.视图中的这样的东西应该这样做:

link_to "Accept this offer", accept_offer_path(@offer), method: :post 
Run Code Online (Sandbox Code Playgroud)

请注意,我不只是写,Offer.find(params[:id])因为一个狡猾的用户可以代表卖家接受报价.请参阅Rails最佳实践.