Why is it where (). First_or_create generating invalid SQL in RSpec?
I see a case where it Action.where(:name => "fred").first_or_create
generates incorrect SQL when run under RSpec but executes correctly in the console. I'm puzzled.
Here's the model. The base table actions
has one field, a row named name
:
# file: app/models/action.rb
class Action < ActiveRecord::Base
def self.internalize(name)
self.where(:name => name).first_or_create
end
end
Here's the 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
Here's the error:
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)>'
It looks like when the record exists Action.where(:name => "fred").first_or_create
creates SQL
SELECT "actions".* FROM "actions" WHERE "name"."name" = 'fred' LIMIT 1
... which is wrong - it is looking for a table named "name".
What's odd is that entering exactly the same thing into the console is done correctly. And yes, I remembered (this time) to print rake db:test:prepare
before running my RSpec tests. I'm runing
Ruby version 1.9.3 (x86_64-darwin10.8.0)
Rails version 3.2.1
RSpec 2.9.0
What's going on here?
Action.internalize(:name => "fred")
generates a where clause:
where(:name => {:name => "fred"})
which means you have a linked table name
that has a column name
with a valuefred