Index's not being created - ruby-on-rails

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

Related

Error on generate scaffolds with references

I'm trying to generate 3 scaffolds:
$ rails g scaffold Artist name:string type:string bio:text resume:string
site:string
$ rails g scaffold ArtistSerie title:string artist:references
$ rails g scaffold ArtistSeriePhoto photo:string
title:string year:integer description:text dimensions:string
featured:boolean artist_serie:references
the first two models are creating their indexes and foreign keys properly, but the third one is generating this error after rake db:migrate:
Mysql2::Error: Key column 'artist_series_id' doesn't exist in table: ALTER TABLE `artist_serie_photos` ADD CONSTRAINT `fk_rails_9422e9e931`
FOREIGN KEY (`artist_series_id`)
REFERENCES `artist_series` (`id`)
here is the generated migrations:
class CreateArtists < ActiveRecord::Migration
def change
create_table :artists do |t|
t.string :name
t.string :type
t.text :bio
t.string :resume
t.string :site
t.timestamps null: false
end
end
end
class CreateArtistSeries < ActiveRecord::Migration
def change
create_table :artist_series do |t|
t.string :title
t.references :artist, index: true, foreign_key: true
t.timestamps null: false
end
end
end
class CreateArtistSeriePhotos < ActiveRecord::Migration
def change
create_table :artist_serie_photos do |t|
t.string :photo
t.string :title
t.integer :year
t.text :description
t.string :dimensions
t.boolean :featured
t.references :artist_serie, index: true, foreign_key: true
t.timestamps null: false
end
end
end
the table was created and the field artist_serie_id too but the index and foreign key don't.
I already created another blank project and it works (on sqlite) so probably it's a mysql adapter error.
Any idea?
I appreciate your help!
I expect the root problem is that series is singular. That is, serie is not the singular form of series. It might be worth replacing series with sequence.

Try to add new column into Posgres DB but only success when there is no data in table

I'm trying to add new column into the table by 'rake db:migrate',but it return nothing in cmd.Then i try 'rake db:migrate:status' this time it return the following...
C:\Sites\seas>rake db:migrate:status
database: seas_development
Status Migration ID Migration Name
--------------------------------------------------
up 20160323084854 Create equipment
up 20160329072332 Devise create users
Below is inside my migration file...
class CreateEquipment < ActiveRecord::Migration
def change
create_table :equipment do |t|
t.string :name
t.string :equip_id
t.date :buy_date
t.string :brand
t.string :note
t.date :exp
t.string :status
t.string :serial
t.float :price
t.string :pic_id
t.string :ownby
t.timestamps null: false
end
add_column :equipment, :process ,:string
end
end
This only happen if there exist some data in the table,otherwise migration work fine.
Any suggestion ?
You have a typo
add_column :equipment, :process ,:string
Table name should be in plural
add_column :equipments, :process ,:string
But... if the migration had already be ran, then it will not run again. Create a new migration
rails g migration add_process_to_equipments process
rake db:migrate
Ta dah!

Specify which foreign key table will be referred to inside of a migration

I'm developing my Ruby On Rails application that is using PostgreSQL as a database and I've faced a problem.
Here is my Questions table (schema.rb):
create_table "questions", primary_key: "hashid", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "questions", ["hashid"], name: "index_questions_on_hashid", unique: true, using: :btree
where hashid field (string) is being used instead of a default numeric id field.
Here's my migration for both Questions and Comments tables:
# Questions migration
class CreateQuestions < ActiveRecord::Migration
def change
create_table :questions, id: false do |t|
t.text :hashid, primary_key: true
t.string :title
t.text :body
t.timestamps null: false
end
add_index :questions, :hashid, unique: true
end
end
# Comments migration
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :body
t.references :question, foreign_key: :hashid
t.timestamps null: false
end
end
end
I want to relate Comments with Questions in my application using belongs_to and has_many relationship accordingly, but the default t.references :question is trying to relate by using id column from the target table.
Here is the migration error message:
== 20160326185658 CreateComments: migrating ===================================
-- create_table(:comments)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedColumn: ERROR: column "id" referenced in foreign key constraint does not exist
: ALTER TABLE "comments" ADD CONSTRAINT "comments_question_id_fk" FOREIGN KEY ("question_id") REFERENCES "questions"(id)
How could I relate by using other than id field? In my case it is hashid?
I would prefer to still name the primary key column id even when the column contains a random generated string.
To create a string id column in your database, use a migration like this:
create_table :questions, id: false do |t|
# primary key should not be nil, limit to improve index speed
t.string :id, limit: 36, primary: true, null: false
# other columns ...
end
In your model, ensure that a id is created:
class Question < ActiveRecord::Base
before_validation :generate_id
private
def generate_id
SecureRandom:uuid
end
end
When you are already in Rails 5 you might just want to use has_secure_token :id instead of the before_validation call back and the generate_id method.

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'

rails generate migration add_index_to... does not put the actual index in the migration file

I created a users table via "rails generate model User name:string email:string ..." the migration file was created as well.
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
Now I want to add an index to the email column "following the tutorial" I've done this successfully the first time through using sqlite3. Second time through im using MySql (mysql2). Again created the table fine with generate model.. When I run the following:
rails generate migration add_index_to_users_email
the process ends with no error message and creates the migration file as shown below, but there is no setting of any index..
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
end
end
Im expecting to see add_index :users, :email, unique: true in there ... Anybody have any idea's.. searched other threads to no avail.. running rails 4, mysql 5.6 ruby 1.9.3 my schema that was created after initil db:migrate is:
ActiveRecord::Schema.define(version: 20131024161033) do
create_table "users", force: true do |t|
t.string "name"
t.string "email"
t.string "city"
t.string "state"
t.string "zip"
t.string "mobile_phone"
t.string "mobile_phone_type"
t.date "birth_date"
t.string "user_type"
t.string "ss_num"
t.boolean "agree_to_terms"
t.datetime "created_at"
t.datetime "updated_at"
end
end
via http://guides.rubyonrails.org/migrations.html
If you'd like to add an index on the new column, you can do that as
well:
$ rails generate migration AddPartNumberToProducts
part_number:string:index
your generator
rails generate migration add_index_to_users_email
simply creates an empty migration file and did not describe a index
so this would be more appropriate...
rails generate migration AddIndexToUsers email:string:index
should give you
class AddIndexToUsers < ActiveRecord::Migration
def change
add_index :users, :email
end
end
Nguyen You - EDIT
This command [Rails 5.2.3]
rails generate migration AddIndexToUsers email:string:index
actually will give you
class AddIndexToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :email, :string
add_index :users, :email
end
end
not only add_index but also add_column to the users table.
rails generate migration AddIndexToUsers email:string:index
if you already have column it just add index, like:
class AddIndexToUsers < ActiveRecord::Migration
def change
add_index :users, :email
end
end
if you create new column (you haven't got column in database yet), it returns:
class AddIndexToUsers < ActiveRecord::Migration
def change
add_column :user, :email, :string
add_index :users, :email
end
end
From the http://railstutorial.ru/chapters/4_0/modeling-users#code-email_uniqueness_index.
The email uniqueness migration is not pre-defined, so we need to fill in its contents with this by ourself " add_index :users, :email, unique: true " .
The result will be:
class AddIndexToUsersEmail < ActiveRecord::Migration
def change
add_index :users, :email, unique: true
end
end

Resources