I study a e-book of Ruby on Rails:
If I create a Active Record below:
class Product < ApplicationRecord
end
Rails Will execute the below code to generate a table:
CREATE TABLE products (
id int(11) NOT NULL auto_increment,
name varchar(255),
PRIMARY KEY (id)
);
There I have a question, I can understand auto generate the major key, but why how to understand the:
name varchar(255),
If the name field is auto generated? and if yes, why it is necessary?
Yes, it will be auto generate. But it's not a activerecord action, it's related to the database. For mysql, if you doesn't set default value for the column, then it will default be NULL, nil in ruby.
Even you didn't set value for specific column, it also need to be display in the database, or visit as product.name, so do necessary.
No,the sql statement to create the table 'products' is not from your model file(product.rb), but from migrate files.
Where you run a Rails rake command: rake g model product name:sring,
it will not only create a model file(product.rb) for you, but also a migrate file in "db/migrate/" folder, naming like "xxxxxx_create_products.rb". Open this file and you will see lines like:
def change
create_table :products do |t|
t.string :name
end
end
That's how Rails knows what columns you want to have in your "products" talbe, and what type they should be.
And this table will not be created, until you run this command: rake db:migrate.
Related
I have the following model:
class Product < ActiveRecord::Base
end
How can I add a field to it?
What is the type of the field you wish to add? If it is a string do it like below:
rails generate migration add_field_to_products field:string
Where 'field' is the name of the field you want to add, so rename accordingly.
Then do in the command line rake db:migrate and after that the field should be in the model.
Also, this question is a duplicate of: Adding a column to an existing table in a Rails migration . There is more discussion of this there if it's still unclear.
You should generate a separate migration with rails g migration [name], where you declare your column:
add_column :products, :[column_name], :[datatype]
Where [column_name] is the name of the column you want to add and [datatype] stands for it's datatype: string, integer and etc.
After that you should run migration with rake db:migrate to add new column to your table.
I need a HABTM join table for item_ones and item_twos, but I can't seem to get the migration results to match Rails's expectations. If I do this:
create_join_table :item_ones, :item_twos do |t|
...
end
(...which is what rails g migration CreateJoinTableOneTwo item_one item_two generates...)
..then it creates a table named item_ones_item_twos, but Rails will be looking for item_ones_twos (because in 4.0, it factors out common prefixes). If I do this:
create_join_table :item_ones, :twos do |t|
...
end
Then it creates the right table, but the second foreign key is named two_id instead of item_two_id.
So is there any way to get this right other than e.g. manually specifying a :table_name?
Normally, Rails would expect a join table name of <first model>s_<second model>s (eg. assemblies_parts) for any HABTM join tables. However, because ItemOne and ItemTwo have the same prefix (Item), Rails shortens the required table name to item_ones_twos.
You will need to specify the table_name option, as detailed here: http://edgeguides.rubyonrails.org/migrations.html#creating-a-join-table
Want to do rails migration but i want the column name to be something like external_id but I don't want to any model with external . i think rails by default , whenever sees _id as suffix it looks for foreign key association and if it doesn't exist migration is canceled.
what's the solution for that. I have
def self.up
create_table :external_mappings do |t|
t.string :external_name
t.integer :external_id
t.timestamps
end
end
Thanks for your help
when i make it t.integer :externalId migration works. that make me think external_id is looking for foreiegn key reference, is there any way we can suppress foriegn key reference. I am using rails 2.3.5
You can give to any column a _id name and reference foreign keys without the _id also, so feel free to continue. It is just a convention on which Rails relies to target the model-name_id, but with no trouble it can be defined differently.
No, rails does not cancel any migration due non existent model.
I wonder if the original poster created the new model using scaffolding and the "references" type. If that is the case, the migration would have failed during it's attempt to creating the foreign key.
Otherwise, if it's just an integer, there is nothing wrong with adding an _id to the end of an otherwise acceptable column name.
I am trying to add one column in one table using migration up. I have created migration for that and ran rake db:migrate:up[version] it added the column in my table but I don't see that attribute in my respective model. Am I missing something here to do? Below is my snippet ...
migration 6, :add_role_users do
up do
execute <<-SQL
ALTER TABLE users
ADD COLUMN role varchar(32) DEFAULT NULL
SQL
end
down do
execute <<-SQL
ALTER TABLE users
DROP COLUMN role
SQL
end
end
After running the above migration I don't see below line in my User model
property :role, , String, :length => 32
Please suggest, I am using Rails 3.0 so I can't use migration Change method.
Rails automatically detects and assigns model attributes based on your table's columns. For some generic information about how this is done, this guide is invaluable: http://guides.rubyonrails.org/migrations.html
Anyway, here's how I would run a migration that adds a role column to the users table.
In your console, run rails g migration add_role_column_to_users role:string. (Since the migration name ends with "users", Rails will automatically know to apply this migration to the users table. Specifying role:string is just a command line shortcut that automatically adds t.add_column :role, :string to your migration. After running this command you should be able to find your new migration in the db/migrate/ directory of your app.)
In your console, run rake db:migrate to migrate the database to your new schema.
That's it! You should now have a "role" column on your "users" table. You can verify this by entering your Rails console with rails c, and bringing up your user model's column names with User.column_names. You should see "role" there.
I created a new model in my rails app. Since it's a one-to-one relation with another table, there's no need for the new model to have an id column. Everything is working fine, but for some reason, all of my Shoulda tests on this model are failing. For example:
should_validate_presence_of :first_name
is throwing this error:
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'my_new_table.id'
in 'field list': SELECT `my_new_table`.id FROM `my_new_table` WHERE
(`my_new_table`.`some_other_column` IS NULL) LIMIT 1
Does Shoulda require an ID column? If so, is there a way around this?
Did you alias the primary key for Rails purposes?
set_primary_key :my_fk_id
Rails expects your models to have an integer id column as a primary key. You can set it to the foreign key like #MattMcKnight suggests but I'd recommend you create the id column even if you don't strictly need it. In my experience it will save you tons of headaches like this, with basically no downside.
Did you run rake db:migrate and rake db:test:prepare after you created the new model?
All tables require an id column that's just the way that ActiveRecord works. As MattMcKnight points out, you can designate another column as the primary key. You can also specify that a table have no id column is creatied by providing :id => false as an option to create_table.
Matt's answer covers renaming the primary key in the model definition. Here's how to do it in a migration.
Note, providing the primary key option without giving the id option as false means that you do not have to add to column's definition to the block. Rails will create it for you. And automatically use it in any join tables.
Example:
class CreateTableWithOUtID < ActiveRecord::Migration
def self.up
create_table :my_new_table, :primary_key => :another_table_id do |t|
t.string :some_other_column
end
end
def self.down
drop_table, :my_new_table
end
end