Validations and has_many :through (Join Models)


#1

Hello again:

I’m hoping that somebody, anybody, can help with this question.

How do I make sure that records in a join model are unique?

Using the scenario outlined in Chad F.'s “Rails Recipies”, number
16, “Many to Many Relationships Where the Relationship Iteself Has
Data”.

Here are the tables:

create_table :magazines do |t|
t.column :title, :string
end

create_table :readers do |t|
t.column :name, :string
end

create_table :subscriptions do |t|
t.column :reader_id, :integer
t.column :magazine_id, :integer
t.column :last_renewal_on, :date
t.column :length_in_issues, :integer
end

And here are the models:

class Subscription < ActiveRecord::Base
belongs_to :reader
belongs_to :magazine
end

class Reader < ActiveRecord::Base
has_many :subscriptions
has_many :magazines, :through => :subscriptions
end

class Magazine < ActiveRecord::Base
has_many :subscriptions
has_many :readers, :through => :subscriptions
end

Here’s the code I’m using to test:

magazine = Magazine.create(:title => “Ruby Illustrated”)
reader = Reader.create(:name => “Anthony Braxton”)
subscription = Subscription.create(:last_renewal_on => Date.today,
:length_in_issues => 6)
reader.subscriptions << subscription
magazine.subscriptions << subscription
subscription.save
subscription2 = Subscription.create(:last_renewal_on => (Date.today+1),
:length_in_issues => 12)
reader.subscriptions << subscription2
magazine.subscriptions << subscription2
subscription2.save

After all of that, there now exists 2 records in the subscriptions
table, both of which have the same reader_id and magazine_id. How do
you perform the validation to make sure that each record in the
subscriptions table has a unique reader_id, magazine_id pair?

Thanks.


#2

Hello David,

[…]

After all of that, there now exists 2 records in the subscriptions
table, both of which have the same reader_id and magazine_id.
How do you perform the validation to make sure that each record
in the subscriptions table has a unique reader_id, magazine_id
pair?

Try this :

class Subscription < ActiveRecord::Base
belongs_to :reader
belongs_to :magazine

validates_uniqueness_of :reader_id, :scope => :magazine_id
end

Good night,

-- Jean-François.

#3

Jean-François wrote:

Hello David,

[…]

After all of that, there now exists 2 records in the subscriptions
table, both of which have the same reader_id and magazine_id.
How do you perform the validation to make sure that each record
in the subscriptions table has a unique reader_id, magazine_id
pair?

Try this :

class Subscription < ActiveRecord::Base
belongs_to :reader
belongs_to :magazine

validates_uniqueness_of :reader_id, :scope => :magazine_id
end

Good night,

-- Jean-François.

Thanks Jean-François!

Originally I tried putting a validates_uniqueness_of in the Subscription
model, but I used validates_uniqueness_of :reader, :scope => :magazine.
Of course it didn’t work. And I didn’t think of using the id’s
directly, because I was not thinking and didn’t want to put database
details in if I didn’t have to. Duh, the model is where those sort of
things are supposed to go!

As I said, thanks again.


#4

With ref to this post, will using a naming convention of
magazines_subscriptions yield any reduction in effort? Or is the
through used because the subscription table is named outside of the
convention?

IM having a very hard time accessing and displaying joined data…i
thought i might have got my head round it after the first 40
hours…grrrr…

I will post more on my specific problem if i dont come across an answer
in the archive…

David W. wrote:

Jean-François wrote:

Hello David,

[…]

After all of that, there now exists 2 records in the subscriptions
table, both of which have the same reader_id and magazine_id.
How do you perform the validation to make sure that each record
in the subscriptions table has a unique reader_id, magazine_id
pair?

Try this :

class Subscription < ActiveRecord::Base
belongs_to :reader
belongs_to :magazine

validates_uniqueness_of :reader_id, :scope => :magazine_id
end

Good night,

-- Jean-François.

Thanks Jean-François!

Originally I tried putting a validates_uniqueness_of in the Subscription
model, but I used validates_uniqueness_of :reader, :scope => :magazine.
Of course it didn’t work. And I didn’t think of using the id’s
directly, because I was not thinking and didn’t want to put database
details in if I didn’t have to. Duh, the model is where those sort of
things are supposed to go!

As I said, thanks again.