I am reading the Rails Guides on migrations. It states the following and I quote:
Some commonly used type modifiers can be passed directly on the
command line. They are enclosed by curly braces and follow the field type:
It provides an example:
$ bin/rails generate migration AddDetailsToProducts
'price:decimal{5,2}' supplier:references{polymorphic}
The Rails Guide also provides a list of column modifiers (SQL constraints):
limit
Sets the maximum size of the string/text/binary/integer fields.
precision
Defines the precision for the decimal fields, representing the total number of digits in the number.
scale
Defines the scale for the decimal fields, representing the number of digits after the decimal point.
polymorphic
Adds a type column for belongs_to associations.
null
Allows or disallows NULL values in the column.
default
Allows to set a default value on the column.
index
Adds an index for the column.
So now I want to use a couple of these column modifiers from the command line, but it does not generate the expected migration:
rails generate resource Employee first_name:string{limit,40, null,false} last_name:string{limit,40,null,false} birth_date:date sex:boolean salary:integer supervisor_id:integer{index,true} branch_id:integer{null,false,index,true}
The result:
class CreateEmployees < ActiveRecord::Migration[5.1]
def change
create_table :employees do |t|
t.string{limit,40, :first_name
t.string :null,false}
t.stringlimit :last_name
t.string40 :last_name
t.stringnull :last_name
t.stringfalse :last_name
t.date :birth_date
t.boolean :sex
t.integer :salary
t.integerindex :supervisor_id
t.integertrue :supervisor_id
t.integernull :branch_id
t.integerfalse :branch_id
t.integerindex :branch_id
t.integertrue :branch_id
t.timestamps
end
end
end
What am I doing wrong?
The format you are using is not quite correct. Take a look at rails g model --help for an explanation on how to use the modifiers. Here is a modified version of what you are looking for, though it doesn't handle all of the cases you are interested in:
rails generate resource Employee first_name:string{40} last_name:string{40} birth_date:date sex:boolean salary:integer supervisor_id:integer:index branch_id:integer:index
This generates the following:
class CreateEmployees < ActiveRecord::Migration
def change
create_table :employees do |t|
t.string :first_name, limit: 40
t.string :last_name, limit: 40
t.date :birth_date
t.boolean :sex
t.integer :salary
t.integer :supervisor_id
t.integer :branch_id
t.timestamps null: false
end
add_index :employees, :supervisor_id
add_index :employees, :branch_id
end
end
You will have to manually add the null: false to those entries where you want it.
But, if Branch and Supervisor also AR objects, you can do the following:
rails generate resource Employee first_name:string{40} last_name:string{40} birth_date:date sex:boolean salary:integer supervisor:references branch:references
which generates the following:
class CreateEmployees < ActiveRecord::Migration
def change
create_table :employees do |t|
t.string :first_name, limit: 40
t.string :last_name, limit: 40
t.date :birth_date
t.boolean :sex
t.integer :salary
t.references :supervisor, index: true, foreign_key: true
t.references :branch, index: true, foreign_key: true
t.timestamps null: false
end
end
end
which may be more what you are looking for
Related
I have a User model with uuid for id column.
Ahoy gem creates visits as expected but the user_id is wrong.
Any ideas?
ok. Got that. Ahoy gem doesn't work with user_id as UUID. It takes the first digits from uuid and stores that in user_id for Ahoy::Visit which could look like random value.
The solution is to change the user_id type to uuid.
This migration would do the trick:
class ChangeAhoyVisits < ActiveRecord::Migration[5.2]
def change
Ahoy::Visit.destroy_all
remove_column :ahoy_visits, :user_id, :bigint
add_column :ahoy_visits, :user_id, :uuid, foreign_key: true, null: true
add_index :ahoy_visits, :user_id
end
end
Probably need to add the same type: :uuid to the user_id column in the ahoy_events table as well. After a few rake db:rollback's I ended up modifying the original migration file that is created by rails generate ahoy:install to look like this before I ran the migration:
def change
create_table :ahoy_visits do |t|
t.string :visit_token
t.string :visitor_token
# the rest are recommended but optional
# simply remove any you don't want
# user
t.references :user, type: :uuid, foreign_key: true, index: true
# standard
t.string :ip
t.text :user_agent
t.text :referrer
t.string :referring_domain
t.text :landing_page
# technology
t.string :browser
t.string :os
t.string :device_type
# location
t.string :country
t.string :region
t.string :city
t.float :latitude
t.float :longitude
# utm parameters
t.string :utm_source
t.string :utm_medium
t.string :utm_term
t.string :utm_content
t.string :utm_campaign
# native apps
t.string :app_version
t.string :os_version
t.string :platform
t.datetime :started_at
end
add_index :ahoy_visits, :visit_token, unique: true
create_table :ahoy_events do |t|
t.references :visit
t.references :user, type: :uuid, foreign_key: true, index: true
t.string :name
t.jsonb :properties
t.datetime :time
end
add_index :ahoy_events, [:name, :time]
add_index :ahoy_events, :properties, using: :gin, opclass: :jsonb_path_ops
end
And after running this slightly modified migration rather than original everything seemed to populate properly on an 'ahoy.track' in the db.
Hello i have to model like;
class CreateLecturers < ActiveRecord::Migration
def change
create_table :lecturers do |t|
t.string :firstname
t.string :lastname
t.string :position
t.string :email
t.timestamps null: false
end
end
end
and here is my second model.
class CreateCurriculums < ActiveRecord::Migration
def change
create_table :curriculums do |t|
t.string :title
t.integer :hours
t.integer :year
t.text :description
t.timestamps null: false
end
end
end
I want migrate to Curriculums to Lecturer. But not with id, with title
how it's can be possible?
So i use rails-admin. When i add some Curriculum i want to choose with dropdown lecturer and when i add some Lecturer i want to choose Curriculum between models .
No matter what, you have to have association between two models. Also do not forget to add curriculum_id to lectures table.
curriculum.rb
has_many :lectures
lecture.rb
belongs_to :curriculum
To add migration
rails g migration add_curriculum_id_to_lectures curriculum_id:integer
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.
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.
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