Error on generate scaffolds with references - ruby-on-rails

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.

Related

Name convention over a Rails Migration reference

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

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.

Migrations From Custom Generator Don't Migrate

I am creating a gem
I have a generator to create a migration based on a name of your choosing
rails g my_generator MODEL
I am not using rails'
rails g migration XYZ
But instead pretty much copying what a schema would look like...example: if a user types the following
rails g my_generator Item
You get:
class CreateItem < ActiveRecord::Migration
def change
create_table "items", force: true do |t|
t.string "title"
t.integer "color_id"
t.integer "size_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "base_product_id"
t.integer "stock_qty"
end
end
end
The name of the migration is (my_generator)create_items.rb I have not inserted the timestamp in the start of the migration. That is really the only difference between a rails g model Item's migration, and the one I get from my generator.
My migration doesn't do anything, but I tested creating a new model, and running rake db:migrate, the rails g model migrates, mine does not.
Here is my generator:
class Rails::ShiftedCommerceGenerator < Rails::Generators::NamedBase
def create_main_model
create_file "app/models/shifted_commerce/#{plural_name.singularize}.rb", <<-FILE
class #{class_name} < ActiveRecord::Base
belongs_to :base_#{plural_name.singularize}
has_many :line_items
belongs_to :size
belongs_to :color
validates_uniqueness_of :base_#{plural_name.singularize}_id, :scope => [:size_id]
def is_base_#{plural_name.singularize}?
return true if self.class.name == "Base#{class_name}"
end
def is_#{plural_name.singularize}?
return true if self.class.name == "#{class_name}"
end
def in_stock
self.stock_qty > 0
end
end
FILE
end
def create_main_migration
create_file "db/migrate/shifted_commerce_create_#{plural_name}.rb", <<-FILE
class Create#{class_name} < ActiveRecord::Migration
def change
create_table :#{plural_name}, force: true do |t|
t.string :title
t.integer :color_id
t.integer :size_id
t.datetime :created_at
t.datetime :updated_at
t.integer :base_product_id
t.integer :stock_qty
t.timestamps
end
end
end
FILE
end
end
Make sure you include the timestamp when you are generating your own migrations
(not using rails g migration)
Your generator should include something this:
create_file "db/migrate/#{Time.now.strftime("%Y%m%d%H%M%S")}_create_#{plural_name}.rb", <<-FILE
the .strftime method is a way to get the timestamp into your migration file the same way rails has it formatted.

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