This project is archived and is in readonly mode.

#5152 ✓resolved
noe

[Rails3 b4] has_and_belongs_to_many (habtm) with string ids don't work

Reported by noe | July 19th, 2010 @ 02:56 PM | in 3.x

Hi,

I have a problem with the has_and_belongs_to_many association. I don't use integer id, but a string uuid for ids. I have 3 tables: users and roles with a users_roles between. If I do this:

user = User.first
role = Role.first
user.roles << role
user.save!

=> It's work with 2.3.8 but not with 3b4. The uuids for user and role are ok, but not the foreign keys is users_roles.

If I have a uuid for user like "123456abc", in users_roles.user_id or users_roles.role_id, I have "'123456abc'" with the '' included.

Regards,
noe

Comments and changes to this ticket

  • Neeraj Singh

    Neeraj Singh July 19th, 2010 @ 06:00 PM

    • Milestone set to 3.x
    • State changed from “new” to “open”
    • Assigned user set to “Neeraj Singh”
    • Importance changed from “” to “Low”
  • Neeraj Singh

    Neeraj Singh July 19th, 2010 @ 08:34 PM

    • Assigned user changed from “Neeraj Singh” to “José Valim”

    Attached is code and test patch.

  • noe

    noe July 20th, 2010 @ 07:53 AM

    Thanks for the patch, it work well for foreign keys :)

    I have a related issue if I add created_at and/or updated_at columns in users_roles table. It's the same problem: AR try to insert "'a date'" instead of "a date".

  • Neeraj Singh

    Neeraj Singh July 20th, 2010 @ 11:13 AM

    I am using rails edge and surprisingly I am getting nil for both created_at and updated_at in my join table. Not sure what I am missing.

    ActiveRecord::Schema.define(:version => 20100719150531) do
    
      create_table "countries", :id => false, :force => true do |t|
        t.string "country_id"
        t.string "name"
      end
    
      create_table "countries_treaties", :id => false, :force => true do |t|
        t.string   "country_id", :null => false
        t.string   "treaty_id",  :null => false
        t.datetime "updated_at"
        t.datetime "created_at"
      end
    
      create_table "treaties", :id => false, :force => true do |t|
        t.string "treaty_id"
        t.string "name"
      end
    
    end
    
    class Country < ActiveRecord::Base
      set_primary_key :country_id
      has_and_belongs_to_many :treaties
    
      def self.lab
        Country.delete_all
        Treaty.delete_all
        c = Country.new(:name => 'india')
        c.country_id = 'c1'
        c.save!
    
        t = Treaty.new(:name => 'peace')
        t.treaty_id = 't1'
        c.treaties << t
        c.save!
        puts Country.first.treaties.inspect
    
        con = ActiveRecord::Base.connection
        sql = 'select * from countries_treaties'
        records = con.select_rows(sql)
        puts records.inspect
        record = records.last
        puts record.inspect
        puts record[0]
        puts record[1]
        puts record[2]
        puts record[3]
      end
    
    end
    
    class Treaty < ActiveRecord::Base
      set_primary_key :treaty_id
    
      has_and_belongs_to_many :countries
    
      def self.lab
      end
    
    end
    
    Country.lab 
    
    ree-1.8.7-2010.01 > Country.lab
      SQL (0.4ms)   SELECT name
     FROM sqlite_master
     WHERE type = 'table' AND NOT name = 'sqlite_sequence'
    
      SQL (3.4ms)  DELETE FROM "countries" WHERE 1=1
      SQL (1.8ms)  DELETE FROM "treaties" WHERE 1=1
      SQL (0.4ms)  INSERT INTO "countries" ("country_id", "name") VALUES ('c1', 'india')
      SQL (0.4ms)  INSERT INTO "treaties" ("name", "treaty_id") VALUES ('peace', 't1')
      SQL (0.2ms)  INSERT INTO "countries_treaties" ("country_id", "treaty_id") VALUES ('c1', 't1')
      Country Load (0.5ms)  SELECT "countries".* FROM "countries" LIMIT 1
      Treaty Load (0.3ms)  SELECT * FROM "treaties" INNER JOIN "countries_treaties" ON "treaties".treaty_id = "countries_treaties".treaty_id WHERE ("countries_treaties".country_id = 'c1' )
    [#<Treaty treaty_id: "t1", name: "peace">, #<Treaty treaty_id: "t1", name: "peace">, #<Treaty treaty_id: "t1", name: "peace">]
      SQL (0.2ms)  select * from countries_treaties
    [["c1", "t1", nil, nil], ["c1", "t1", nil, nil], ["c1", "t1", nil, nil]]
    ["c1", "t1", nil, nil]
    c1
    t1
    nil
    nil
    
  • Samuel Kadolph

    Samuel Kadolph July 20th, 2010 @ 03:43 PM

    The has_and_belongs_to_many association doesn't store created_at and updated_at because they would be useless since there is no join model to access them. And since they are created and updated only when assigning one model to another, the times would be exactly the same.

    A habtm join table row is never updated even when you add the same model to another. A new row is always created.

    c.treaties << t
    c.treaties << t
    

    would give 2 additional join table rows.

  • Neeraj Singh

    Neeraj Singh July 20th, 2010 @ 04:20 PM

    timestamps should always be updated to reduce any element of surprise. Created ticket #5161 to fix that issue.

  • José Valim

    José Valim July 20th, 2010 @ 04:25 PM

    @Samuel, I would expect c.treaties << t to create two rows unless you specify :uniq in the association.

    Besides, it is documented that all columns in the join table are available in the model instance, overwriting the model ones. So if you do post.tags, where posts and tags have a HABTM relationship, the created_at and updated_at fields for each tag object in post.tags will return the created_at and updated_at value in the join table, and not in the tag attribute. This work for all columns and this is the reason you should not have id in join tables (otherwise it would overwrite your model id).

  • Repository
  • José Valim

    José Valim July 21st, 2010 @ 01:56 PM

    • State changed from “open” to “resolved”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Referenced by

Pages