Problems setting a custom primary key in a Rails 4 migration - ruby-on-rails

I use postgresql 9.3, Ruby 2.0, Rails 4.0.0.
After reading numerous questions on SO regarding setting the Primary key on a table, I generated and added the following migration:
class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, { id: false, primary_key: :uid } do |t|
t.integer :uid, limit: 8
t.string :name
t.integer :shares
t.timestamps
end
end
end
I also added self.primary_key = "uid" to my model.
The migration runs successfully, but when I connect to the DB using pgAdmin III I see that the uid column is not set as primary key. What am I missing?

Take a look at this answer. Try to execute "ALTER TABLE shareholders ADD PRIMARY KEY (uid);" without specifying primary_key parameter in create_table block.
I suggest to write your migration like this (so you could rollback normally):
class CreateShareholders < ActiveRecord::Migration
def up
create_table :shareholders, id: false do |t|
t.integer :uid, limit: 8
t.string :name
t.integer :shares
t.timestamps
end
execute "ALTER TABLE shareholders ADD PRIMARY KEY (uid);"
end
def down
drop_table :shareholders
end
end
UPD: There is natural way (found here), but only with int4 type:
class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, id: false do |t|
t.primary_key :uid
t.string :name
t.integer :shares
t.timestamps
end
end
end

In my environment(activerecord 3.2.19 and postgres 9.3.1),
:id => true, :primary_key => "columname"
creates a primary key successfully but instead of specifying ":limit => 8" the column' type is int4!
create_table :m_check_pattern, :primary_key => "checkpatternid" do |t|
t.integer :checkpatternid, :limit => 8, :null => false
end
Sorry for the incomplete info.

I have created migrations like this:
class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, id: false do |t|
t.integer :uid, primary_key: true
t.string :name
t.integer :shares
t.timestamps
end
end
end

Related

Default rails id column name in Rails

I wanna rename the column id, how do I do?
I want to set number to primary key and auto increment, and id to just string of user id.
How do I do?
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :user
t.timestamps
end
rename_column :users, :id, :number
end
end
I did like above, but it didn't work.
Even if I wouldn't recommend it, here is how I guess you can do it:
in your migration:
def up
create_table :users, id: false do |t|
t.string :user
t.integer :number, null: false, index: true, unique: true
t.timestamps
end
execute %Q{ ALTER TABLE "users" ADD PRIMARY KEY ("number"); }
end
def down
drop_table :users
end
in your model:
self.primay_key = 'number'

ActiveRecord::UnknownAttributeError: unknown attribute: p_id

after I run
bundle exec rake db:seed
The titled error will show.
Could anyone has a look at my RoR code? I've not sure where is the issue.
my
product.rb
file
class Product < ActiveRecord::Base
set_primary_key :p_id
attr_accessible :p_id, :name, :category, :description, :price
end
schema.rb
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20111119180638) do
create_table "products", :force => true do |t|
t.string "p_id"
t.string "name"
t.string "category"
t.text "description"
t.string "price"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
create_products.rb
class CreateProducts < ActiveRecord::Migration
def up
create_table :products, {:id => false} do |t|
t.string :p_id
t.string :name
t.string :category
t.text :description
t.string :price
# Add fields that let Rails automatically keep track
# of when products are added or modified:
t.timestamps
end
execute "ALTER TABLE products ADD PRIMARY KEY (p_id);"
end
def down
drop_table :products
end
end
primery_key method is expecting an string:
self.primary_key 'p_id'
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html#method-i-primary_key-3D

Index's not being created

I am trying to create a user_roles table in my engine that joins the user with a particular role allowing that user to have one or more roles.
I have the following migrations:
User
-- This migration works fine.
class CreateXaaronUsers < ActiveRecord::Migration
def change
create_table :xaaron_users do |t|
t.string :first_name
t.string :last_name
t.string :user_name
t.string :email
t.string :password
t.string :salt
t.timestamps
end
end
end
Roles
-- This migration works fine
class Roles < ActiveRecord::Migration
def change
create_table :xaaron_roles do |t|
t.string :role
t.timestamps
end
end
end
user_roles
-- This migration explodes stating that column user_id doesn't exist. I assume that this migration, dealing with indexes and the such, would create the appropriate columns referencing what I am telling it to reference.
class UserRolesJoin < ActiveRecord::Migration
def change
create_table :xaaron_user_roles, id: false do |t|
t.references :xaaron_user, null: false
t.references :xaaron_role, null: false
end
add_index :xaaron_user_roles, :user_id
add_index :xaaron_user_roles, [:role_id, :user_id], unique: true
add_index :xarron_roles, :role, unique: true
end
end
The exact error is:
PG::UndefinedColumn: ERROR: column "user_id" does not exist
: CREATE INDEX "index_xaaron_user_roles_on_user_id" ON "xaaron_user_roles" ("user_id")/Users/Adam/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in `async_exec'
/Users/Adam/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in `block in execute''
Did I fail at typing something? Why is this migration failing, aside from the obvious?
If you just want to create a join table then,
1. Remove the existing migration
rails d migration UserRolesJoin
2. Create a new migration for join table as
rails g migration CreateJoinTableUserRole user role
This will create a migration like:
class CreateJoinTableUserRole < ActiveRecord::Migration
def change
create_join_table :users, :roles do |t|
# t.index [:user_id, :role_id]
# t.index [:role_id, :user_id]
end
end
end
NOTE: You need to uncomment one of the combination as per your requirement from the generated migration.
3. Run rake db:migrate

