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?

+3


source to share


1 answer


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

+1


source







All Articles