Rails 3, generate migration with foreign key - ruby-on-rails

How I can do or generate a migration with a foreign key? I have municipios table, and I want to relate with the table ciudades, the table will have these fields: nombre_id (name id), nombre (name), departamento (department) in this case how I can run the scaffold script to generate the foreign key migration?

If you mean that you want to create the migration file the command is
rails generate migration NAME [field:type field:type] [options]
or shortcut
rails g migration NAME [field:type field:type] [options]
But if you want to create a scaffold from model that referencing other model. Maybe you could do it like this
create ciudades model with scaffold
rails g scaffold ciudades nombre_id:integer nombre:integer departamento:string
create municipios model that reference ciudades
rails g scaffold municipios ciudades:references
this will create attribute ciudades_id on the municipios table.
The migration should look like this.
class CreateMunicipios < ActiveRecord::Migration
def self.up
create_table :municipios do |t|
t.references :ciudades
t.timestamps
end
end
def self.down
drop_table :municipios
end
end
also on the municipios model it will create the belongs_to relation.
but this does not update the cuidades model. You have to specify the relation.
Also keep in mind that rails automatically create id field on a model. it is the convention. if you mean that nombre_id is the primary key, you have to specify it your self.
Hope this help

Scaffold will not create the relationships for you. It will create views, controllers and others but the rest (relationships) need to be coded by hand.
So you scaffold "municipios", but if you want municipio has many ciudades, you need to do it yourself. For example:
When scaffold gives you:
<% form_for([#municipio]) do |f| %>
You need to change it to:
<% form_for([#municipio, #ciudad]) do |f| %>

Related

create migration for model that in subdirectory

I have a 'question' model in Subdirectory Exceed::Question.
now I want to add migration for Question model, so I run
rails g migration AddImageToExceedQuestions
after that when I run `rake db:migrate
Its show error -
Mysql2::Error: Table 'bs_development.questions' doesn't exist: ALTER TABLE `questions`
In my database question model save as exceed_question.
I also try rails g migration AddImageToQuestions and rails g migration AddImageToExceed::Questions but get same error.
How I can create migration for model that in subdirectory.
In ActiveRecord migrations are not actually tied to model classes. They simply modify the schema and database tables but do not care about if your models actually exist at all.
The rails generators are smart enough to recognize some forms such as rails g migration AddNameToFooBar name:string which would generate:
class AddNameToFooBar < ActiveRecord::Migration
def change
add_column :foo_bars, :name, :string
end
end
Rails will recognize that the part after to is a table name and snake case it. And then pluralize the last word if it is singular.
rails g migration add_name_to_foo_bar name:string creates an identical migration. The same with rails g migration add_name_to_foo_bars name:string except for the file & class name of the migration.
You can fix your issue by opening up the migration file and ensuring that it has the correct table
class AddImageToExceedQuestions < ActiveRecord::Migration
def change
add_column :exceed_questions, :image, :string # or binary
end
end
Note that your table should be named exceed_questions, tables in rails use the plural form of the table name.

What is the correct way to generate multi-word reference fields in rails

rails generate model product name:string twoWord:string twoWordRef:references
produces the following migration file
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.string :twoWord
t.references :twoWordRef, index: true
t.timestamps null: false
end
add_foreign_key :products, :twoWordRefs
end
end
I thought that field names were supposed to be snake case, not camel case, yet rails generate model is producing camel case field names in the migration file. I think I am following the examples on my generate command.
I am also finding issues later on when I try to update via reference where rails assumes the foreign key is in snake case and can't find my foreign key in the table.
What am I doing wrong? Thanks
Rails automatically generate the database tables in snake case. For example if your model is TestModel corresponding table in database will be test_models. However same is not the case for attributes.
Do this instead:
rails generate model product name:string two_word:string two_word_ref:references
Update
This is completely out of scope for what OP asked, but I thought sharing this might be helpful if you are starting Rails. Rails uses a few conventions when naming models and tables (like singular name for model and plural for table). For this it uses ActiveSupport::Inflector module.
The Inflector transforms words from singular to plural, class names to
table names, modularized class names to ones without, and class names
to foreign keys. The default inflections for pluralization,
singularization, and uncountable words are kept in inflections.rb.
You can use its classify and tableize methods to validate corresponding names. Eg:
"test_models".classify
# => "TestModel"
"TestModel".tableize
# => "test_models"

Guidelines about using of migrate on Rails

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

Rails 3 ActiveRecord Table Name Issue

I'm on Windows XP...
Ruby 1.9.2
Rails 3.0.9
MS SQL Server 2005
I'm using tiny_tds + activerecord-sqlserver-adapter
In my database I have table named t4.
I have created a model like this: rails generate model t4
Here is my simple model t4.rb:
class T4 < ActiveRecord::Base
end
Here is migration file 20111013125957_create_t4s.rb:
class CreateT4s < ActiveRecord::Migration
def self.up
create_table :t4s do |t|
t.timestamps
end
end
def self.down
drop_table :t4s
end
end
I have schema.rb:
...
create_table "t4", :force => true do |t|
t.string "title", :limit => 50
end
...
Problem:
When I try T4.select("title").where(["id = 3"]) I get error message:
ActiveRecord::StatementInvalid: TinyTds::Error: Invalid object name 't4s'.: SELECT title FROM [t4s] WHERE (id = 3)
P.S.:
I have another some tables named Adddocs and Eclaims.
There are not problems with queries to them.
I guess that problem is that T4.select("title").where(["id = 3"]) maps to SELECT title FROM [t4s] WHERE (id = 3) (T4 to t4s).
Why? I don't know
But when I edited file config/initializers/inflections.rb like this:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 't4', 't4'
end
Everything works! But it's not suitable solution (bad tone i think) :(((
By convention, if you create a model named album, rails will create a table called albums.
To override this (which isn't usually done) and use a custom defined table name you can use set_table_name method like this in your model:
class Album < ActiveRecord::Base
self.table_name="album" * define here whatever table name you have
end
When you create a new model it is the singular of the object your storing, whereas when it then generates the table, it uses the plural as there are multiple stored within the table. Example...
If you create a model named user, you'll end up with app/models/user.rb but the table it makes will be called users.
If you don't like that you have a few options...
You can override the inflections as you've done, however you should only do this if Rails is getting the pluralization wrong, rather than forcing it to use a certain word.
You can override the table name using the set_table_name method in the model file, providing it with a parameter of what your table name actually is.
You could disable the whole pluralized table names with config.active_record.pluralize_table_names = false in your config/application.rb file, however I strongly recommend you don't do this.
Ultimately I would suggest using more descriptive table names which can be pluralized over ones that can't. T4 as a model and table name don't explain to me what's stored within, where as Post does.

scaffolding and updating attributes manually in ruby on rails howto?

I was wondering if anyone knew how to update the files (adding/removing/updating an attribute) produced by using the scaffold generator in ruby on rails.
For example:
scaffold student name:string lastname:string
so this will create a the associate files (controller,view,etc) with name and lastname as string attributes. When you db:migrate the project, it'll create the table in the database. However, say I want to update whether it be update it with an addition attribue (ex. studenId:integer) or if its removing or updating an attribute, how do you do that?
I tired just updating the generated files, but when I do that db:migrate it still sets the schema that is generated to what is in the table. Is there a built in script in rails that will update the table?
Any advise appreciated?
Thanks,
D
Full command in this example:
$ rails generate migration add_studentid_to_student
You need new migration file for new attributes, from console:
$ script/gnerate migration add_sudentid_to_sudent
it will generate your_app/db/migrate/8293898391_add_sudentid_to_sudent.rb, spicify in this file your new attributes:
def self.up
add_column :sudents, :studentId, :integer
end
def self.down
remove_column :students, :studentsId
end
after that, back to console:
$ rake db:migrate
and than you can edit your views, model, controller files and use new attribute
Hi Try ruby script/destroy scaffold student and then ruby script/generate scaffold student
also try reading up on rails migrations, for dropping/updating table columns.
http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

Resources