Reputation: 6321
I am trying to understand, what's difference between 1 and 2 line of codes.
Is it same code ? Thank You !
Activity : has_many :events
Event : belongs_to :activity
1)
@activity = Activity.find(params[:activity_id])
event = Event.new(event_params)
event.activity_id = @activity
2) Edited, 'events' supposed tobe pluralized.
@activity = Activity.find(params[:activity_id])
event = @activity.events.new(event_params)
Upvotes: 4
Views: 421
Reputation: 76784
No they're not the same lines of code.
They tell ActiveRecord to look up particular files in specific datatables, using the appropriate foreign key:
The has_many
declaration will perform a query like this:
"SELECT * FROM `events` WHERE `event`.`id` IN ?", [activity.id]
It's pinging the events data table.
--
The belongs_to
will pull data out of the parent table using the provided foreign_key
:
"SELECT * FROM `activities` WHERE `activity`.`event_id` IN ?", [event.id]
It's important to note that you could also use this to get a similar result:
event_id = "SELECT * FROM `activites` WHERE `activity`.`id` IN ? LIMIT 1", ["1"]
"SELECT * FROM `activities` WHERE `activity`.`event_id` IN ?", [event_id]
IE you're essentially using data from the same table, whilst has_many
pulls data from another table.
Although these look similar, they are very different in the background. The has_many
association denotes the possibility of extra records in another data table; the belongs_to
association has to have a "parent" object.
Thus, when using has_many
/ belongs_to
, you have to understand which is the "parent" object. For example:
#app/models/post.rb
class Post < ActiveRecord::Base
has_many :comments #-> doesn't have to be any "comment" objects
end
#app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :post # -> only works if there is a "post" object
end
Hopefully that explains it a little clearer.
Also, you have to remember that Rails is built on top of a relational database.
This means that each time you use ActiveRecord or any of the adjoining functionality, you have to ensure that you understand what this means.
Relational databases work by taking a "foreign key" and applying it to a conjoining database. This allows your ORM (Object Relational Mapper) (in our case ActiveRecord
) to pull the appropriate data from the other tables:
As such, all the associations you call within your application are basically ways to represent the above relational database setup.
Upvotes: 1
Reputation: 34338
Yeah, in general, the two approaches are basically doing the same things and will generate same results.
In scenario 1: You are finding an activity
and initializing an event
, and then associating the event
to the activity
.
In scenario 2: You are finding an activity
and then initializing one of it's associated event
s using events
association. Although it should be: @activity.events.new(event_params)
NOT @activity.event.new(event_params)
[Notice events
should be plural as you have a has_many
association]
If you call save in both cases, you will get the same result. Basically, when you will call: activity.events
you will get the list of events associated with that activity. The above-created event will be in that list in both cases.
However, although both of the scenarios are doing the same thing, the second way is considered to be more Railsy way of doing things and hence a better practice.
Upvotes: 2
Reputation: 3587
Two blocks are doing the same. But they are not doing the more preferred way, they are doing differently. See my comment how they are doing differently. I explained line by line. 1)
#
# Finding the activity event
@activity = Activity.find(params[:activity_id])
#
# initialising event object from events parameters
event = Event.new(event_params)
# assigning activity in event, this will help building the
# association though its a manual process. Your ORM active record
# gives the best way to handle that. Your step 2 is
# something what is preferred.
event.activity_id = @activity
#
# Comment:
# This is not the best practice. Because its not utilising Rails's
# ORM active record
2)
# finding the activity
@activity = Activity.find(params[:activity_id])
event = @activity.events.new(event_params)
# Creating event using events association
# I believe your association name is different. it should
# be plural form events.
# it should be:
event = @activity.events.new(event_params)
#
# Comment: This is the preferred way.
# Although you can do more refactoring,
# like moving the @activity on any before action
# call back to ensure it is not define every time in
# your different different action.
Upvotes: 2