Creating associations with new() versus create()

46 views Asked by At

I'm hoping that this question will lead to me understanding more about how to construct many-to-many relationships with foreign keys that don't have inherant "Rails magic", as I've been Googling for hours and still don't fully understand.

Basically, Users can organize Events, and Events can be organized by many Users.

I have the following models:

class User < ActiveRecord::Base
  has_many :event_organizers, foreign_key: "organizer_id"
  has_many :organized_events, through: :event_organizers, source: "event"
class EventOrganizer < ActiveRecord::Base
  belongs_to :event
  belongs_to :organizer, class_name: "User", foreign_key: "organizer_id"
class Event < ActiveRecord::Base
  has_many :event_organizers
  has_many :organizers, through: :event_organizers

In case you have questions about the columns on event_organizers:

event_organizers
  event_id (references an event)
  organizer_id (references a user)

Now to the fun part, which I noticed was happening in my Controller but will show in the console to make this post shorter:

2.2.0 :001 > User.first
  User Load (0.1ms)  SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1
 => #<User id: 1, email: "[email protected]", password_digest: "$2a$10$SCOFgQTF4krBYlqKVHSSMOtVP8ad/vTFPN/60WjX8s....", first_name: "test", last_name: "user", admin: false, created_at: "2015-06-18 02:36:21", updated_at: "2015-06-18 02:36:21"> 

2.2.0 :002 > event = User.first.organized_events.new( name: "test", location: "test", start_time: Time.now, end_time: 2.hours.from_now )
  User Load (0.2ms)  SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1
 => #<Event id: nil, name: "test", location: "test", start_time: "2015-06-18 02:37:15", end_time: "2015-06-18 04:37:15", created_at: nil, updated_at: nil> 

2.2.0 :003 > event.organizers
 => #<ActiveRecord::Associations::CollectionProxy []> 

2.2.0 :004 > event = User.first.organized_events.create( name: "test", location: "test", start_time: Time.now, end_time: 2.hours.from_now )
  User Load (0.5ms)  SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1
   (0.2ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "events" ("name", "location", "start_time", "end_time", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?)  [["name", "test"], ["location", "test"], ["start_time", "2015-06-18 02:37:37.781981"], ["end_time", "2015-06-18 04:37:37.782003"], ["created_at", "2015-06-18 02:37:37.788761"], ["updated_at", "2015-06-18 02:37:37.788761"]]
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
  EventOrganizer Exists (0.1ms)  SELECT  1 AS one FROM "event_organizers" WHERE ("event_organizers"."organizer_id" = 1 AND "event_organizers"."event_id" = 1) LIMIT 1
  SQL (0.1ms)  INSERT INTO "event_organizers" ("organizer_id", "event_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["organizer_id", 1], ["event_id", 1], ["created_at", "2015-06-18 02:37:37.800400"], ["updated_at", "2015-06-18 02:37:37.800400"]]
   (37.2ms)  commit transaction
 => #<Event id: 1, name: "test", location: "test", start_time: "2015-06-18 02:37:37", end_time: "2015-06-18 04:37:37", created_at: "2015-06-18 02:37:37", updated_at: "2015-06-18 02:37:37"> 

2.2.0 :005 > event.organizers
  User Load (0.6ms)  SELECT "users".* FROM "users" INNER JOIN "event_organizers" ON "users"."id" = "event_organizers"."organizer_id" WHERE "event_organizers"."event_id" = ?  [["event_id", 1]]
 => #<ActiveRecord::Associations::CollectionProxy [#<User id: 1, email: "[email protected]", password_digest: "$2a$10$SCOFgQTF4krBYlqKVHSSMOtVP8ad/vTFPN/60WjX8s....", first_name: "test", last_name: "user", admin: false, created_at: "2015-06-18 02:36:21", updated_at: "2015-06-18 02:36:21">]> 

So,my question is this: Why is it that when I use user.organized_events.new(), the association doesn't exist, but when I use user.organized_events.create(), it does?

2

There are 2 answers

0
Darpa On BEST ANSWER

As you will be able to notice, when you are using 'new', the id for the new event is not generated. The id for a record is generated only at the time it is saved to the database and two records are linked through their ids only if you haven't mentioned any other attribute explicitly. Since no id has been generated for the new event yet, a user cannot be linked to it. Hence, when you use the query 'event.organizers', you get an empty array.

6
rxing On

It's my bad. I should have read your question more carefully.

You are using event.organizers. I guess it is because you have to set inverse_of in your model.