2012-04-11 3 views
2

Ich bin verwirrt darüber, wie ich diesen Anwendungsbereich oder diese Methode machen sollte. Ich habe folgende Verbände:Erstellen einer Methode oder eines Bereichs, um niedrigere Preise anzuzeigen?

Modelle

class User 
    has_many :prices 
    has_many :products, :through => :prices 
    has_many :subscriptions, :foreign_key => :subscriber_id 
end 

class Product 
    has_many :prices 
    has_many :users, :through => :prices 
end 

class Price 
    # Table columns => :product_id, :cost, :user_id 
    belongs_to :user 
    belongs_to :product 
    belongs_to :store 
    has_many :subscriptions, :as => :subscribable 
end 

class Subscription 
    # Table columns => :product_id, :cost, :subscriber_id, :subscribable_id 
    # :subscribable_type 
    belongs_to :subscriber, :class_name => "User" 
    belongs_to :subscribable, :polymorphic => true 
    validates_uniqueness_of :subscribable_id, :scope => 
         [ :subscriber_id, :subscribable_type] 
end 

So soll die Methode sein, so etwas wie:

class Price 

def self.lower_price 
    if self.product_id == self.subscription.product_id 
    if self.cost < self.subscription.cost 
    end 
    end 
end 

end 

Was diese Methode Show zu tun ist wohl nur niedrigere Preise von UserProducts, die zu gehören das gleiche Product wie die Subscription, während sie sich mit den Abonnements price Feld vergleichen, um zu sehen, ob es niedriger ist.

Mache ich das richtig? Was muss behoben werden?


EDIT

class Price < ActiveRecord::Base 
    scope :for_product, lambda { |product_id| where(:product_id => product_id) } 
    scope :cheaper, lambda { |cost| where(["prices.cost < :cost", { :cost => cost } ]) } 
end 

class Subscription < ActiveRecord::Base 

    def cheaper_prices 
    Price.for_product(product_id).cheaper(cost) 
    end 
end 

PrivatePagesController: 

def watch 
@prices = Price.cheaper_prices.paginate(:page => params[:page], :per_page => 20).order('purchase_date DESC') 
end 

This gives me the error: 

NoMethodError in PrivatePagesController#watch 

