How to inherit from another Rails migration? - ruby-on-rails

I have a Rails migration for a simple User model:
class Users < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, :default => :null
t.float :weight
t.datetime :recorded_at
t.timestamps
end
end
end
I would like to have a second table for the history of the user. It should have the same columns but another name, obviously. Also it should reference the user table.
require_relative '20130718143019_create_history.rb'
class History < Users
def change
create_table :history do |t|
t.references :user
# ...?
end
end
end
How can use inheritence to avoid copying all the migration configuration?

After leaving the keyboard tomatoes fell off my eyes and it was clear how I can set this up:
class Users < ActiveRecord::Migration
def change
create_table :users do |t|
prepare_columns(t)
end
end
protected
def prepare_columns(t)
t.string :name, :default => :null
t.float :weight
t.datetime :recorded_at
t.timestamps
end
end
...
require_relative '20130718143019_create_history.rb'
class History < Users
def change
create_table :history do |t|
t.references :user
prepare_columns(t)
end
end
end

Related

Group has_and_belongs_to_many

Given a model with ActiveStorage: DayFrame, Day, Session. Models and migration see below. DayFrame and Session are many-to-many relationship. day_frames_sessions intermediate join table that includes foreign keys referring to each of the classes DayFrame and Session. How can I get day_frames group by session and sort by day.date like this:
{session_id_1=> [DayFrame1, DayFram2, DayFram3], session_id_2 => [DayFrame2, DayFram1, DayFram4]}
class DayFrame
has_and_belongs_to_many :sessions
belongs_to :day
end
class Day
has_and_belongs_to_many :sessions
has_many :day_frames
end
class Session
has_and_belongs_to_many :conference_day_frames
end
The migrations are:
class CreateDay < ActiveRecord::Migration[5.2]
def up
create_table :days do |t|
t.date :date
t.string :day_type
t.timestamps
end
end
def down
drop_table :days
end
end
class CreateDayFrame < ActiveRecord::Migration[5.2]
def up
create_table :day_frames do |t|
t.string :name
t.time :begin_time
t.time :end_time
t.string :frame_type
t.timestamps
t.references :day, index: true
end
def down
drop_table :day_frames
end
end
class CreateSessions < ActiveRecord::Migration[5.2]
def up
create_table :sessions do |t|
t.integer :number, limit: 1
t.string :title
t.string :short_title
t.boolean :is_active
t.timestamps
end
end
def down
drop_table :sessions
end
end
class CreateDayFramesSessions < ActiveRecord::Migration[5.2]
def up
create_join_table :day_frames, :sessions do |t|
t.index :day_frame_id
t.index :session_id
end
end
def down
drop_table :day_frames_sessions
end
end

"TypeError: no implicit conversion of nil into String" on HABTM association

I have to deal with this error when I try to associate a record to another one via a HABTM association:
Person.first.communities = Communities.all
Models and migrations:
class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :name
t.string :email
t.timestamps null: false
end
end
end
class CreateCommunities < ActiveRecord::Migration
def change
create_table :communities do |t|
t.string :name
t.text :description
t.timestamps null: false
end
end
end
class CreateJoinTablePersonCommunity < ActiveRecord::Migration
def change
create_join_table :people, :communities do |t|
# t.index [:person_id, :community_id]
# t.index [:community_id, :person_id]
end
end
end
I use the pg (0.18.4) gem with the Postgres (9.5.2)
Youcan use below code to create relationship.
Person.first.communities << Communities.all
If this not works please check your associations via reflect association method on the model.

How To add new table and link it with previous table in with adding index in ruby

I have this table structure:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :username
t.string :email
t.string :encrypted_password
t.string :salt
t.timestamps
end
end
end
And I want to add a new table as shown below:
class CreateHolidays < ActiveRecord::Migration
def change
create_table :holidays do |t|
t.string :earn_leave
t.string :seek_leave
t.string :unplanned_leave
t.timestamps
t.timestamps
end
add_index(users,id)
end
end
What should I do for this, please also suggest commands that can/should be used for migration.
You want to look up about foreign_keys:
#app/models/holiday.rb
class Holiday < ActiveRecord::Base
belongs_to :user
end
#app/models/user.rb
class User < ActiveRecord::Base
has_many :holidays
end
This will mean you have to add the user_id foreign key to your holidays data table:
class CreateHolidays < ActiveRecord::Migration
def change
create_table :holidays do |t|
t.references :user
t.string :earn_leave
t.string :seek_leave
t.string :unplanned_leave
t.timestamps
t.timestamps
end
end
end
You must remember that Rails is designed to be built on top of a relational database. As such, it uses foreign_keys in the tables to locate associated records:
The above will allow you to call:
#user.holidays
and
#holiday.user

How to add database level foreign key in the migration file in rails 4.2?

I have gone through some of similar question people asked but couldn't find the appropriate solution for it. I have also seen some people using this method - add_foreign_key
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
but it is throwing undefined method error.
undefined method `add_foreign_key' for
#<CreateTaskLists:0x007ffe9a5cd578>
/Users/sushilkumar/.rvm/gems/ruby-2.2.3/gems/
activerecord-4.0.0/lib/active_record/
migration.rb:624:in `block in method_missing'
How to add foreign key in rails migration with different table name
I don't know, How does this work for them?
You can simply try this way using references
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user, index: true
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user, index: true
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
try this
Did you meant to reference the table User and not Users? If so, you must use the singular (:user) when making a reference:
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
Hope this will work for you.
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user
t.timestamps
end
add_foreign_key :users, :task_lists
end
end

Inheritance with ActiveRecord at the same time

I have a class 'Report' that has columns 'description', 'pending', etc.
/app/models/report.rb
class Report < ActiveRecord::Base
end
class CreateReports < ActiveRecord::Migration
def change
create_table :reports do |t|
t.boolean :pending, :default => true
t.boolean :accepted, :default => false
t.text :description
t.timestamps null: false
end
end
end
But I also have two other classes: ReportPost (when a User report a Post), and ReportTopic (when a User report a Topic). I used this approach because I can user 'belongs_to :topic' for ReportTopic and 'belongs_to :post' for ReportPost. So, here comes the problem:
Since ReportPost and ReportTopic have the same columns of 'Report', I need to use the inheritance from 'Report'. But I also need to use ActiveRecord inheritance to capture new attributes from :report_topic migrates.
But, how?
Here are the other classes:
class ReportTopic < Report
belongs_to :topic
end
class ReportPost < Report
belongs_to :post
end
`And, the migrates:
class CreateReportPosts < ActiveRecord::Migration
def change
create_table :report_posts do |t|
t.belongs_to :post
t.timestamps null: false
end
end
end
class CreateReportTopics < ActiveRecord::Migration
def change
create_table :report_topics do |t|
t.belongs_to :topic
t.timestamps null: false
end
end
end
You could use Single Table Inheritance (STI) in this case. Just add a column named 'type' to your report table.
def change
create_table :reports do |t|
t.boolean :pending, :default => true
t.boolean :accepted, :default => false
t.text :description
t.string :type
t.timestamps null: false
end
end
Rails will understand this as STI. Any subclass that you may create will have its type equal to the name of the class (e.g. type = 'ReportTopic')

Resources