7urkm3n
7urkm3n

Reputation: 6321

Rails Controller (events to activity)

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

Answers (3)

Richard Peck
Richard Peck

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:

enter image description here

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:

enter image description here

As such, all the associations you call within your application are basically ways to represent the above relational database setup.

Upvotes: 1

K M Rakibul Islam
K M Rakibul Islam

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 events 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

Rubyrider
Rubyrider

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

Related Questions