2012-03-23 3 views
3

Ich sehe einen Fall, in dem Action.where(:name => "fred").first_or_create falsche SQL generiert, wenn unter RSpec ausgeführt wird, aber in der Konsole ordnungsgemäß ausgeführt wird. Ich bin verwirrt.Warum ist dies wo(). First_or_create, die nur in RSpec falsches SQL erzeugt?

Hier ist das Modell. Die zugrunde liegende actions Tabelle hat ein Feld, eine Zeichenfolge mit dem Namen name:

# file: app/models/action.rb 
class Action < ActiveRecord::Base 
    def self.internalize(name) 
    self.where(:name => name).first_or_create 
    end 
end 

Hier ist der rspec Test:

# file: spec/models/action_spec.rb 
require 'spec_helper' 
describe Action do 
    describe 'intern' do 
    it 'should create a new name' do # works 
     lambda { Action.internalize("fred") }.should change { Action.count }.by(1) 
    end 
    it 'should not create duplicate names' do # fails 
     Action.internalize(:name => "fred") 
     lambda { Action.internalize("fred") }.should_not change { Action.count } 
    end 
    end 
end 

Hier ist der Fehler:

1) Action intern should not create duplicate names 
    Failure/Error: Action.internalize(:name => "fred") 
    ActiveRecord::StatementInvalid: 
    PG::Error: ERROR: missing FROM-clause entry for table "name" 
    LINE 1: SELECT "actions".* FROM "actions" WHERE "name"."name" = 'f... 
    : SELECT "actions".* FROM "actions" WHERE "name"."name" = 'fred' LIMIT 1 
    # ./app/models/action.rb:4:in `internalize' 
    # ./spec/models/action_spec.rb:12:in `block (3 levels) in <top (required)>' 

Es scheint, dass, wenn der Datensatz vorhanden , Action.where(:name => "fred").first_or_create erzeugt das SQL

SELECT "actions".* FROM "actions" WHERE "name"."name" = 'fred' LIMIT 1 

... was falsch ist - es sucht nach einer Tabelle namens "name".

Was seltsam ist, ist, dass die Eingabe der exakt gleichen Sache in die Konsole einwandfrei funktioniert. Und ja, ich erinnerte mich (diesmal), rake db:test:prepare vor dem Ausführen meiner RSpec-Tests zu schreiben. Ich laufe

Ruby version    1.9.3 (x86_64-darwin10.8.0) 
Rails version    3.2.1 
RSpec      2.9.0 

Was zum Teufel geht hier vor?

Antwort

1

Action.internalize(:name => "fred") erzeugt where-Klausel:

where(:name => {:name => "fred"}) 

das bedeuten, Sie name Tabelle zugeordnet haben, die Spalte name mit Wert hat fred

+0

Es bedeutet, dass die Tatsache, dass es auf der Rails-Konsole funktioniert a glücklicher Zufall. –

+0

@Mik: Bitte erklären? Soweit ich das beurteilen kann, generiert 'Action.internalize (: name =>" fred ")' die Where-Klausel 'Action.where (: name =>" fred ")', nein? [Siehe http://guides.rubyonrails.org/active_record_querying.html#hash-conditions]. Woher bekommst du den verschachtelten Hash? –

+1

@Mik: OOHHHHH! Ja, das war ein wirklich dummer Tippfehler meinerseits. Der Aufruf von Action.internalize (: name => "fred") sollte einfach Action.internalize ("fred") lauten. Du weißt nicht, wie oft ich diesen Code angestarrt habe und ihn völlig vermisst habe. –

Verwandte Themen