Do I need to create an assocation table for a :has_many :through association?

I'm trying to use a :has_many :through type association, but I'm getting the following error:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: work_units.developer_id:
Many other posts about this sort of thing have just had spelling mistakes, but I've checked mine.
class Developer < ActiveRecord::Base
attr_accessible :skype_name, :language_ids, :user_attributes
has_many :work_units
has_many :projects, :through => :work_units
...
end
class Project < ActiveRecord::Base
attr_accessible :complete, :description, :finalised, :price
has_many :work_units
has_many :developers, :through => :work_units
...
end
class WorkUnit < ActiveRecord::Base
attr_accessible :hours_worked
belongs_to :project
belongs_to :developer
end
I've run db:migrate and it didn't complain. I did make a mistake and had to rollback the db then re-migrate, but I think I did it right. I use the annotate gem and it doesn't show any of the relationship ids I'd expect. So, do I need to create a WorkUnits table or am I missing something? The rails guide didn't mention manually making tables.
Edit
Here's the migration I used to create the WorkUnit model and stuff:
class CreateWorkUnits < ActiveRecord::Migration
def change
create_table :work_units do |t|
t.integer :hours_worked, :default => 0
t.timestamps
end
end
end
Edit 2
Snippets from my schema.rb:
create_table "work_units", :force => true do |t|
t.integer "hours_worked", :default => 0
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "projects", :force => true do |t|
t.string "description"
t.decimal "price", :precision => 8, :scale => 2
t.boolean "complete", :default => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
Similarly for :developers. So, why doesn't my migration add the association information for me?
Your WorkUnit migration should look like this:
class CreateWorkUnits < ActiveRecord::Migration
def change
create_table :work_units do |t|
t.integer :hours_worked, :default => 0
t.references :developer
t.references :project
t.timestamps
end
add_index :work_units, :developer_id
add_index :work_units, :project_id
end
end
You need to add the foreign keys to your work_units table.
class CreateWorkUnits < ActiveRecord::Migration
def change
create_table :work_units do |t|
t.integer :hours_worked, :default => 0
t.integer :project_id, null: false
t.integer :developer_id, null: false
t.timestamps
end
add_index :work_units, :project_id
add_index :work_units, :developer_id
end
end
Another way:
class CreateWorkUnits < ActiveRecord::Migration
def change
create_table :work_units do |t|
t.integer :hours_worked, :default => 0
t.belongs_to :project
t.belongs_to :developer
t.timestamps
end
add_index :work_units, :project_id
add_index :work_units, :developer_id
end
end
You can also define these fields when generating your model, then they'll be added to the migration automatically as show in the second snippet.
$ rails g model WorkUnit hours_worked:integer project:belongs_to developer:belongs_to
Hope that helps.
A table for WorkUnit needs to exist, whether that means it migration was automatically generated via scaffolding or if the migration was manually written by you.
If you don't have a migration yet that creates that table, you'll need to create that migration because the table does need to exist.
You do need a work_units table with a project_id and developer_id column.
Have a look at http://xyzpub.com/en/ruby-on-rails/3.2/activerecord_datenbank_anlegen.html if you don't know how to create a table.

Rails create_table query

I am a beginner in Rails. In the following code,there is an id which is set as false. What's the meaning of it?
class CreateCoursesStudents < ActiveRecord::Migration
def self.up
create_table :courses_students, **:id => false** do |t|
t.integer :course_id,:null => false
t.integer :student_id, :null => false
end
# Add index to speed up looking up the connection, and ensure # we only
enrol a student into each course once
add_index :courses_students, [:course_id, :student_id], :unique => true
end
def self.down
remove_index :courses_students, :column => [:course_id, :student_id]
drop_table :courses_students
end
end
Thanks
:id => false defines a table with no primary key, which is useful e.g. when you create a join table for a many-to-many relationship.
:null=>false indicates that the field in question cannot be null for any row that gets created in the the courses_students table.

Resources