I have an existing database(Postgresql). How can i create models from it? How can i pass column names for Rails? As if something like this:
Person:
Name :table_name_for_name_attribute
Surname :table_name_for_surname_attribute
PersonalCode :table_name_for_perconal_code_attribute
Unfortunately, my database is not following Rails convention, because not all tables are named in English. Any ideas how can i map it?
UPDATE reverse_scaffold script generates only model, but i need controller and view forms also.
You can define a table name not matching the model's using the table_name method.
class MyModel < ActiveRecord::Base
def self.table_name
'my_table_name'
end
end
Change the value of 'my_table_name' to your effective table name.
For generating controllers and views with automatic methods to create, update, delete and view database objects, you should create a scaffold. There's some pretty good documentation on the rails guides about that.
In your model, you'll need to tell ActiveRecord what the table name and primary key field column is named if they don't follow the conventions.
class MyLegacyTable < ActiveRecord::Base
self.table_name = "some_name"
self.primary_key = "some_name_primary_key_field"
end
Once you've done that, ActiveRecord knows the some_name_primary_key_field as id, which makes life much easier.
Rails doesn't need to know the column names it figures them out when it connects to the database.
As others have said you can specify a table name in the model.
As for generating controllers/views, you're pretty much own your own. script/generate scaffold is deprecated. It still works as far as creating things, but you need to pass all column names and times on the command line.
Instead have a look at the ActiveScaffold Plugin, it has a similar end result. But is much more robust and easier to adapt to model changes.
Related
To my knowledge, you specify your model field data types within db/migrations . This is new to me as in Django, you can directly specify your model field data types in the Model class. Am I correct in thinking about this? Is this a common practice in rails or am I just using a work around?
Also, how do you specify table relationships in this db/migrations file. For instance if I have a model that is called class A.
I have another model called class B and I want a one to many relationship with class A. Do I just do
class ClassA < ActiveRecord::Migration
def change
create_table :projects do |t|
t.classB :name
end
end
end
How do I validate that my migration file and my model file don't have any syntax errors. To my knowledge I just run rake db:migrate, but what if I don't want my migration file to be replaced as I specified my field datatypes in the file?
Ok, so all in all you seem to have three questions:
1.: To my knowledge, you specify your model field data types within db/migrations. [...] Am I correct in thinking about this? Is this a common practice in rails or am I just using a work around?
Yes, you are correct about this. Field data types do not show inside the model, only in your migration.
By the way: I rarely find myself writing migration files manually. If you use the rails command, it will generate migration files automatically. For example, if you use
rails g model User first_name:string last_name:string
this will create a model called User, and a migration that will create a users table with the fields id, first_name, last_name, and timestamp fields. If you want to add or remove columns later, there is a nifty trick for that; just run
rails g migration add_fields_to_users field_name:field_type
or
rails g migration remove_fields_from_users field_name.
Replace field_name, field_type and users as you think fit. This command will create a migration for you to add or remove fields, so you don't have to write those manually.
2.: Also, how do you specify table relationships in this db/migrations file.
You don't. Rails handles this for you through association methods like has_many, belongs_to, has_and_belongs_to, etc. Have a look at this rails guide to active record associations. The one thing you need to do on the database side is add foreign_id columns for a one to many relationship or create join tables for a many to many relationship. For example, if you have a users table and a pictures table, and each picture belongs to a user, in your user model you would write has_many :pictures, in your picture model you would write belongs_to :user, and in your pictures table you need a field called user_id with a type of integer.
3.: How do I validate that my migration file and my model file don't have any syntax errors.
You don't either. You just run rake db:migrate, and if something fails, it will tell you where and why. If your model has syntax errors, it will tell you when you start your server, or when you run your tests, or at least when you use it somewhere (e.g., when you call a model's method). If you mean how you validate your model's data, this is a whole other question - refer to this guide to active record validations and callbacks, which explains validations to check for presence, uniqueness, length, etc. in detail.
You have asked several questions, let's go one by one:
To my knowledge, you specify your model field data types within
db/migrations . This is new to me as in Django, you can directly
specify your model field data types in the Model class. Am I correct
in thinking about this? Is this a common practice in rails or am I
just using a work around?
The migrations are used to alter the database. Example of a migration:
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.text :description
end
end
end
When running this, you would be creating a table products with a string field called name. So, yes, you specify your model field data types in the migrations.
Also, how do you specify table relationships in this db/migrations
file. For instance if I have a model that is called class A.
You need to specify your relationships (or associations) in your models. Read this, because it is really well explained. But take into account that in the migrations somehow you have to do some work to create the associations because you might need to create join tables for many to many associations, or create a column that references another table for a has_many association.
How do I validate that my migration file and my model file don't have
any syntax errors. To my knowledge I just run rake db:migrate, but
what if I don't want my migration file to be replaced as I specified
my field datatypes in the file?
I am not sure what you mean in this question.
When you create a new model rails creates your shema migration files and your model.
In the migration file you specify your columns. It is possible to add some code here but you should do as less as possible. For up and down you add/remove columns here, add db indexes and so on.
In your model you define your relations belongs_to, has_many, etc. and your scopes for your tables and ofc the methods for your model. Your model inherit your table columns so you can access them directly.
I don't know Django, this is the common practice in rails.
Relations and other good infos you can check here: http://www.tutorialspoint.com/ruby-on-rails/rails-models.htm
I'm working up an app that interfaces with a legacy database which has a type column used for single table inheritance. This database is still used by an existing PHP application so I have to work with what is there. I'm trying to set up some models for this and one of the key tables is set up with an STI scheme and a type column, however, all of the types in that column are entirely lowercase.
In my testing so far, rails works fine with the type column if I change the value to match the class name (for example, Claimant instead of claimant). However I don't want to go changing those values in the production database even though it would probably be ok, nor do I want to have to go in and modify the legacy app to save the names differently...
In order to fix this I have two questions...
1) Is there anyway I can configure the model to recognize that type = 'claimant' maps to class = 'Claimant'?
2) failing that, is there a way I can tell rails to not use STI on this table even though it has a type column?
I've done some googling and haven't come up with much yet...
I haven't tried this in an STI setting, but when using a legacy table I was able to use the method "set_table_name" on the ActiveRecord model.
class Claimant < ActiveRecord::Base
set_table_name 'claimant'
end
Or with a custom method:
def table_name
'claimant'
end
Apologies I haven't got an STI table handy to test this on, but thought it might help solve your problem.
In answer to the second part of your question, I believe you can disable Rails looking at the type column, by just specifying a non-existant column name.
class Claimant < ActiveRecord::Base
inheritance_column = :_type_column_disabled
end
I am using Rails and postgres.
I have a couple of models using STI and i was wondering where i should put indexes on the tables and why?
For example lets say i have the following setup:
class Comment < AR; end
class MovieComment < Comment; end
class MagazineComment < Comment; end
# Fake Comment Table
id:integer
title:string
body:text
type:string
Thanks!
On the type field, if you want only one of MovieComment or MagazineComment. If you don't do that, you won't need the index here. I'm not sure if AR does use type every time, but just to make sure.
Because the id field is a primary key, an index should already be there.
If you want to query by both type and id make sure you have a combined index.
On the other fields: Depends what you query on, but I suppose you want to retrieve these only.
In general, you need indices in the columns that you will use when performing queries.
If you do MovieComment.find(10), the database will use the index in the id field that Rails will add automatically for you. Same if you do Comment.find(30): Rails will retrieve the commend with id 30 using the index, then it will read the type column and it will return a MovieComment or a MagazineComment.
If you are going to add a feature to search by title, for instance, you will have to create an index in this column as well. In this case, probably a :fulltext index.
An Index in the type column would make a query like MagazineComment.all faster because it is equivalent to Comment.where(type: 'MagazineComment').all, but it is probably not worth it.
I'm working through the Ruby on Rails tutorial and just made a Comment model with three properties.
rails generate model Comment commenter:string body:text post:references
It generated an ActiveRecord class with post but not commenter and body.
class Comment < ActiveRecord::Base
belongs_to :post
end
Why doesn't rails formally define the non-reference properties anywhere other than the DB migration scripts?
Rails dynamically loads attributes - specifically, the names of the columns and their types - based on the database schema. There is no need to define or declare them in your models. For apps running in production, it does this once, at load time. For development, it will reload them as often as every request, but only loads them when each model is used.
Rails does not infer other things from your database, though. For instance, if you were to place a unique index on a name column, it would not automatically add a validates_uniqueness_of :name to your model. Of course, the database would still enforce this constraint when you save the record, causing an exception to be raised should the name field contain a duplicate value. The recommendation, in this case, is to do both.
Why doesn't rails formally define the non-reference properties anywhere other than the DB migration scripts?
Well, where do you need them "defined" anyways? Migrations are the only place where these attributes matter coz its responsibility is to create database tables with those attributes.
If you do a scaffold on comments with similar parameters, it would also generate the views and it would be using the attributes. They don't need to be "defined" as such anywhere else.
The short answer to your question is "no". Even the migration is not a definitive place to look as there might be many migrations related to a model.
However, you may have a look at the generated "db/schema.rb" which is an aggregation of all migrations. It contains the schema definition of all activerecord models. This maybe your best bet.
Additionally, you may want to use the https://github.com/ctran/annotate_models plugin that inserts a comment in your model to help you keep track of all your model's attributes.
What is the deal with this? I'm working with a pre-existing that I did not do myself. Everything in the database is labeled in singular form. user, security, spec, etc. I guess the right way would be users, securities, specs. At least that's what ruby on rails try's to lookup when I generate a scaffold .
How do I specifically state to use user instead of users in the sql. I don't see anywhere in my project where it is looking up the sql. I mean if my model is user you would think it would try to lookup user. Instead of users.
Thanks for any help.
You need set_table_name :name_of_the_table in your model (source).
So:
class User < ActiveRecord::Base
set_table_name :user
end
The reason they use plural for the table and singular for the model is because an instance of the model represents one user, whereas the table contains all the users. It's just to make it more readable and logical.
You can specifiy the table name:
How do I explicitly specify a Model's table-name mapping in Rails?