Forum: Ruby on Rails uniqueness on has_many associations

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.
tron (Guest)
on 2009-01-06 15:03
(Received via mailing list)
Dear List,

This may not be rails unique but what is the best practice to validate
the uniqueness of has_many associations.
In particular the models are

class Word
end

class PhraseComponent
   belongs_to :word
   belongs_to :dictionary_entry
   acts_as_list :scope => :dictionary_entry
end

class DictionaryEntry
  has_many :phrase_components
  has_many :words, :through => :phrase_components
end

Dictionary entries  (words and phrases) are composed of words (which
are uniq)
and I want to check the same phrase occurs only once in the
DictionaryEntry table.

Is there a better or more efficient way to do this than create and
update a footprint
of the word associations on dictionary entries?
This means I would have a string field in the dictionary_entries table
which is a concatenation of
the associated words and would check the uniquness of that.

If we generalize the problem, we need to assure uniqueness of lists of
arbitrary objects (where a list is via a join table), in that case the
only representation that I can create on the list is the concatenation
of ids of list items and check the uniqueness of this?
I begin to think there must be a more canonical way to handle this.
Any help appreciated

Viktor










I found someone asking the same question but no reply followed.

http://groups.google.com/group/rubyonrails-talk/br...
tron (Guest)
on 2009-01-07 18:50
(Received via mailing list)
Hello,
I am still trying to find a solution to this.
Please feel free to throw any ideas at me or help me find the
appropriate forum.
Thank you
V
Robert W. (Guest)
on 2009-01-07 19:45
tron wrote:
> class Word
> end
>
> class PhraseComponent
>    belongs_to :word
>    belongs_to :dictionary_entry
>    acts_as_list :scope => :dictionary_entry
> end
>
> class DictionaryEntry
>   has_many :phrase_components
>   has_many :words, :through => :phrase_components
> end
>

Well from the database side of thing that's easily solved by adding a
unique index across the two foreign keys in the join table. That would
definitely prevent duplicates in the join table.

CREATE UNIQUE INDEX idx_word_dictionary_entry ON phrase_components
(word_id, dictionary_entry_id);

From the Rails side you might be able to use something like the
following example:

class TeacherSchedule < ActiveRecord::Base
  validates_uniqueness_of :teacher_id, :scope => [:semester_id,
:class_id]
end

Maybe (untested):

class PhraseComponent < ActiveRecord::Base
  validates_uniqueness_of :word_id, :scope => :dictionary_entry
  validates_uniqueness_of :dictionary_entry_id, :scope => :word_id
end

Note: This may be an expensive method for validating uniqueness!

In any of the cases mentioned you'll still have issues related to
"Optimistic Concurrency Control:"
http://en.wikipedia.org/wiki/Optimistic_concurrency_control

This section of the Rails documentation has a good explanation of these
issues and some options on how to solve them:
http://www.railsbrain.com/api/rails-2.2.2/doc/inde...
tron (Guest)
on 2009-01-07 21:58
(Received via mailing list)
Hello Robert,

You misunderstood my problem I guess.

Think of bora as a unique word, with id 1.
there is a dictionary entry for bora bora with id 2
then the phrase components representing this association are not
unique in word_id X dictionary_id (both are 1,2)
only word_id and dictionary_id AND list index (position) meaning
there can only be one word on the same position of a list.

The real problem is that I want to make sure
bora bora is entered only once in the dictionary.

For those who like more examples, think of travel itineraries
(which are a list of cities, say New York - London - Paris - Budapest)
Cities are a table, Itineraries are another and there is a join
model (Visits) which acts as a list.

How do I make sure an itinerary is created only once?

Thanks a million all

Vik



On Jan 7, 5:45 pm, Robert W. <removed_email_address@domain.invalid>
This topic is locked and can not be replied to.