2012-03-23 56 views
3

我看到一個案例,其中Action.where(:name => "fred").first_or_create在RSpec下運行時生成不正確的SQL,但在控制檯中正確執行。我很困惑。這是爲什麼where()。first_or_create只在RSpec中生成不正確的SQL?

這是模型。底層actions表有一個字段,一個字符串,命名爲name

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

這裏的RSpec的測試:

# 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 

這裏的失敗:

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

看來,當記錄存在,Action.where(:name => "fred").first_or_create正在生成SQL

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

......這是錯誤的 - 它正在尋找名爲「名稱」的表。

奇怪的是,在控制檯中輸入完全相同的東西會正常運行。是的,我記得(這次)在運行我的RSpec測試之前輸入rake db:test:prepare。我正在運行

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

這是怎麼回事?

回答

1

Action.internalize(:name => "fred")正在生成where子句:

說的意思是,你有相關的表 name
where(:name => {:name => "fred"}) 

,有列name與價值fred

+0

這意味着,它的工作原理Rails的控制檯上的事實是幸運的巧合。 – 2012-03-25 02:51:05

+0

@Mik:請解釋一下?據我所知,'Action.internalize(:name =>「fred」)'生成where子句'Action.where(:name =>「fred」)',否? [見http://guides.rubyonrails.org/active_record_querying.html#hash-conditions]。你在哪裏得到嵌套散列? – 2012-03-25 05:56:19

+1

@Mik:OOHHHHH!是的,這是我的一個非常愚蠢的錯字。對Action.internalize(:name =>「fred」)的調用應該只是Action.internalize(「fred」)。你不知道我有多少次盯着那段代碼,完全錯過了它。 – 2012-03-25 06:50:41

相關問題