2012-10-15 29 views
5

Tôi có ba kiểu: Người dùng, Sản phẩm, Ưu đãi và sự cố với mối quan hệ giữa các mô hình này.Đơn đặt hàng sản phẩm giữa 2 người dùng

Kịch bản:

User 1 bài viết một sản phẩm

User 2 có thể gửi tài khoản 1 lời đề nghị với mức giá ví dụ như $ 10

User 1 có thể chấp nhận hoặc từ chối lời đề nghị

Câu hỏi của tôi hiện là:

Mối quan hệ đúng đắn giữa Người dùng, Sản phẩm và Ưu đãi là gì?

Tôi làm cách nào để xử lý các hành động "chấp nhận hoặc từ chối" đó?

Có thể có giải pháp tốt hơn không?

model User:

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 

mô hình sản phẩm: mô hình

class Product < ActiveRecord::Base 
    attr_accessible :content, :price, :title, :tag_list, :productimage, :user_id 
    belongs_to :user 
    has_many :offers, :through => :users 
end 

Offer:

class Offer < ActiveRecord::Base 
    attr_accessible :offer_price, :status, :user_id, :product_id 
    has_many :products 
    has_many :users, through: :products 
end 

Cảm ơn trước :)

EDIT:

Tôi đang sử dụng Rails 3.2.8

Trả lời

5

Cảnh báo: ở đây có một cuốn tiểu thuyết nhỏ.

Phần 1: thành lập các hiệp hội

tôi khuyên bạn nên đọc Rails guide on associations kỹ lưỡng, đánh dấu nó, và đọc nó một lần nữa, bởi vì đây là một điều quan trọng để hiểu đúng, và có thể là một chút khôn lanh - có rất nhiều tùy chọn khi bạn vượt ra ngoài các liên kết cơ bản.

Một điều cần lưu ý về ứng dụng của bạn là người dùng của bạn có hai vai trò, người mua và người bán. Bạn sẽ cần phải cẩn thận với tên của các hiệp hội của bạn - Không @user.offers trả lại phiếu mua hàng mà người dùng có được thực hiện hoặc phiếu mua hàng mà người dùng có đã nhận được? Bạn có thể muốn đặt danh sách cả hai thứ này vào hồ sơ của người dùng.

Các mối quan hệ cơ bản bạn đang mô tả là khá đơn giản:

  • Một người sử dụng có thể bán nhiều sản phẩm, vì vậy User has_many :productsProduct belongs_to :user

  • Một người sử dụng có thể làm cho nhiều lời đề nghị, vì vậy User has_many :offersOffer belongs_to :user

  • Sản phẩm có thể nhận được nhiều phiếu mua hàng như vậy Product has_many :offersOffer belongs_to :product

Đó là tất cả tốt và tốt, và bạn chắc chắn có thể nhận được bằng cách chỉ làm điều này - trong trường hợp này bạn có thể bỏ xuống Phần 2 :)

Tuy nhiên, ngay sau khi bạn bắt đầu cố gắng thêm through mối quan hệ các vùng biển sẽ nhận được bùn. Sau khi tất cả,

  • Offer belongs_to :user (người mua), nhưng nó cũng có một người dùng thông qua sản phẩm (người bán)

  • User has_many :products (mà họ đang bán), nhưng họ cũng có nhiều sản phẩm thông qua cung cấp (mà họ đang mua - tốt, cố gắng mua).

Aargh, khó hiểu!

Đây là điểm khi bạn cần tùy chọn :class_name, cho phép bạn đặt tên một liên kết khác với lớp mà nó đề cập và tùy chọn :source, cho phép bạn đặt tên cho các liên kết trên mô hình 'từ' khác nhau ' mô hình.

Vì vậy, bạn sau đó có thể hình thành các hiệp hội của bạn như thế này:

# 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 

Mặc dù nếu bạn đã đổi tên user_id cột của bạn để seller_id trong bảng products, và buyer_id trong bảng offers, bạn sẽ không cần những :foreign_key tùy chọn .

Phần 2: chấp nhận/từ chối cung cấp

Có một số cách để giải quyết vấn đề này. Tôi sẽ đặt một lĩnh vực boolean accepted trên Offer và sau đó bạn có thể có một cái gì đó giống như

# Offer 
def accept 
    self.accepted = true 
    save 
end 

def reject 
    self.accepted = false 
    save 
end 

và bạn có thể tìm thấy những cung cấp vượt trội (nơi accepted là null)

scope :outstanding, where(accepted: nil) 

Để có được chấp nhận/từ chối Logic xảy ra trong bộ điều khiển, bạn có thể xem xét adding new RESTful actions (hướng dẫn được liên kết là một hướng dẫn khác đáng đọc kỹ!). Bạn nên tìm một dòng như

resources :offers 

trong config/routes.rb, cung cấp các hoạt động tiêu chuẩn index, show, edit, vv Bạn có thể thay đổi nó để

resources :offers do 
    member do 
    post :accept 
    post :reject 
    end 
end 

và đặt một cái gì đó như thế này trong bạn OffersController

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

# similarly for reject 

Sau đó, bạn có thể đưa ra một yêu cầu POST để offers/3/accept và nó wil l làm cho phiếu mua hàng có id 3 được chấp nhận. Một cái gì đó như thế này trong một cái nhìn nên làm điều đó:

link_to "Accept this offer", accept_offer_path(@offer), method: :post 

Lưu ý rằng tôi không chỉ viết Offer.find(params[:id]) vì sau đó người dùng xảo quyệt có thể chấp nhận cung cấp trên thay mặt cho người bán. Xem Rails Best Practices.

+0

Cảm ơn bạn đã trả lời. Tôi nghĩ rằng công trình này :) Tôi sẽ kiểm tra các tùy chọn khác. Một câu hỏi nữa: Làm thế nào tôi có thể thêm điều này vào bộ điều khiển phiếu mua hàng của tôi? Xin lỗi vì những câu hỏi noob nhưng tôi vẫn đang học. –

+0

Không sao cả, đó là một câu hỏi hay! Tôi đã cập nhật câu trả lời của mình để giải thích. –

+0

Tôi đang gặp sự cố khi trực quan hóa việc di chuyển này. Bảng phiếu mua hàng chỉ có khóa ngoại cho 'user_id' và' product_id'? – sabaeus

2

Làm thế nào về

class User < ActiveRecord::Base 
    has_many :products # All products posted by this user 
    has_many :offers # All offers created by this user 
end 

class Product < ActiveRecord::Base 
    belongs_to :user # This is the user who posts the product (User 1) 
    has_many :offers 
end 

class Offer < ActiveRecord::Base 
    belongs_to :product 
    belongs_to :user # This is the user who creates the offer (User 2) 

    # Use a 'state' field with values 'nil', 'accepted', 'rejected' 
end 

Đối với kịch bản của bạn:

# User 1 posts a product 
product = user1.products.create 

# User 2 can send User 1 an offer with an price e.g $ 10 
offer = user2.offers.create(:product => product) 

# User 1 can accept or reject the offer 
offer.state = 'rejected' 

Bạn có thể tinh chỉnh này tùy thuộc vào nhu cầu của bạn - ví dụ nếu cùng một sản phẩm có thể được đăng bởi những người dùng khác nhau.

4

Mô hình của bạn đủ tốt, ngoại trừ các mối quan hệ. Sự nhầm lẫn bắt đầu khi bạn đang cố gắng phân biệt các sản phẩm thuộc sở hữu với các sản phẩm quan tâm (được cung cấp) và chủ sở hữu sản phẩm so với người dùng quan tâm (người dùng đã đặt phiếu mua hàng). Nếu bạn có thể đưa ra một quy ước đặt tên tốt hơn, bạn có thể dễ dàng sửa nó.

1. quan hệ tốt hơn

class User < ActiveRecord::Base 
    attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :avatar, :screen_name 
    has_many :owned_products, :class_name => "Product" 
    has_many :offers 
    has_many :interested_products, :through => :offers 
end 

class Offer < ActiveRecord::Base 
    attr_accessible :offer_price, :status, :user_id, :product_id 
    belongs_to :interested_user, :class_name => "User", :foreign_key => :user_id 
    belongs_to :interested_product, :class_name => "Product", :foreign_key => :product_id 
end 

class Product < ActiveRecord::Base 
    attr_accessible :content, :price, :title, :tag_list, :productimage, :user_id 
    belongs_to :owner, :foreign_key => :user_id, :class_name => "User" 
    has_many :offers 
    has_many :interested_users, :through => :offers 
end 

Với những mối quan hệ Tôi nghĩ rằng bạn có thể nhận được tất cả các thông tin cơ bản bạn sẽ quan tâm. Ví dụ,

@product = Product.find(1) 
@product.owner # would give you the user who created the product 
@product.interested_users # would give you users who placed an offer for this product 

@user = User.find(1) 
@user.owned_products # would give you the products created by this user 
@user.interested_products # would give you the products where the user placed an offer 

2. Xử lý chấp nhận và từ chối hành động.

Từ mô tả của bạn, tôi thấy có thể có 2 thay đổi trạng thái có thể cho phiếu mua hàng, "được tạo" -> "chấp nhận" hoặc "đã tạo" -> "từ chối". Tôi đề nghị bạn xem state_machine.Máy nhà nước sẽ thêm hương vị đẹp cho mô hình của bạn với phương pháp trợ giúp của nó, mà tôi nghĩ sẽ rất hữu ích trong trường hợp của bạn. Vì vậy, mô hình Offer của bạn sẽ trông giống như thế này,

class Offer < ActiveRecord::Base 
    # attr_accessible :title, :body 
    attr_accessible :offer_price, :status, :user_id, :product_id 
    belongs_to :interested_user, :class_name => "User", :foreign_key => :user_id 
    belongs_to :interested_product, :class_name => "Product", :foreign_key => :product_id 

    state_machine :status, :initial => :created do 
    event :accept do 
     transition :created => :accepted 
    end 
    event :reject do 
     transition :created => :reject 
    end 
    end 
end 

#cool helper methods 
@offer = Offer.new 
@offer.accepted? #returns false 
@offer.reject #rejects the offer 
@offer.rejected? #returns true 

Tôi hy vọng điều này sẽ mang đến cho bạn một bức tranh đẹp hơn.

Các vấn đề liên quan