Ruby Active Record Associations in Rails Active Record Associations Has Many Through Associations

Cant associate magazine with subscription.

This is what I am getting

irb(main):001:0> subscription = Subscription.create(months: 12, magazine: Magazine.find_by(title: "Ruby Reader"))
  Magazine Load (0.2ms)  SELECT  "magazines".* FROM "magazines" WHERE "magazines"."title" = ? LIMIT ?  [["title", "Ruby Reader"], ["LIMIT", 1]]
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
=> #<Subscription id: nil, months: 12, subscriber_id: nil, magazine_id: 1, created_at: nil, updated_at: nil>
irb(main):002:0> subscription.valid?
=> false
irb(main):003:0> subscription.errors.messages
=> {:subscriber=>["must exist"]}
irb(main):004:0>

But in the video, it was saved without the subscriber_id. It was only in the next command that they added an associatiojn for the Subscriber.

3 Answers

Tim Knight
MOD
Tim Knight
Treehouse Moderator 28,686 Points

Hi calvin,

Since the relationship is going to largely depend on how you set up your Subscription and Magazine models would you mind sharing the code you have in both of those models so the community can help take a look?

Hi I simply followed the code from the video - https://teamtreehouse.com/library/has-many-through-associations

class Subscription < ApplicationRecord
  belongs_to :subscriber
  belongs_to :magazine
end

class Subscriber < ApplicationRecord
  has_many :subscriptions
  has_many :magazines, through: :subscriptions
end

class Magazine < ApplicationRecord
  has_many :subscriptions
  has_many :subscribers, through: :subscriptions
end

From console

subscription = Subscription.create(months: 12, magazine: Magazine.find_by(title: "Ruby Reader"))

The teacher there ran this without any issues.

Jay McGavren
STAFF
Jay McGavren
Treehouse Teacher

Actually, calvin hobbs , I'm not sure why it didn't throw a validation error in the video, because trying it now I get the same issue as you. However, even if you get a validation error, the next command adds a Subscriber to the Subscription, thereby making it valid and allowing it to be saved (which should happen automatically):

Subscriber.find_by(name: "Jay").subscriptions << subscription

Here's what I'd recommend. Instead of calling Subscription.create, which will cause ActiveRecord to attempt to save the Subscription while it's in an invalid state, try calling Subscription.new instead:

subscription = Subscription.new(months: 12, magazine: Magazine.find_by(title: "Ruby Reader"))

Then you can run the command to associate a Subscriber, which will cause everything to be saved:

Subscriber.find_by(name: "Jay").subscriptions << subscription

Both the old command and this new command will work. But this new version will avoid the database transaction rollback that you saw. Please let us know whether this works for you!