I'm trying to rename the columns in a Rails project, and I generated migration files and bundle exec rake db:migrate.
Procedures are like this.
generate file,
bin/rails g migration RenameUserTwitterNameToName
and write the method with column names,
def change
rename_column :users, :twitter_name, :name
end
finally execute the rake task.
bundle exec rake db:migrate
Although it works well, I need to modify the controllers related to the columns.
For example, if there is a code like below, I need to change the method find_by_twitter_name to find_by_name
#user = User.find_by_twitter_name(name)
Is there any way to modify the controller like above automatically?
There is no way to modify the controller automatically, but you can make aliases for attributes, which includes getter, setter, and query methods.
class User < ActiveRecord::Base
alias_attribute :twitter_name, :name
end
http://api.rubyonrails.org/classes/Module.html#method-i-alias_attribute
Related
I have created 2 tables (categories and products) and I did has_many association like Category has_many :products and Product belongs_to :category.
When I do a migration like:
rails generate migration add_product_id_to_categories product_id:integer
then migration is running but not seeing product_id in Category.
I've tried multiple ways like
add_product_id_to_category product_id:integer
but still facing the same problem.
You only generated a migration file (rails generate migration add_product_id_to_categories product_id:integer). You have to run the migration with rake db:migrate.
Generating a migration is a different thing than actually running it. You just generated it, and in order to execute what you have written, you need to run it, and you can do so by invoking the following command:
rake db:migrate
Not sure that either you have run the migration or not, run the following command, and it will tell you the statues of all the migrations. If the status is up, the migration has been run, and for down, a migration couldn't be run.
rake db:migrate:status
When you run a migration, and you would like to get notified in terminal that it has been successfully run, you can add a puts statement in there like following:
class AddColumnToCategories < ActiveRecord::Migration
def change
add_column :categories, :product_id, :integer, index: true
puts "product_id column has been added into categories."
end
end
Have you tried rails generate migration AddProductIdToCategories product_id:integer?
When you have created the migration if you look inside the migration file you can see if any code has been generated in the change method before you run the migration. If it has not generated any content you can manually add it:
def change
add_column :categories, :product_id, :integer
end
self explanatory from the title. I have to generate an ERD diagram reflecting customization for primary keys and timestamps in my app, but nothing i'm typing into terminal seems to work. currently using this resource: http://voormedia.github.io/rails-erd/customise.html
i tried something along the lines of
rails g model Comment attribute=primary_keys,timestamps
but my Comment model remains unchanged when i open the erd pdf. any ideas? any constructive input is appreciated. thank you
You should be able to execute the following within your Rails application root directory to generate the ERD diagram for your models:
$ bundle exec erd --attributes=content,primary_keys,foreign_keys,timestamps
Then you'll find a document called erd.pdf within your Rails application root directory.
To add columns to an existing model from the terminal; run a migration:
rails g migration AddPrimaryKeyToModel,
This will generate a new file in app/db/migrate that you would edit to look as follows:
class AddPrimaryKeyToProducts < ActiveRecord::Migration
def change
add_column :model, :id, :primary_key
add_column :model, :timestamp, :datetime
end
end
From the terminal, then run
rake db:migrate
Be aware that ActiveRecord automagically includes :id of type integer and designated as the primary_key, as well as :created_at and :updated_at of type datetime. ERD does NOT show these attributes in the diagram by default and you need to set the ERD attributes to show them in your output file.
Thank you for all your help. I found I could add the attribute using
rake erd attributes=primary_keys
and
rake erd attributes=timestamps
content is the other whole attributes.
to include primary_key and foreign_key plus attributes, do as follow :
rake erd attributes=primary_key,foreign_key,content
tested working on Rails 3.2
You can also create a config file on your project root directory like this:
.erdconfig
title: Project Model Diagram
orientation: vertical
attributes:
- content
- primary_keys
- foreign_keys
- timestamps
I'm very new to ruby on rails, been trying to play around with it in the past few days.
Basically trying to: Create a empty table, with fixed columns - Ruby on Rails
I've created a model like so:
rails g model table
rails g migration table
my tables.rb files looks like this:
class Tables < ActiveRecord::Migration
def change
add_column :table, :firstname, :string
add_column :table, :lastname, :string
end
end
(hopefully I created the columns okay)
I then run:
rake db:migrate RAILS_ENV=development
but seem to get an error no such table: table (but I thought I created it ? )
Also what is a good view I can use to see my table on localhost:3000, in a html.erb file?
What you are displaying as your tables.rb file is a migration file, not a model. Models are stored in app/models. Migrations are in db/migrate and have a name that is a datetime stamp followed by the migration name.
Your migration is performing add_column. You can't add_column until you create_table. That migration should have been built using "rails g model table". Please show all migrations with the entire filename.
Check the document that dax provided. The rails generate command uses a stylized command line. Many standard migration functions, such as creating tables and adding columns, can be automatically generated by using the correct migration name. For example:
rails g migration add_url_to_feed url:string
This will create a migration that adds a string column called url to the feed table.
Generally, migrations should do what you need. However there is another command, rake, that you will need. The reference is here. For example:
rake db:create # Create the database from config/database.yml for the current Rails.env
can create the database for you.
I have already read the documentation of "migrate" on Rails 3 (Rails 3.0 Relese Notes Migrate) but I have some doubts.
e.g. I created two class:
rails generate scaffold User name:string age:integer height:float
rails generate scaffold Hat type:string width:float height:float
This create models, controllers, ... User and Hat and its migrate class: xxx_create_users.rb and xxx_create_hats.rb
Ok, now we guess we want modify User class and we delete height attribute, and we add the relationships between Users and Hats:
User
class User < ActiveRecord::Base
attr_accessible :name, :age
has_many :hats
end
Hat
class Hat < ActiveRecord::Base
attr_accessible :type, :width, height
belongs_to :user
end
Options that I guess:
I remove all files xxx_create_xxx.rb and then I will create again with: rails generate migration CreateUser (and the same for Hat)
I create a new migration file: rails generate migration MyNewMigration where I codify by hand all changes.
Is there another way to automate changes in my classes for passed it to the database? What is the correct way to proceed?
The idea of migrations is that you have a stringent storyline where you can start at any point, forward and backwards. This means that it should not ever be necessary to delete a migration.
Instead, you create a new migration that will change, remove or add database fields.
In your example, you would leave the old migration where it is and then create a new migration like so:
rails g migration change_user_fields
And inside def up you write
remove_column :table_name, :column_name
change_column :table_name, :column_name, :data_type
Add a def down - this will be run whenever the migration is reversed by rake db:rollback. Inside def down put:
add_column :table_name, :column_name # add the field that you removed (s.a.)
change_column :table_name, :column_name, :data_type # change back to old data type
Rails 3 gives you a nice shortcut for adding and removing fields from a table by doing:
rails g migration add_something_to_users name:string
which will automatically create a migration that adds a field called name with a data type of string to the users table. Or
rails g migration remove_something_from_users name
which will automatically create a migration to remove the name field from the users table. These shortcuts and the created migration files do not need a def down - rails will automatically be smart enough to figure that out when reversed.
In both cases, you can replace the word "something" with whatever you like.
However, I know of no way to use a shortcut to change data types, so you need to go in the migration file and do that manually.
Eventually, just run rake db:migrate and you'll be all set!
Scaffold only automate a fixed command, so if you create a model and its attributes with scaffold, your migration will only contain the fields you specify on the command line. There is no way to keep track of changes automatically.
If you add/remove/change something on your database, you have to manually set it. Migrations are useful because you can keep track of these changes on time.
So i recommend you to never delete a migration. In this particular case you described, you just have to create another one to reflect the new change on your database, keeping a total of 3 migrations, instead of deleting and creating another.
The answer to your question should be alternative 2. But you don't have to do it all by hand if you just want to add or remove attributes:
http://guides.rubyonrails.org/migrations.html#creating-a-standalone-migration
All,
I need clarification on how model changes need to tracked in ruby on rails. I started off by creating a model with say two fields, name and email. Here is what i have done
Created a model by running
"rails generate model user first_name:string last_name:string"
This created a model file
I then added some validations to the files created in user
Used the annotation gem to annotate the class
used "bundle exec rake db:migrate" to move my model to database which created the tables
I now want to add a couple more fields to the model. What steps do i need to follow?
Do i add columns to the database and run some command so that the model(class) is in sync with the db?
Do i delete and recreate the whole model with the new fields?
what is the recommended approach
Venu
You want to use a migration to update the existing table, you can do the entire process from the command line
Assuming you've done
rails generate model user first_name:string last_name:string
previously you would add fields like so;
rails generate migration AddFieldsToModel new_field:string another_field:string....
Rails does magic on the 'AddFieldsToModel' and works out the table name from the value for you.
Once you've created the migration you can look at it in db/migrations and then if you're happy with it just run
rake db:migrate
this will update your database to add the new fields to it. You don't need to do anything to the actual model.rb file - but you will need to re run the annotate task to have it reannotated to the model.rb file.
I am not sure what version of rails your are using .. but int rails 3.x it can be done as
rails generate migration add_fields_user
this creates a file in db/migrate/[timestamp]/add_fields_user.rb
now you can write in the file and run rake db:migrate
add_column :users , :city, :string
What you want to do is run a migration by typing. rails generate migration description_of_migration. This will create an empty migration which you can define what you want to add to your model. In your case it may be something like this:
class DescriptionOfMigration < ActiveRecord::Migration
self.up
add_column :users, :email, :string
end
self.down
remove_column :users, :email
end
end
This makes it so you can migrate both ways on the model.