2012-04-11 1 views
2

私はこのスコープまたは方法をどうすべきか混乱しています。私は、次の団体があります低価格を表示する方法または範囲を作成しますか?

モデル

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 

をだから、方法のようなものでなければなりません:このメソッドが行うことに仮定される何

class Price 

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

end 

属するUserProductsのショーであるだけ低価格Subscriptionと同じProductが、サブスクリプションであるpriceと比較しながら、それが低いかどうかを確認します。

私はこの権利を行っていますか?何が修正される必要がありますか?


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> 

答えて

1

あなたは、ユーザーが見つけた価格を入力して購読して安価な価格を見つけるWebサイトを作っていると考えました。 UserProductエンティティの名前をPriceに変更します。

購読者が商品を購読するのか価格を購読するのかは曖昧です。これをクリアすると、多型関連を単純化することができます。特定の価格で製品を購読しているとします。次に、次のようにしてください:

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

私はこれについてどうやって行くのか混乱しています。私は 'UserProduct'(または' Price')属性を複製しなければならなかったので、より安い価格をチェックする方法を知っていました。 'サブスクリプション'と '価格'は同じフィールドを持っているので、私はこれら2つのモデルを比較することができると思う。したがって、「サブスクリプション」はすべての「価格」と比較されます。 – LearningRoR

+0

また、あなたは自分のウェブサイトについて正しいです。ユーザーは新しい価格を入力する必要があります。代わりに、モデルを「価格」に変更したので、現在と将来の間に作成されます。ありがとうございました。 – LearningRoR

+0

はい。最初は、サブスクリプションエンティティに価格フィールドがあることに気付かなかった。私はあなたのUIのどこかで、あなたはサブスクリプションを取得すると仮定したいと思います。私の他のアプローチは、価格モデルに安価な価格を返す方法を持たせることでした。基本的には、この回答で指定されたスコープでは、製品IDと価格を提供できるすべてのオブジェクトがスコープを使用できます。 –

0

あなたが持っているすべての製品は、あなたが

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") 

これは読み取り専用のレコードを返しますのために働く必要があり、このよりもサブスクリプションを持っていると仮定することができます。読み取り/書き込みアクセスが必要な場合は、UserProduct.find(rec.id)を使用してレコードをリロードする必要があります。

どうすればいいか教えてください。

1

まず、UserProductテーブルをより意味のある名前にする必要があります。私はそれがセマンティクスがリンクテーブルとして以外のものであるかどうかはわかりません。

また、製品またはUserProductの購読に関しては混乱があります。多形性の関連が見えますが、混乱があると思われます。

通知サブスクリプションにはproduct_idが含まれているため、サブスクリプションはサブスクリプションに属しているのではなく、サブスクリプションに属しています。

まず、デザインをクリーンアップする必要があります。

しかし、私はそのあなたが望むものは、あなたがSQLに望むものを

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 

これはあなたが全体的にございます、すべて安い価格のレポートを与えるであるという信仰上のあなたの状態を取ることができます仮定。与えられたuser_productsレコードのすべての安価な価格については、指定されたidの条件を含める必要があります。

次に、ActiveRecordの中でこの作品を作るためには、我々は今、我々はActiveRecordのコールを行う準備ができているのは、

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 = ? 

にSQLを変換させ、選択は、クラスのためにテーブルの上になりたいです。

ActiveRecordが結合から結合を形成できるかどうかわかりません。私はRails 2.3 APIが文字列を必要としていることを知っています。したがって、範囲は次のようになります:

関連する問題