Foreign key in Ruby Rails - ruby-on-rails

Hey I need help with the following set-up, I cant seem to find a solution:
User.rb
class User < ActiveRecord::Base
has_one :education
end
Education.rb
class Education < ActiveRecord::Base
belongs_to :user
end
-The Users table holds 'id'(id of the user) and 'education_id' and other columns which are of no importance now.
-The Educations table holds 'id' and 'name' which is the name of the education.
I'd like to get the Education name by using the *education_id* in the Users table to link to id in Educations.
I want to be able to use that in the view by using some syntax like
<%= user.education %>
I believe its a real simple solution but I cant seem to find it
Cheers

Ref this
As per your Model declaration you should have user_id column in your educations table.
OR you have to change your model declaration to following
class User < ActiveRecord::Base
belongs_to :education
end
class Education < ActiveRecord::Base
has_one :user
end

by seeing the comment i think you need proper explanation
first of all do
class User < ActiveRecord::Base
belongs_to :education
end
class Education < ActiveRecord::Base
has_one :user
end
the table which has the foreign key in this case education_id should have belongs_to( in this case ) user and the table of which the foreign key is created here education_id has has_one

Related

Should a link 'has one' or 'belongs_to' a category?

I'm designing a simple Rails app with 2 models: Link and Category. Each link has exactly one category, and a category can have 0 or multiple links. What association should I apply to Link and Category? I'm very new to Ruby and those association terms are so confused to me.
You said each link has exactly one category
class Link < ApplicationRecord
belongs_to :category
end
category should exist before the link, so we go for belongs_to, not has_one
You said a category can have 0 or multiple links, so 0, 1, 2 or 79.
class Category < ApplicationRecord
has_many :links
end
I would suggest first to read active record associations
In your case
class Link
belongs_to :category
end
class Category
has_many :links
end
Don't get confused by the semantics when it gets to has_one and belongs_to.
The key difference is that belongs_to puts the foreign key on this models table:
class Link < ApplicationRecord
belongs_to :category
end
class Category < ApplicationRecord
has_many :links
end
You should read belongs_to :category as "this models table has a category_id column that references categories, it can only belong to a single category".
If you instead used:
class Link < ApplicationRecord
has_one :category
end
Rails would attempt to resolve the association through the categories.link_id column which won't work at all. has_one should be used when you have a one to one association on the the side without the foreign key:
class Country
has_one :capitol
end
class Capitol
belongs_to :country
end

Multiple associations query - DB Modelling

I am planning a rails apps that allows a User to list one/many Vaults, at either their personal address or any other additional address (location) specified against a vault. Before I go ahead and generate the Models I want to make sure I understand what associations need to be set up between the three Models. Here the code representation that I have typed manually to depict what associations are required.
class User < ActiveRecord::Base
has_many :vaults
end
class Vault < ActiveRecord::Base
belongs_to :user
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :user
end
Your database looks okay, few consideration are below :
class User < ActiveRecord::Base
has_many :vaults
has_many :addresses #(optional)if you want to fetch addresses directly
end
class Vault < ActiveRecord::Base
belongs_to :user
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :user #(optional) if you want to fetch user directly
belongs_to :vault
end
Database requirement:
adresses table must contain user_id(optional) and vault_id.
vaults table must contain user_id.

Rails Associations for Lookup Table

I have a Statuses table which contains only an id and name field (Active, Inactive, Pending, etc). I then have tables such as Users, Achievements, Badges for which each of these contain a status_id foreign key. Do the associations in my models look correct?
class Status < ActiveRecord::Base
has_many :achievements
has_many :badges
has_many :users
end
class User < ActiveRecord::Base
belongs_to :status
end
class Badge < ActiveRecord::Base
belongs_to :status
end
class Achievement < ActiveRecord::Base
belongs_to :status
end
I am struggling with how to properly read the difference between has_one and has_many in the case of a lookup table. I know that a user has one company and has one profile and a company has many users but this seems backwards to me.
The simplest association setup would be:
class User < ActiveRecord::Base
has_one :status
end
That exactly describes what you have posted. Your solution would work, but it is overkill for what you've described. All the association I posted above would do is add one method to the user model, i.e.
#user = User.find(1)
#user.status
If on the other hand you wanted simple semantics for showing all the users with a particular status, THEN you'd add
class Status < ActiveRecord::Base
has_many :users
end
so now you could do:
#status = Status.find_by_description('Active').first()
#status.users
Note that in BOTH cases, all that is needed is for the users model to have an attribute 'status_id'
Belongs_to is better suited when there is an implicit hierarchy , i,e,
class Child << ActiveRecord::Base
belongs_to :parent
end

