2012-10-15 32 views
5

मेरे पास तीन मॉडल हैं: उपयोगकर्ता, उत्पाद, प्रस्ताव और इन मॉडलों के बीच संबंधों में समस्या।2 उपयोगकर्ताओं के बीच उत्पाद आदेश

परिदृश्य:

उपयोगकर्ता 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 

उत्पाद मॉडल:

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

ऑफर मॉडल:

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

अग्रिम धन्यवाद :)

संपादित करें:

मैं रेल उपयोग कर रहा हूँ 3.2.8

उत्तर

5

चेतावनी: यहां एक छोटा उपन्यास आता है।

भाग 1: संघों

मैं पूरी तरह Rails guide on associations पढ़ने, यह बुकमार्क की सलाह देते हैं, और इसे फिर से पढ़ने की स्थापना, क्योंकि इस को ठीक से समझने के लिए एक महत्वपूर्ण बात यह है, और थोड़ा मुश्किल हो सकता है - बुनियादी संगठनों से परे जाने के बाद कई विकल्प हैं।

आपके ऐप के बारे में ध्यान देने योग्य एक बात यह है कि आपके उपयोगकर्ताओं के पास दो भूमिकाएं, खरीदारों और विक्रेता हैं। आपको अपने संगठनों के नाम से सावधान रहने की आवश्यकता होगी - @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 रिश्ते पानी को गंदे होने जा रहे हैं। सभी,

  • Offer belongs_to :user (खरीदार), लेकिन यह भी उत्पाद के माध्यम से एक उपयोगकर्ता है (विक्रेता) के बाद

  • User has_many :products (कि वे बेच रहे हैं), लेकिन वे भी कई उत्पाद प्रदान करता है के माध्यम से (कि वे खरीद रहे हैं - ठीक है, खरीदने की कोशिश कर रहे हैं)।

आर्ग, उलझन में!

यह वह बिंदु है जब आपको :class_name विकल्प की आवश्यकता होती है, जो आपको उस वर्ग के लिए अलग-अलग एसोसिएशन का नाम देता है, और :source विकल्प, जो आपको 'से' मॉडल पर संगठनों को अलग-अलग ' ' आदर्श।

तो तुम तो इस तरह अपने संगठन बनाते हैं हो सकता है:

# 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 

हालांकि अगर आप offers तालिका में products तालिका में seller_id, और buyer_id करने के लिए अपने user_id कॉलम का नाम बदला, तो आप की जरूरत नहीं होगी उन :foreign_key विकल्प ।

भाग 2: को स्वीकार/खारिज प्रस्तावों

तरीके इस से निपटने के लिए की एक संख्या है। मैं Offer पर एक बूलियन क्षेत्र accepted रखा और फिर आप की तरह

# Offer 
def accept 
    self.accepted = true 
    save 
end 

def reject 
    self.accepted = false 
    save 
end 

कुछ हो सकता था और आप बकाया ऑफर मिल सकता है (जहां accepted रिक्त है)

scope :outstanding, where(accepted: nil) 

प्राप्त करने के लिए स्वीकार/अस्वीकार तर्क नियंत्रक में हो रहा है, आप adding new RESTful actions पर विचार कर सकते हैं (लिंक की गई मार्गदर्शिका पूरी तरह से पढ़ने योग्य है!)। आप index, show, edit, आदि आप इसे

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

को बदल सकते हैं और कुछ इस तरह रख सकते हैं जैसे

resources :offers 
config में

/routes.rb एक लाइन है, जो मानक कार्यों प्रदान करता है खोजने चाहिए अपने OffersController

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

# similarly for reject 

में तो फिर तुम offers/3/accept करने के लिए एक पोस्ट अनुरोध जारी कर सकते हैं और यह wil मैं आईडी 3 के साथ प्रस्ताव स्वीकार किया जाना है। एक दृश्य में कुछ इस तरह यह करना चाहिए:

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

ध्यान दें कि मैं सिर्फ Offer.find(params[:id]) नहीं लिखा था क्योंकि तब एक चालाक उपयोगकर्ता विक्रेता की ओर से प्रस्तावों को स्वीकार कर सकता है। Rails Best Practices देखें।

+0

आपके उत्तर के लिए धन्यवाद। मुझे लगता है कि यह काम करता है :) मैं अन्य विकल्पों का परीक्षण करूंगा। एक और सवाल: मैं इसे अपने ऑफ़र नियंत्रक में कैसे जोड़ सकता हूं? इन नोब सवालों के लिए खेद है लेकिन मैं अभी भी सीख रहा हूं। –

+0

कोई समस्या नहीं, यह एक अच्छा सवाल है! मैंने इसे समझाने के लिए अपना जवाब अपडेट कर दिया है। –

+0

मुझे इस माइग्रेशन को देखने में परेशानी हो रही है। क्या ऑफर टेबल में 'user_id' और 'product_id' के लिए एक विदेशी कुंजी होनी चाहिए? – sabaeus

2

कैसे के बारे में

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 

अपने परिदृश्य के लिए:

# 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' 

आप इस अपनी आवश्यकताओं पर निर्भर करता है और परिशोधित कर सकते हैं - उदा यदि एक ही उत्पाद विभिन्न उपयोगकर्ताओं द्वारा पोस्ट किया जा सकता है।

4

संबंधों को छोड़कर आपके मॉडल पर्याप्त अच्छे हैं। भ्रम तब शुरू होता है जब आप स्वामित्व वाले उत्पादों बनाम रुचि वाले उत्पादों (प्रस्तावित) और उत्पाद मालिक बनाम रुचि रखने वाले उपयोगकर्ताओं (उपयोगकर्ताओं को जो प्रस्ताव देते हैं) को अलग करने की कोशिश कर रहे हैं। यदि आप एक बेहतर नामकरण सम्मेलन के साथ आ सकते हैं, तो आप इसे आसानी से ठीक कर सकते हैं।

1. बेहतर संबंधों

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 

इन संबंधों मुझे लगता है कि आप सभी बुनियादी जानकारी आप रुचि होगी प्राप्त कर सकते हैं के साथ। उदाहरण के लिए,

@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. हैंडलिंग स्वीकार या अस्वीकार करती कार्रवाई।

आपके विवरण से, मुझे लगता है कि एक प्रस्ताव में 2 संभव राज्य परिवर्तन हो सकते हैं, "बनाया गया" -> "स्वीकार करें" या "बनाया गया" -> अस्वीकार करें। मेरा सुझाव है कि आप state_machine देखें।राज्य मशीन अपने मॉडल में अपने सहायक तरीकों के साथ अच्छा स्वाद जोड़ देगा, जो मुझे लगता है कि आपके मामले में बहुत उपयोगी होगा। तो अपने Offer मॉडल कुछ इस तरह,

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 

मुझे आशा है कि यह आप एक बेहतर तस्वीर देता दिखेगा।