Rails Activerecord adding columns to multiple tables - ruby-on-rails

I need to make a migration where a column is added to three separate tables. The views column is an integer and needs to also default => 0. How can I add these columns with activerecord commands? I am using postgreSQL database.
Here is how my migration should look like:
class AddViewsToRestaurantsMenusDishes < ActiveRecord::Migration[6.0]
def change
add_column Restaurant, :views, :integer, :default => 0
add_column Menu, :views, :integer, :default => 0
add_column Dish, :views, :integer, :default => 0
end
end

add_column(table_name, column_name, type, **options)
class AddViewsToRestaurantsMenusDishes < ActiveRecord::Migration[6.0]
def change
add_column :restaurants, :views, :integer, default: 0
add_column :menus, :views, :integer, default: 0
add_column :dishes, :views, :integer, default: 0
end
end
None of the methods in ActiveRecord::ConnectionAdapters::SchemaStatements or ActiveRecord::ConnectionAdapters::TableDefinition which make up the whole migrations DSL take models as arguments - its all tables all the way.
This assumes that your tables are conventionally named. If you really wanted to do the same thing from a list of model classes you could do:
class AddViewsToRestaurantsMenusDishes < ActiveRecord::Migration[6.0]
def change
[Restaurant, Menu, Dish].each do |model|
add_column model.table_name, :views, :integer, default: 0
end
end
end
But for migrations its usually a good idea to KISS. Especially since they are not supposed to stick around for the entire lifetime of your project.

Related

ActiveRecord change column default value (not working)

I've got a companies table in my database with two columns (size and state) that I wish to add default values to. Currently there is no default value and the columns are not set to null: false. I've tried using the update_column and update_column_default methods as outlined in the docs, but neither seems to be doing anything. I'm able to run the migration but there are no changes to the table.
I've tried update_column like so:
class AddDefaultValuesToCompanies < ActiveRecord::Migration
def change
def up
change_column :companies, :state, :string, default: 'MA'
change_column :companies, :size, :string, default: '1-10'
end
def down
change_column :companies, :state, :string, default: nil
change_column :companies, :size, :string, default: nil
end
end
end
I've also tried using update_column_default like so:
class AddDefaultValuesToCompanies < ActiveRecord::Migration
def change
def up
change_column_default(:companies, :state, 'MA')
change_column_default(:companies, :size, '1-10')
end
def down
change_column_default(:companies, :state, nil)
change_column_default(:companies, :size, nil)
end
end
end
What am I missing here?
Your migration will only change the default value for newly created records. I would write a rake task to update the existing values in the DB. Use something like
Companies.where(state: "").map{|c| c.update_attribute(state: "ma")

Query to define a default value in a database migration

In this SO article I can see how to add a default value to a certain table:
Add a default value to a column through a migration
change_column :shops, :currency_id, :integer, :default => 1
I have another table currencies that has an ID and also a ISO_Name. I want the system to use EUR as default value. But it's possible that this has ID 5 or ID 1 or ...
So my question: How can I define a default value that is based on the result of a query? For example Currency.find_by_iso_code('EUR').id
As you have iso_name field in the currencies, you can achieve it by the following code.
change_column :shops, :currency_id, :integer, :default => Currency.find_by_iso_name('EUR').id
How about:
class SetDefaultCurrencyForShops < ActiveRecord::Migration
def up
currency = Currency.find_by_iso_code('EUR')
if currency
change_column :shops, :currency_id, :integer, :default => currency.id
end
end
end

Migrations: change column from integer to string

Can anyone show me how to edit the following migration to change :phone integer to string?
class CreateContactInfos < ActiveRecord::Migration
def change
create_table :contact_infos do |t|
t.integer :phone
t.string :facebook
t.references :user
t.timestamps
end
add_index :contact_infos, :user_id
end
end
Thanks in advance!
I guess you already migrated the one you're showing, so create another in which you'd put:
change_column :contact_infos, :phone, :string
I have added some more explanation to this.We need to generate a new migration
rails g migration change_phone_to_be_string_in_contact_infos
If we open up the migration we should see something like this
class ChangePhoneToBeStringInContactInfos < ActiveRecord::Migration[5.0]
def change
end
end
What we call this migration will have no impact on what we need to do next, but future we and other developers will thank us for naming our migration appropriately.
As you can see the change method is sitting empty. We need to manually add some code here.
class ChangePhoneToBeStringInContactInfos < ActiveRecord::Migration[5.0]
def change
change_column :customers, :phone, :string
end
end
After Saving this file just do rake db:migrate we can see changes we want.
For a reversible migration, use:
def up
change_column :contact_infos, :phone, :string
end
def down
change_column :contact_infos, :phone, :integer, using: "phone::integer"
end
Convert column type string into integer in rails migration :
def change
change_column :contact_infos, :phone, :integer, using: 'phone::integer'
end
Convert column type integer into string in rails migration:
def change
change_column :contact_infos, :phone, :string, using: 'phone::string'
end

How can I add a column to reference to another table on RoR?

Here is the Customer:
class CreateCustomer < ActiveRecord::Migration
def self.up
create_table :customers do |t|
t.column :email, :string, :null => false
end
end
def self.down
drop_table :customers
end
end
And this is the customer Info:
class CustomerInfo < ActiveRecord::Migration
def self.up
create_table :statuses do |t|
t.column :statuses, :string, :null => false
end
end
def self.down
drop_table :status
end
end
What I would like to do is the customer and customer Info have a one to one relationship. How can I do it in a new migration? thank you.
When you want a 1 to 1 in Rails, you have to decide which one of the models will store the foreign key. In your case, you probably want status to store the fk, so add an integer column called customer_id to the status table. Then you can add the has_one/belongs_to on Customer and Status. belongs_to always goes on the model with the foreign key.
Also I'm not sure if Rails will like you calling your table with the singular name, so you will probably have to do some extra work if you really want to call it 'status' instead of 'statuses'
You can try following thing in your next migration
add_column :customer_infos , :customer_id , :integer ,:references=>"customers" , :null=>:true
Then you can add the has_one/belongs_to on Customer and Cusomer_infos .
You can also execute an SQL statement.
statement = "ALTER TABLE users CHANGE id id SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT" ActiveRecord::Base.connection.execute(statement)
you can entry manually in your migration
Note this is just an example. The final SQL statement syntax depends on the database.

Alter existing model with a Redmine plugin

The Redmine plugin tutorials explain how to wrap core models but what I need is to add another column to the journals table.
I need a boolean field inserted in the journals model. Creating another model with a 'belongs_to :journal' relation seems like an overkill.
Can this be done with a plugin?
I should note that I am a rails newbie.
You just have to create the appropriate migration.
In your plugin's directory, create the file db/migrate/update_journal.rb with the following :
class UpdateJournal < ActiveRecord::Migration
def self.up
change_table :journal do |t|
t.column :my_bool, :boolean
end
end
def self.down
change_table :journal do |t|
t.remove :my_bool
end
end
end
Then you can execute the task rake db:migrate_plugins RAILS_ENV=production to update your database with the new field.
After executing the migration, your journal database will have the my_bool field that you'll be able to call like every other field.
I was able to extend the existing user model using the following code:
class UpdateUsers < ActiveRecord::Migration
def up
add_column :users, :your_new_column, :string, :default => ''
add_column :users, :your_other_new_column, :string, :default => ''
end
def down
remove_column :users, :your_new_column
remove_column :users, :your_other_new_column
end
end
Also I needed to name the migration file in way that it began with a number eg. myplugin/db/migrate/001_update_user.rb

Resources