Reputation: 16469
Im learning Ruby on Rails and I am practicing by making a small website. I am trying to make one to many relationship for a few models but I am having some trouble.
Currently I am stuck. I have a Users, ExpensePictures, IncomePictures models.
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
has_many :expense_picture, :income_picture
end
ExpensePicture model
class ExpensePicture < ActiveRecord::Base
belongs_to :user
end
IncomePicture model
class IncomePicture < ActiveRecord::Base
belongs_to :user
end
I'm stuck on how to actually make these relationships.
I want Users to have a one to many
relationship with IncomePicture
and ExpensePicture
I'm also not sure how to handle image files inside the model
ex:
User
- user_id (primary key)
- user_name
ExpensePicture
- picture_id (primary key)
- user_id (foreign key)
- ExpensePictureFile
IncomePicture
- picture_id (primary key)
- user_id (foreign key)
- IncomePictureFile
Upvotes: 3
Views: 6641
Reputation: 6620
one-to-many
association indicates that each instance of the model A can have zero or more instances of another model B and model B belongs to only one model A.
Example of how your models should be:
class User < ApplicationRecord
has_many :stories
end
class Story < ApplicationRecord
belongs_to :user
end
Notice that has_many is always followed by a plural word: has_many :stories
. It is also very important to correctly decide which model will have has_many
and which will have belongs_to
. The second model (Stories) contains one reference to the first model in form of a foreign key.
The second model doesn't know about the first model relation to it, it is not aware if the first model has reference to more than one of them or just to one.
You can read more about rails associations in this article.
Upvotes: 1
Reputation: 76774
Associations
What you're looking at is something called ActiveRecord Associations - the backend relational database (ORM - object-relational mapping) system
ActiveRecord is the "glue" which binds your Ruby classes (models) together, allowing you to pull data from a variety of different databases on your system. Any association inside Rails is governed by the ActiveRecord system - meaning if you can set it up correctly, you'll be able to get the associations you want
--
One-to-Many
The one-to-many
association is one of the most common with Rails -
It works very simply:
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :expense_pictures
has_many :income_pictures
end
#app/models/expense_picture.rb
Class ExpensePicture < ActiveRecord::Base
belongs_to :user
end
#app/models/income_picture.rb
Class IncomePicture < ActiveRecord::Base
belongs_to :user
end
This will allow you to call:
@user = User.find params[:id]
@user.income_pictures #-> collection of income pictures :)
This should be what you're looking for, with relevant documentation to help you
--
STI
A bonus for you: Single Table Inheritance
STI's are an advanced feature (so I wouldn't expect you to learn it immediately), but they will certainly help you with your current project. Basically, they allow you to define "parent" / "child" models which inherit from a single table (have a single pictures
table, rather than multiple income_pictures
and expense_pictures
tables):
#app/models/picture.rb
Class Picture < ActiveRecord::Base
belongs_to :user
end
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :expense_pictures
has_many :income_pictures
end
#app/models/expense_picture.rb
Class ExpensePicture < Picture
end
#app/models/income_picture.rb
Class IncomePicture < Picture
end
Why is this important? Simply, it allows you to just use a single table for both of these models (the pictures
table will have a column type
to identify the model which saved it)
This is a far DRYer way to accomplish your goal
Upvotes: 5
Reputation: 3407
As long as to handle images inside your models use Paperclip or Carrierwave (newer gem). Both very simple and easy to do the job.
Also take a look at this railscast about Paperclip and this one about carrierwave, very enlightening.
Besides, what's wrong with your relationship between the models ? Is it not working ? Cause it makes sense. Just use the plurals in your has_many declarations and I think this is it.
Upvotes: 3
Reputation: 13181
You must separate the declarations, and you must declare them plural versions (with a 's') like this
class User < ActiveRecord::Base
...
has_many :expense_pictures
has_many :income_pictures
end
It's useful to go through the guide
Upvotes: 1