Forum: Ruby on Rails Validations and has_many :through (Join Models)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
David W. (Guest)
on 2006-04-12 00:14
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.
Jean-François (Guest)
on 2006-04-12 00:57
(Received via mailing list)
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.
David W. (Guest)
on 2006-04-12 01:27
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.
steev (Guest)
on 2006-04-12 16:45
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.
This topic is locked and can not be replied to.