Ruby on Rails Model / Database Associations

I have a user model, farmer model, doctor model, and education model.
A farmer has a user and many educations.
A doctor has a user and many educations.
How do I setup the database for the education model?
Should it have a farmer_id AND a doctor_id?
But a education cannot belong to a farmer AND and doctor at the same time. It's one or the other.
So my education database entry would either have a farmer_id OR a doctor_id filled in, but not both.
Is there a way to guarantee that only one of the ids could be filled in at a time?
Or is there a better way to associate these models?
Your help would be appreciated!
Oh, and don't worry about the names of the models (farmer, doctor, etc.). It's just an example.
I see two possible solutions for this scenario.
The first one is to make use of polymorphic associations for education. That could look like this:
class Farmer < ActiveRecord::Base
belongs_to :user
has_many :educations, :as => :profession
end
class Doctor < ActiveRecord::Base
belongs_to :user
has_many :educations, :as => :profession
end
class Education < ActiveRecord::Base
belongs_to :profession, :polymorphic => true
end
So instead of education having a doctor_id or a farmer_id it has one profession_id and one profession_type.
The second solution would be to make use of Single Table Inheritance. And in your scenrio, that could be accomplished by letting a Doctor be a User instead of belonging to a User. And of course the same thing for a Farmer. That could look like this:
class User < ActiveRecord::Base
has_many :educations
end
class Farmer < User
end
class Doctor < User
end
class Education < ActiveRecord::Base
belongs_to :user
end
And in this scenario you would add a type column to the User model to store what type of class it is and then only having a user_id in the Education model
I think its appropriate to have the relations this way based on roles.
Class User
has_one :role
has_many :educations
end
Class Role
#What ever roles you have.
#Farmer or Doctor
belongs_to :user
end
class Education
belongs_to :user
end
This way you will store the user_id in the education object, which solves your problem.

Action Controller: Exception - ID not found

I am slowly getting the hang of Rails and thanks to a few people I now have a basic grasp of the database relations and associations etc. You can see my previous questions here: Rails database relationships
I have setup my applications models with all of the necessary has_one and has_many :through etc. but when I go to add a kase and choose from a company from the drop down list - it doesnt seem to be assigning the company ID to the kase.
You can see a video of the the application and error here: http://screenr.com/BHC
You can see a full breakdown of the application and relevant source code at the Git repo here: http://github.com/dannyweb/surveycontrol
If anyone could shed some light on my mistake I would be appreciate it very much!
Thanks,
Danny
You have setup your Kase and Company models as a one-to-one relationship (see http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). This is probably not what you intended. Maybe if you could explain your intended relationship I could tell you where your mistake is?
class Company < ActiveRecord::Base
has_many :kases
has_many :people
end
class Kase < ActiveRecord::Base
belongs_to :company # foreign key: company_id
has_and_belongs_to_many :people # foreign key in join table
end
class Person < ActiveRecord::Base
has_and_belongs_to_many :kases # foreign key in join table
end
Relevant parts shown only. This should be a step in the right direction. You will need a join table for the many-to-many relationship, or alternatively, to model it using "has_many :through". Depends on whether you need to store other properties on the join. See link above for details.
I believe It should be
class Company < ActiveRecord::Base
has_many :people
has_many :kases
end
class Kase < ActiveRecord::Base
belongs_to :company
belongs_to :person
end
class Person < ActiveRecord::Base
belongs_to :company
has_one :kase
end
In your view (app/views/kases/new.html.erb) you have
<li>Company Select<span><%= f.select :company_id, Company.all %></span></li>
Try changing the select part to
<%= f.select :company_id, Company.all.collect {|m| [m.name, m.id]} %>
Suggestion
I also notice that you have four methods in your controller to find Kases by status. You can do this in your model, using named_scope. It's like this:
named_scope :active, :conditions => {:kase_status => 'Archived'}
And then, wherever you need to show only active Kases, you call Kase.active. The same for the other status.

Resources