Query to define a default value in a database migration - ruby-on-rails

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

Related

Rails Activerecord adding columns to multiple tables

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.

Rails 4 Migration

I had a table posts with column content of string type(255), when i migrate changes,to change type of string to text,it really change that type,but i get text(255) what does nothing.What im must to do to get such result :
TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT2 | :limit => 1 to 4294967296 (default = 65536)2
p.s. on my localmachine i can create posts of any long and type of string,but on heroku i get
PG::Error: ERROR: value is too long for type character variyng(255)
my _change_datatypes_on_posts_from_string_to_text.rb
class ChangeDatatypeOnPostsFromStringToText < ActiveRecord::Migration
def change
change_column :posts, :content, :text
change_column :posts, :title, :text
change_column :users, :name, :text
end
end
Try using the limit attribute...
eg : "change_column :posts, :content, :text, limit: nil".
On Postgres, a :string, limit:nil is effectively synonymous with :text.

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.

Create a set column with database migration in rails

I need to add a new column to my users table in the database. I want the type of the column to be set. The column represents the users gender. There should be two options to the set. One form Male "m" and the other for Female "f".
But I haven't found any documentation for adding a column with the set type.
How can I do this?
What db is used? mysql? If you're want to use SET datatype, you'll have to do it manually, as rails doesn't support it. However, I'd do just
t.string :gender, :limit => 1
for the sake of convenience.
In your Users model, you should add the following line to require M/F answers.
validates_inclusion_of :gender, :in => %w( m f M F)
I think you want to add the gender column with a default datatype (correct me if I'm wrong), If so there would be the step
here I'm assuming 'M' is for male and "F" is for female (you can use integers also if you wish)
create a migration
ruby script/generate migration add_gender_column_to_users
This will create a migration for you and as the name implies it will add a gender column to your users table
in your migrations self.up action add this
add_column :users, :gender, :string, :default => 'm'
here it says we are adding a gender column of string type and its default values is 'm'
and add this to self.down events
remove_column :users, :gender
so your final migration will look something like this
class AddGenderColumnToUsers < ActiveRecord::Migration
def self.up
add_column :users, :gender, :string, :default => 'm'
end
def self.down
remove_column :users, :gender
end
end
and do a
rake db:migrate
thats it, hope this helps

In a Rails migration, is it possible to indicate that a newly added column should be before or after an existing column in the table?

Let's say I create a table in a Rails migration, specifying to omit the ID column:
create_table :categories_posts, :id => false do |t|
t.column :category_id, :integer, :null => false
t.column :post_id, :integer, :null => false
end
Later I decide I want to add an ID column as a primary key so I create a new migration:
class ChangeCategoriesToRichJoin < ActiveRecord::Migration
def self.up
add_column :categories_posts, :id, :primary_key
end
def self.down
remove_column :categories_posts, :id
end
end
But when I look at the table after I migrate, it looks like this:
category_id
post_id
id
The id column is in the last position in the table, whereas normally an id column would be first.
Is there a way to change the ChangeCategoriesToRichJoin migration to insist on the id column being created BEFORE the category_id column in the table?
Or do I need to drop the table and add the column in the "create table" definition?
Use :after => :another_column_name, e.g.:
change_table :users do |t|
t.integer :like_count, :default => 0, :after => :view_count
end
I haven't been able to put the columns in order, myself, but with Rails you can rollback, alter the old migration file to add the new columns in the order you want, then re-migrate up the old migration including the new field. It's not exactly ideal, but the ability to migrate and rollback easily, it can work if you're OCD enough to require column order. :P
I am not an expert, but I've read a lot of Rails documentation (and very recently) and can't recall finding a solution for this.

Resources