Re: postgres adapater problem with create_table :id => false

Rick
Thu, 17 Sep 2009 01:33:56 -0000

I think you want to be using the gem "pg" as your postgresql adapter,
not "postgres".

gem list pg -r
*** REMOTE GEMS ***
pg (0.8.0)

This adapter definitely supports tables without a primary key -
typical join table used for habtm models.  For instance the following
migration works to provide role <-> user join.  This works with
ruby1.8.7 or 1.9.1 and rails 2.3.0-2.3.4, postgres version 8.3.7.

NNNN_create_role_users.rb
class CreateRoleUsers < ActiveRecord::Migration
  def self.up
    create_table :roles_users, :id => false do |t|
      t.integer :role_id
      t.integer :user_id
    end
  end

models/role.rb
class Role < ActiveRecord::Base
  has_and_belongs_to_many :users

models/user.rb
class User < ActiveRecord::Base
  has_and_belongs_to_many :roles


On Sep 16, 4:36 pm, Howard Yeh
<hay...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:
> Hi All,
>
> When saving a record to a table that doesn''t use primary key, the
> adapater raises
>
> ActiveRecord::StatementInvalid: PGError: ERROR:  column "id" does
not
> exist
>
> That''s because the postgres adapter does,
>
> INSERT INTO ... RETURNING "id"
>
> And "id" doesn''t exist for a table that doesn''t
ues it.
>
> The offending block of code is from
>
> PostgreSQLAdapter#insert(sql, name = nil, pk = nil, id_value = nil,
> sequence_name = nil)
>
> if supports_insert_with_returning?
>   pk, sequence_name = *pk_and_sequence_for(table) unless pk
>   if pk
>     id = select_value("#{sql} RETURNING
#{quote_column_name(pk)}")
>     clear_query_cache
>     return id
>   end
> end
>
> The problem is that ActiveRecord::Base.create
> would pass in the primary_key "id" for the
> parameter pk even though the ActiveRecord class
> doesn''t have a primary key.
>
> # this would work
> if supports_insert_with_returning?
>   # this would work
>   pk, sequence_name = *pk_and_sequence_for(table)
>   if pk
>     id = select_value("#{sql} RETURNING
#{quote_column_name(pk)}")
>     clear_query_cache
>     return id
>   end
> end
>
> Or is there a way to set the primary key to nil?
>
> class Foo < ActiveRecord::Base
>  set_primary_key nil
>  primary_key # => ""
> end
>
> Howard