Rails association with tables without models - ruby-on-rails

I'm looking to rewrite my project in Rails. It's currently written in PHP (CodeIgniter), I've come to the point where I'm writing more libraries and core extensions than I'm writing new code. I've been looking at some Rails tutorials and I'm liking what I see so far (even though I feel you have less control of what's been passed around). However it seems there's little information out there (maybe I'm not looking in the right places) on database tables without models.
For example, I need a table called user_verification_token
CREATE TABLE IF NOT EXISTS `user_verification_token` (
`user_id` int(11) NOT NULL,
`token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`is_used` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
It doesn't make sense for me to create a model for this, right?
First question: How do I generate a migration to create a table alone without any model?
Second question: When this table is filled with data, how do I associate with it. e.g. Associate it with the User model (if possible)/a user object so I can find a user by a token (provided is_used = 0) and return the user's data?
I apologize in advance if this is a newb question, I can do all these comfortably with PHP but I don't know how to do this on Rails.

You need a model for this table. It does make sense for you to have a model for the user_verification_token table. In order to get the associations and all the other functionality you'll want from this data, you need to create a model and the associations for it.
To answer the first question: run rails generate migration your_migration_name
For the activity_type table you mention in the comment on the original question, you might be interested in the RailsLookup gem to help automate some of the work required to make good use of lookup tables in Rails. There is a blog post describing it and the source can be found on GitHub

Your current scenario does require a model, although when you need to store data like categories e.g Sports(football,tennis,cricket,swimming,basketball,etc), you can store them as constants in your config->initializers->constant eg. SPORT_CATEGORIES = [["Football","football"],["Tennis","tennis"],etc], alternatively if you have more cols to store you can create a model then create the default rows as you would in a php .sql file but in ruby of course :) For example:
sport_categories = [
{:category => "football", :category_type => "manly" },
{:category => "Tennis", :category_type => "manly" },
etc
]
sport_categories.each do |attributes|
Model_name_here.find_or_initialize_by_category(attributes[:category]).tap do |p|
p.category_type = attributes[:category_type]
p.save!
end
end
Then you run rake db:seed.

I will suggest you to create model for this, as you will have complete access to user_verification_token table via UserVerificationToken model which will be associated to user.

Create a model because all the validations can be done in a model.
eg:validates :user_id. So there is no need to include those constraints while creating the table

Related

Looking for a good idea and a good Ruby structure

I am writing a Rake task to populate a database for development purposes to have some data to work with. ( but In test I am using FactoryGirl, so not talking about that. )
So let's say I have two sample Organizations in my demo database, so I have defined them like this:
sample_organizations = [ '37 Signals', 'Fog Creek']
and then a small method to populate the DB like this:
def create_organizations
sample_organization.each { |item|
Organization.first_or_create(
name: item,
time_zone: 'Central'
)
}
end
so the good thing is that two months from now if I wanted to add a third organization I just go to top of my code and hand type another organization name in that array. Method still works and creates it.
Now here starts the question: I have more tables to populate! For example Summaries table which is hanging off of Organization table, so each organization can have many Summaries, so we have an organization_id foreign key in Summary table to fill too.
But still I want to have a method like create_summaries that does something similar to create_organization method above, but this time fills in Summaries table, and the tricky part is to fill in that organization_id field of the table.
How should I approach this?
Let's say Summaries table has these fields: id (auto generate by Rails) , organization_id, name, member_count
Try using Populator gem for tasks like this. It is easy to use, and you can generate complex structures. Screencast.
As you can't use those, use select a random parent object, or specify one by name in a hash.
summaries = [{:name => "foo", :organization => "bar"}]

Rails rename the ID column in a model

I'm currently looking at migrating an existing system (written in spaghetti PHP) over to rails. The problem is, it has to run off of a live database. A lot of the ID columns on these different tables aren't named id. For instance, the customers table has an ID column called Customer_ID. Upon looking, I just realised that rails does infact seem to find by the primary key instead of a specific column called id.
Will I face a lot of problems later with the naming of these ID columns, specifically in stuff like relationships?
After v2.3.8, set_primary_key :col_name is deprecated.
self.primary_key = 'col_name' is recommended.
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html
Change primary key attribute in model by using
set_primary_key :col_name

What's the point of having foreign keys if Rails can access other model's attributes through associations anyways?

I'm a Rails beginner (and loving it so far). I'm not sure if this is a stupid question.
As far as I know, a foreign key, for example, like this: user_id in a model called Micropost will associate a micropost with the ID of an User model. Like this:
railtutorial.org
So you can do this: <%= micropost.user_id %> to get the ID of the user who created a micropost.
But can also do this: <%= micropost.user.id %> due to Rails' ability to associate models via has_many and belongs_to.
So I wonder, why are foreign keys necessary in Rails applications if the web framework can access other model's attributes through associations anyways?
Is it necessary to index them and improve database performance?
Or are they necessary so that something like this: micropost.user.username can work?
Foreign keys are used under the hood to make Rails associations work, and those associations wouldn't work without them. You can see this by attaching .to_sql to a Relation, e.g.:
> Blog.first.articles.to_sql
=> "SELECT `articles`.* FROM `articles` WHERE `articles`.`blog_id` = 42"
In this case it's using the blog_id foreign key to query the articles association.
It isn't necessary to index foreign keys, but it is a good idea and gives better performance.
So I wonder, why are foreign keys necessary in Rails applications if the web framework can access other model's attributes through associations anyways?
Foreign keys (along with the Primary key counter part) are what links the models together. If you did not have a user_id how would you know which user it ultimately is associated to?
Is it necessary to index them and improve database performance?
I find this practice helpful, in regards to performance.
Or are they necessary so that something like this: micropost.user.username can work?
It's only necessary in the context that to find micropost's associated user you need to know which user it is.
The key thing to understand about user vs user_id in your model is that user_id is the foreign key and that user is an instance of a User (eg, it's the model object).
Without user_id, rails can't make the correct user for you.
Note that if you are not preloading your associations, if all you need is the user id (say, for a building a URL), using micropost.user_id will be faster than micropost.user.id because rails won't need to instantiate the User object just to retrieve the id.
By calling micropost.user_id, Rails gives you the entry of the user_id column of the microposts table.
By calling micropost.user.id, Rails takes the user_id column from micropost and "searches" for Users with the corresponding id. When you do not have the user_id, Rails do not know anything about the correlation between the two tables.

Adding more data on saving 'has_many :through' associated records by keeping use of the "RoR magical\automatic way"

I am using Ruby on Rails 3.0.7 and I followed this post about handling an "has_many :through => checkboxes" in which, in order to create user-group relationship records for membership purposes, is just passed a group_ids parameter (that is an array of id values) from check box input fields to the #user.save method. Using that code all works good in a "RoR magical\automatic way" (RoR set properly user_id values in the related memberships database table).
However, on saving, I would like to add some extra information to Membership records. That is, (following that post content) when it creates the associated records in the memberships database table (which database table has id, user_id and group_id columns) I would like to save an extra description information (which, for example, can be represented by a description column in that memberships table).
Is it possible to accomplish that by keeping use of the "RoR magical\automatic way"?
I would use the ActiveRecord Callbacks to achieve this :
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

What does a db table created by the Rails framework look like?

I don't have a Rails environment set up and this is actually quite hard to find a quick answer for, so I'll ask the experts.
When Rails creates a table based on your "model" that you have set up, does Rails create a table that mirrors this model exactly, or does it add in more fields to the table to help it work its magic? If so, what other fields does it add and why? Perhaps you could cut and paste the table structure, or simply point me to a doc or tutorial section that addresses this.
If you're building a completely new application, including a new database, then you can build the whole back end with migrations. Running
ruby script/generate model User name:string
produces both a user.rb file for the model and a migration:
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :users
end
end
You can see that by default the generate script adds "timestamps" for (created and last updated) and they're managed automatically if allowed to remain present.
Not visible, but important, is that an extra column, "id", is created to be the single primary key. It's not complusory, though - you can specify your own primary key in the model, which is useful if you're working with a legacy schema. Assuming you retain id as the key, then Rails will use whatever RDBMS-specific features are available for new key values.
In ActiveRecord, models are created from database tables, not the other way around.
You may also want to look into Migrations, which is a way of describing and creating the database from Ruby code. However, the migration is not related to the model; the model is still created at runtime based on the shape of the database.
There are screencasts related to ActiveRecord and Migrations on the Rails site: http://www.rubyonrails.org/screencasts
Here's the official documentation for ActiveRecord. It agrees with Brad. You might have seen either a different access method or a migration (which alters the tables and thus the model)
I have had a little experience moving legacy databases into Rails and accessing Rails databases from outside scripts. That sounds like what you're trying to do. My experience is in Rails databases built on top of MySQL, so your mileage may vary.
The one hidden field is the most obvious --- the "id" field (an integer) that Rails uses as its default primary key. Unless you specify otherwise, each model in Rails has an "id" field that is a unique, incremented integer primary key. This "id" field will appear automatically in any model generated within Rails through a migration, unless you tell Rails not to do so (by specifying a different field to be the primary key). If you work with Rails databases from outside Rails itself, you should be careful about this value.
The "id" field is a key part of the Rails magic because it is used to define Rails' associations. Say you relate two tables together --- Group and Person. The Group model will have an "id" field, and the Person model should have both its own "id" field and a "group_id" field for the relationship. The value in "group_id" will refer back to the unique id of the associated Group. If you have built your models in a way that follows those conventions of Rails, you can take advantage of Rails' associations by saying that the Group model "has_many :people" and that the Person model "belongs_to :group".
Rails migrations also, by default, want to add "created_at" and "updated_at" fields (the so-called "timestamps"), which are datetime fields. By default, these take advantage of the "magic" in the database --- not in Rails itself --- to automatically update whenever a record is created or modified. I don't think these columns will trip you up, because they should be taken care of at the database level, not by any special Rails magic.

Resources