undefined method `cheaper_prices' for #<Class:0x6f99210> 

Antwort

1

ich dachte, dass Sie eine Website machen, wo Benutzer eingeben Preise, die sie gefunden und abonnieren günstigere Preise zu finden. Ich würde die UserProduct-Entität in Price umbenennen.

Es ist zweideutig, ob Abonnenten ein Produkt oder einen Preis abonnieren. Wenn Sie das aufheben, kann es die polymorphe Assoziation vereinfachen. Nehmen wir an, sie abonnieren ein Produkt mit einem bestimmten Preis. Dann willst du folgendes:

class Price 
    # Table columns => :product_id, :price, :user_id 
    belongs_to :finder, :class_name => "User" 
    belongs_to :product 
    belongs_to :store 

    scope for_product, lambda { |product_id| where(:product_id => product_id) 
    scope cheaper, lambda { |price| where([ "prices.price < :price", {:price => price} ] } 
end 

class Subscription 
    # Table columns => :product_id, :price, :subscriber_id 
    belongs_to :subscriber, :class_name => "User" 
    belongs_to :product 
    validates_uniqueness_of :subscribable_id, :scope => 
         [ :subscriber_id, :subscribable_type] 

    def cheaper 
    Price.for_product(product_id).cheaper(price) 
    end 
end 
+0

Ich bin auch verwirrt wie das weitergeht. Ich musste die 'UserProduct' (oder 'Price') Attribute duplizieren, um dann nach günstigeren Preisen zu suchen. Da die "Subscription" und "Price" dieselben Felder haben, kann ich diese zwei Modelle vergleichen. Das "Abonnement" würde also mit allen "Preisen" verglichen werden. – LearningRoR

+0

Auch Sie haben Recht mit meiner Website. Die Benutzer müssen neue Preise eingeben. Ich habe das Modell geändert, um "Preis" zu sein, also macht es jetzt und in der Zukunft. Vielen Dank. – LearningRoR

+0

Ja. Zuerst habe ich nicht bemerkt, dass die Subscription-Einheit ein Preisfeld hatte. Ich nehme an, dass Sie in Ihrer Benutzeroberfläche das Abonnement erhalten. Mein anderer Ansatz war, dass das Preismodell die Methode hat, die günstigeren Preise zurückzugeben. Mit den in dieser Antwort angegebenen Bereichen kann jedes Objekt, das die Produkt-ID und einen Preis bereitstellen kann, die Bereiche verwenden. –

0

, wenn Sie können davon ausgehen, dass jedes Produkt, das Sie haben, Abonnement als diese hat, sollte für Sie arbeiten

scope :lower_priced_user_products, self.joins("join subscriptions on subscriptions.product_id = user_products.product_id").where("user_products.product_id < subscriptions.product_id") 

dies einen Nur-Lese-Datensatz zurück. Wenn Sie Lese-/Schreibzugriff wünschen, sollten Sie den Datensatz mit UserProduct.find (rec.id) erneut laden.

lassen Sie mich wissen, wie es geht.

1

Als Erstes sollten Sie Ihrer UserProduct-Tabelle einen höheren Stellenwert zuweisen. Ich kann nicht sagen, was Semantik ist, außer als Verknüpfungstabelle.

Es gibt auch einige Verwirrung über das Abonnieren eines Produkts oder eines UserProduct. Ich sehe die polymorphe Assoziation, aber ich vermute, dass es etwas Verwirrung gibt.

Ich bemerke, dass Subskription eine product_id hat, so dass mir sagt Subscription gehört zu Product, anstatt, oder zusätzlich dazu, abonnierbar.

Also, zuerst müssen Sie möglicherweise Ihr Design aufräumen.

jedoch vorausgesetzt, ich Ihre Bedingung auf den Glauben nehmen kann, dass sein, was Sie wollen, was Sie in SQL wollen würde, ist

SELECT cheaper.* 
FROM user_products 
    INNER JOIN subscriptions ON subscribable_type = 'UserProduct' 
          AND subscriptions.subscribable_id = user_products.id 
    INNER JOIN user_products cheaper ON cheaper.product_id = subscriptions.product_id 
WHERE cheaper.price < user_products.price 

Dies würde Sie einen Bericht aller günstigeren Preisen geben Sie insgesamt finden. Für alle günstigeren Preise eines gegebenen user_products-Datensatzes müssen Sie eine Bedingung angeben, die für eine bestimmte ID gilt.

Als nächstes diese Arbeit in Active zu machen, wollen wir die Auswahl für die Klasse auf den Tisch sein, so lassen Sie sich die SQL

SELECT user_products.* 
FROM user_products 
    INNER JOIN subscriptions ON user_products.product_id = subscriptions.product_id 
    INNER JOIN user_products target ON subscribable_type = 'UserProduct' 
          AND subscriptions.subscribable_id = target.id 
WHERE user_products.price < target.price 
    AND target.id = ? 

nun den Active Anruf zu machen, wir sind bereit zu verwandeln.

Ich weiß nicht, ob ActiveRecord Joins aus einer Assoziation bilden kann. Ich weiß, dass die Rails 2.3 API eine Zeichenfolge benötigt.So würde der Umfang sein:

class UserProduct 
    ... 

    #defines UserProduct.cheaper(user_product_id) 
    scope :cheaper, lambda do |user_product_id| 
    join(%Q{INNER JOIN subscriptions 
      ON user_products.product_id = subscriptions.product_id 
      INNER JOIN user_products target 
      ON subscribable_type = 'UserProduct' 
      AND subscriptions.subscribable_id = target.id}). 
    where("cheaper.price < user_products.price"). 
    where(["target.id = :target_id", { :target_id => user_product_id } ]) 
    end 

    #defines user_product.cheaper 
    def cheaper 
    UserProduct.cheaper(id) 
    end 
... 
Verwandte Themen