2016-10-05 6 views
0

私は以前この質問をしていましたが、うまくいきませんでした。Ruby On Rails - スコープでHAVINGを使用してJOINをカバーする

私はバッチが味の3つのモデル

class Flavor < ActiveRecord::Base 
    has_many :components 
    has_many :ingredients, through: :components 
end 

class Ingredient < ActiveRecord::Base 
    has_many :components 
    has_many :flavors, through: :components 
end 

class Component < ActiveRecord::Base 
    belongs_to :ingredient 
    belongs_to :flavor 

    validates :percentage, presence: true 
end 

を作られていましたが、それは部品が100%まで追加だ場合、私はそうそこに割合の検証を置く理由は味だけので、(バッチにすることができますそれは表現された)。

は、最初に私は、スコープとしてこれを書いてみましたが、それは仕事を得ることができませんでした、私が作成したモデルのテストが

def self.batch_eligible 
    self.find_by_sql("Select flavors.* FROM flavors 
    INNER JOIN components on flavors.id = components.flavor_id 
    GROUP BY flavors.id, flavors.name 
    HAVING SUM(percentage)=100") 
end 

を使用して働いていた私は、スコープの試みを行いましたし、それが失敗しました。その結果、オブジェクトがバッチの形で選択リストを移入するために使用されます

scope :batch_eligible, -> {joins(:components).having('SUM(percentage) = 100').group('flavor.id')}

(コンポーネントが完全に働いている前に、味が存在することができます):ここでは私が思いついた範囲の最終バージョンがあります。

私はここでスコープを理解していますが、find_by_sql式と同じ結果を出すためにスコープを正しく構築するにはどうすればよいでしょうか?

ありがとう、ありがとうございました。最初のコメントを受けて

- 私はエラーを取得することなく、スコープの多様性を試してみました - 戻って上記の範囲このエラー:「

ActiveRecord::StatementInvalid: 
    PG::UndefinedTable: ERROR: missing FROM-clause entry for table "flavor" 
    LINE 1: SELECT COUNT(*) AS count_all, flavor.id AS flavor_id FROM "f... 
             ^
    : SELECT COUNT(*) AS count_all, flavor.id AS flavor_id FROM "flavors" INNER JOIN "components" ON "components"."flavor_id" = "flavors"."id" GROUP BY flavor.id HAVING SUM(percentage) = 100 

が味のIDに変更するには、それが仕事 "になり、それはdoesnの適切な情報を返します。

コードのもう一つのピース - batch_eligibleカウントが4である - - ない1

つ以上の音符 - テストがfind_by_sql機能を渡してもきれいなテストデータベースとモデル試験

require 'rails_helper' 

RSpec.describe Flavor, type: :model do 
    let!(:flavor) {FactoryGirl.create(:flavor)} 
    let!(:flavor2) {FactoryGirl.create(:flavor)} 
    let!(:ingredient) {FactoryGirl.create(:ingredient)} 
    let!(:component) {FactoryGirl.create(:component, flavor: flavor, ingredient: ingredient, percentage: 25)} 
    let!(:component1) {FactoryGirl.create(:component, flavor: flavor2, ingredient: ingredient, percentage: 100)} 

    it "should have a default archive as false" do 
    expect(flavor.archive).to be(false) 
    end 

    it "should only have valid flavors for batch creation" do 
    expect(Flavor.batch_eligible.count).to eq 1 
    expect(Flavor.batcH_eligible.first).to eq flavor2 
    end 
end 

使用されている - 私は範囲が可能であるべきだと思う?

+1

これまでに行ったバージョンを試してみましたが、どのようなエラーがありましたか?あなたは部品を取り除き、結果が何であるかを見て、作品が独立していることを確認しましたか?またはどの作品が壊れている作品ですか? –

+1

@TarynEast上記の編集を参照してください - エラーに関して - どのように私はエラーに対応してそれを修正しようとし、まだ動作しません。私は本当にこれが簡単なことだと思った – MageeWorld

+1

これはflavour_idのことを不平にしています:列が何に属しているかを明示する必要があるかもしれません。例えば 'joins(:components).references(:components) ( 'SUM(components.percentage)= 100')。group( 'components.flavor_id') 'また、' count'で始まらないことをお勧めします - >時々複雑なスコープが動作しますが、適切な "count"クエリ... '.all'を返してから' .size'を実行することで開始します(ちょうどそれが部分的に働くようにするため)... 'count'を正しく動作させる方法を見つけます。 –

答えて

1

助けのための@taryneastへの小道具 - 私はこれによって正しい方向に指摘されました。

flavors.idで範囲の問題を修正した後、私は何が起こっていたのかを調べるために検査を実行しましたが、さまざまな機能も実行しました。

puts Flavor.batch_eligible.countまたはputs Flavor.batch_eligible.sizeの両方が同じものを生成します。たとえば、ハッシュ{312 => 1} - 312は、Factory Created FlavorのIDになります。

だから問題(一度私がflavors.idを解決した)は、スコープに含まれていませんでした。テスト中でした。 LENGTHをテストする必要があります。Flavor.batch_eligible.lengthは、必要な整数1を生成します。

恐らく誰もが知っていた - 私はしなかった。

ありがとうTaryn

関連する問題