Search code examples
ruby-on-rails-3primary-keycomposite

Give composite primary key in Rails


How can i give composite primary key in Rails without any gem?

My first table in migration file:

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :userid
      t.string :name
      t.string :address
      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end

My second table in migration file:

class CreateProjects < ActiveRecord::Migration
  def self.up
    create_table :projects do |t|
      t.string :title
      t.string :description
      t.timestamps
    end
  end
  def self.down
    drop_table :projects
  end
end

In my schema file:

ActiveRecord::Schema.define(:version => 20110222044146) do
  create_table "projects", :force => true do |t|
    t.string   "title"
    t.string   "description"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", :force => true do |t|
    t.string   "userid"
    t.string   "name"
    t.string   "address"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

Now I want to create a table called User_has_project in which I will refer to User and Project that means will have 2 foreign keys. So I tried like this:

class CreateUser_has_projects < ActiveRecord::Migration
  def self.up
    create_table :user_has_projects do |t|
      t.references :User
      t.references :Project
      t.boolean :status
      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end

Now how can I set combination of user_id and project_id as a primary key in user_has_projects?


Solution

  • It looks like you're trying to specify a many-many relationship between Users and Projects, with an additional field on the relationship itself.

    The way you're currently doing isn't the Rails way of doing things - especially with the concept of a composite primary key.

    The Rails/ActiveRecord way of doing this sort of relationship modelling is to have a third model that describes the relationship between User and Project. For the sake of example, I'm going to call it an Assignment. All you need to do is re-name your user_has_projects table to assignments like so:

    class CreateAssignments < ActiveRecord::Migration
      def self.up
        create_table :assignments do |t|
          t.references :user
          t.references :project
          t.boolean :status
          t.timestamps
        end
      end
    
      def self.down
        drop_table :assignments
      end
    end
    

    And then, in your model files:

    # app/models/user.rb
    class User < ActiveRecord::Base
      has_many :assignments
      has_many :projects, :through => :assignments
    end
    
    # app/models/assignment.rb
    class Assignment < ActiveRecord::Base
      belongs_to :user
      belongs_to :project
    end
    
    # app/models/project.rb
    class Project < ActiveRecord::Base
      has_many :assignments
      has_many :users, :through => :assignments
    end
    

    You can read more about this here: http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association