I've been trying to find a way to achieve this but I cannot find any attempts even so I am thinking that maybe my approach is completely wrong. That said, what should I do in my migration if I want a combination of two fields to be unique? Please note that I do not want them to be indexes, just database fields.
For example, for the migration below, I can separately add unique: true to the fields, but the combo?
class CreateSomething < ActiveRecord::Migration
def change
create_table :something do |t|
t.date :datestamp, :null => false
t.integer :some_number, :null => false
t.timestamps
end
end
end
I'm not sure what you mean by
Please note that I do not want them to be indexes, just database fields.
Indexes are extra pieces on information that the database stores about the columns.
More importantly an index is exactly what you need!
class CreateSomething < ActiveRecord::Migration
def change
create_table :something do |t|
t.date :datestamp, :null => false
t.integer :some_number, :null => false
t.timestamps
end
add_index :something, [:datestamp, :some_number], unique: true
end
end
Related
I have designed the following migration and wanted to check with the community is that is meeting the best practices of rails migration. I am running a postgres db.
I am trying to achieve a db structure where the various status attached to a user is stored in a separate table. for instance, its marital status.
let me know if that sounds like a reasonably efficient table design. and what I could improve.
class CreatePrequalifications < ActiveRecord::Migration[5.2]
def change
create_table :prequalifications do |t|
t.string :attachment
t.text :description
t.integer :marital_status
t.integer :professional_status
t.integer :collateral_status
t.integer :income_direct
t.integer :income_support
t.integer :income_scolarship
t.integer :income_other
t.boolean :blacklist
t.references :user, foreign_key: true
t.timestamps
end
end
create_table :marital_status do |t|
t.string :single
t.string :married
t.string :other
t.string :divorced
t.string :with_dependants
t.references :user, foreign_key: true
t.references :prequalifications, foreign_key: true
end
create_table :professional_status do |t|
t.string :self_employed
t.string :employed
t.string :student
t.string :other
t.text :description
t.datetime :contract_created_at
t.datetime :contract_terminated_at
t.references :user, foreign_key: true
t.references :prequalifications, foreign_key: true
end
create_table :collateral_status do |t|
t.string :collateral_name
t.string :collateral_income
t.boolean :visale_collateral
t.boolean :student_collateral
t.boolean :bank_collateral
t.references :user, foreign_key: true
t.references :prequalifications, foreign_key: true
end
end
In this case, best practices would dictate:
Break each create_table into its own migration.
Your table names should be pluralized, e.g. marital_statuses.
Time stamps are a good idea.
Consider adding indexes to fields that will be queried regularly, e.g. model names, user emails, or foreign keys.
Check out the rails guide on migrations for information about best practice: https://edgeguides.rubyonrails.org/active_record_migrations.html
Let's start with:
Is it a single migration? If so, I would start with splitting it into several migrations (one for each table).
Add timestamps for each table (t.timestamps null: false). You will thank me later ;)
For statuses tables (martial_status, professional_status) create simpler tables with just name and references (no need to create column for each value). Also, you probably do not need the table for marital status, because you can use classy_enum instead.
In prequalifications you have integer columns for relations (maritial_status, professional_status). Don't do that, use references.
For boolean columns, define default values.
So I've been successfully creating join tables by using the name parameter when adding an index, but I'm not sure why this isn't working when I'm trying to do create a new migration:
class CreateVMailCampaignScheduleHours < ActiveRecord::Migration[5.1]
def change
create_table :v_mail_campaign_schedule_hours do |t|
t.belongs_to :v_mail_campaign_schedule, foreign_key: true
t.string :day
t.time :start_hours
t.time :stop_hours
t.timestamps
end
add_index [:v_mail_campaign_schedule_hours, :v_mail_campaign_schedule_id], name: :v_mail_campaign_schedule_id
end
end
The error I get is:
ArgumentError: Index name
'index_v_mail_campaign_schedule_hours_on_v_mail_campaign_schedule_id'
on table 'v_mail_campaign_schedule_hours' is too long; the limit is 64
characters
Any suggestions? I thought my add_index would do the trick, but apparently not.
You can change it to the following:
class CreateVMailCampaignScheduleHours < ActiveRecord::Migration[5.1]
def change
create_table :v_mail_campaign_schedule_hours do |t|
t.bigint :v_mail_campaign_schedule
t.string :day
t.time :start_hours
t.time :stop_hours
t.timestamps
end
add_index :v_mail_campaign_schedule_hours, :v_mail_campaign_schedule_id, name: :index_campaign_schedule_hours_on_schedule
end
end
Your approach to create the index manually is the right one. However, t.belongs_to, which is an alias for t.references, instructs the creation of both the foreign key column and the corresponding index. So Rails still tries to create the index, before reaching add_index. Using a simple t.bigint doesn't create the index.
Yeah, so as previously said, t.belongs_to will create an index.
So, I think you can still use create_join_table, but you'll just need to specify index: false on your belongsTo.
create_join_table :v_mail_campaign_schedule_hours do |t|
t.belongs_to :v_mail_campaign_schedule, foreign_key: true, index: false
t.string :day
t.time :start_hours
t.time :stop_hours
t.timestamps
t.index [:v_mail_campaign_schedule_id], name: 'v_mail_campaign_schedule_id'
end
I have three models in my Rails 3 application, DailyData and DailyDataVehicle and Vehicle, a many to many relationship.
I just learned that if you update the model with the associations, that it doesn't update the database, so I am going back and adding those migrations. I am also lucky enough to confidently think I know the differences between belongs_to and has_many, however, in my migration file, I am not sure that t.references does.
So I named the migration model AddDailyDataToDailyDataVehicle, and want to add the dailyData_id to the daily_data_vehicles table. This is a many to many relationship, so I want the id key to be in the relationship table DailyDataVehicles, but I'm not quite sure that t.references will know that.
Maybe I am slightly mixing up the class associations and the database relationships, and if I am, then please clarify this.
If t.references is not what I want, do I have to declare the relationship manually with has_many, and if so, what is the syntax for that?
schema file currently:
create_table "daily_data_vehicles", :force => true do |t|
t.integer "vehicle_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "daily_data_vehicles", ["vehicle_id"], :name => "index_daily_data_vehicles_on_vehicle_id"
Migration (attempt):
class AddDailyDataToDailyDataVehicle < ActiveRecord::Migration
def change
change_table :dailyDataVehicles do |t|
t.references :dailyData
end
add_index :dailyDataVehicles, :dailyData_id
end
end
What I think the schema file should look like if the migration works correctly:
create_table "daily_data_vehicles", :force => true do |t|
t.integer "vehicle_id"
t.integer "dailyData_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "daily_data_vehicles", ["vehicle_id"], :name => "index_daily_data_vehicles_on_vehicle_id"
add_index "daily_data_vehicles", ["dailyData_id"], :name => "index_daily_data_vehicles_on_daily_data_id"
with the difference being t.integer "dailyData_id" and add_index "daily_data_vehicles", ["dailyData_id"], :name => "index_daily_data_vehicles_on_daily_data_id"
class AddDailyDataToDailyDataVehicle < ActiveRecord::Migration
def change
add_column :daily_data_vehicles, : daily_data_id, :integer
add_index :daily_data_vehicles, :daily_data_id
end
end
class DailyDataVehicle < ActiveRecord::Base
belongs_to :daily_data
end
class DailyData < ActiveRecord::Base
has_many :daily_data_vehicles
end
I'm using rails 3.2 with the following migration and created_at/updated_at both get generated. I was under the impression that adding t.timestamps was what caused those columns to get generated.
class CreateContactsCountries < ActiveRecord::Migration
def change
create_table :contacts_countries do |t|
t.string :name, :official_name, :null => false
t.string :alpha_2_code, :null => false, :limit => 2
t.string :alpha_3_code, :null => false, :limit => 3
end
add_index :contacts_countries, :alpha_2_code
end
end
Please delete the table and check again becuase
By default, the generated migration will include t.timestamps (which creates
the updated_at and created_at columns that are automatically populated
by Active Record).
Ref this
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.