Name convention over a Rails Migration reference - ruby-on-rails

i have a problem creating a db table through rails generators.
I named a table personal_data and works fine.
class CreatePersonalData < ActiveRecord::Migration
def change
create_table :personal_data do |t|
t.string :name
t.string :lastName
t.string :dni
t.string :contact
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
But i created another table with a reference to Personal Data
class CreateMerchants < ActiveRecord::Migration
def change
create_table :merchants do |t|
t.string :storeName
t.references :personal_data, index: true, foreign_key: true
t.references :category, index: true, foreign_key: true
t.string :webPage
t.string :city
t.timestamps null: false
end
end
end
And when a run the migration instead of seeking for personal_data_id the migrations looks for personal_datum_id and throws and exception.
PG::UndefinedColumn: ERROR: no existe la columna «personal_datum_id» referida en la llave foránea
: ALTER TABLE "merchants" ADD CONSTRAINT "fk_rails_e4239c30dc"
FOREIGN KEY ("personal_datum_id")
REFERENCES "personal_data" ("id")
I translate the error to English
column "personal_datum_id" referenced in foreign key constraint does not exist

I'm not sure why it's confused, but perhaps you can set up your inflections such that the plural of personal_data is personal_data?
In the file: config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'personal_data', 'personal_data'
end

add self.table_name = 'personal_data' in your personal_data.rb model and run the migration

Related

ArgumentError: Index name ... is too long; the limit is 62 characters

I created a scaffold with this command (Rails 5.2.1.1):
rails g scaffold EmailAddress value:string:index
email_address_type:references
email_addressable:references{polymorphic}
position:integer
which resulted in this migration file:
class CreateEmailAddresses < ActiveRecord::Migration[5.2]
def change
create_table :email_addresses do |t|
t.string :value
t.references :email_address_type, foreign_key: true
t.references :email_addressable, polymorphic: true
t.integer :position
t.timestamps
end
add_index :email_addresses, :value
end
end
Unfortunately this raises the following error on rails db:migrate:
Caused by:
ArgumentError: Index name
'index_email_addresses_on_email_addressable_type_and_email_addressa...'
on table 'email_addresses' is too long; the limit is 62 characters
I understand the problem and the error. I'm wondering what the best solution is because the index is not set explicity by add_index but by some background magic.
As Wintermeyer says is one solution, there is another way at least I find smoother to use.
t.references :email_address_type, foreign_key: true,
index: { name: "addressable_index" }
Through this you dont get a bunch of add_index rows in your migration. This helps if you ever have a large migration and need to find a specific index quickly. This is just my personal opinion, Wintermeyer solution is also a working fix!
index: false is the solution for this problem. Followed by an add_index at the bottom. Here is the migration:
class CreateEmailAddresses < ActiveRecord::Migration[5.2]
def change
create_table :email_addresses do |t|
t.string :value
t.references :email_address_type, foreign_key: true
t.references :email_addressable, polymorphic: true, index: false
t.integer :position
t.timestamps
end
add_index :email_addresses, :value
add_index :email_addresses, [:email_addressable_type,
:email_addressable_id],
name: 'email_addressable_index'
end
end

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.

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'

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

Resources