سؤال

واني اسعى الى خلق نموذج لروبي على القضبان المشروع أن يبني علاقات بين الكلمات المختلفة. كما أنها تفكر في قاموس فيها "الروابط" بين كلمتين تبين أنها يمكن أن تستخدم بشكل مترادف. بلدي DB يبدو شيئا من هذا القبيل:

Words
----
id

Links
-----
id
word1_id
word2_id

وكيف يمكنني إنشاء علاقة بين كلمتين، وذلك باستخدام الجدول الارتباط. لقد حاولت لإنشاء نموذج لكنه كان غير متأكد من كيفية الحصول على جدول الارتباط في اللعب:

class Word < ActiveRecord::Base
  has_many :synonyms, :class_name => 'Word', :foreign_key => 'word1_id'
end
هل كانت مفيدة؟

المحلول

في عام، إذا جمعيتكم لها اللواحق مثل 1 و 2، انها ليست إعداد بشكل صحيح. جرب هذا لنموذج الكلمات:

class Word < ActiveRecord::Base
  has_many :links, :dependent => :destroy
  has_many :synonyms, :through => :links
end

ونموذج الرابط:

class Link < ActiveRecord::Base
  belongs_to :word
  belongs_to :synonym, :class_name => 'Word'

  # Creates the complementary link automatically - this means all synonymous
  # relationships are represented in @word.synonyms
  def after_save_on_create
    if find_complement.nil?
      Link.new(:word => synonym, :synonym => word).save
    end
  end

  # Deletes the complementary link automatically.
  def after_destroy
    if complement = find_complement
      complement.destroy
    end
  end

  protected

  def find_complement
    Link.find(:first, :conditions => 
      ["word_id = ? and synonym_id = ?", synonym.id, word.id])
  end
end

والجداول:

Words
----
id

Links
-----
id
word_id
synonym_id

نصائح أخرى

وهم، وهذا هو واحد صعبة. وذلك لأن المترادفات يمكن أن يكون من أي هوية WORD1 أو هوية WORD2 أو كليهما.

وعلى أي حال، عند استخدام نموذج لجدول ارتباط، يجب استخدام: من خلال الخيار على نماذج التي تستخدم الجدول ارتباط

class Word < ActiveRecord::Base
  has_many :links1, :class_name => 'Link', :foreign_key => 'word1_id'
  has_many :synonyms1, :through => :links1, :source => :word
  has_many :links2, :class_name => 'Link', :foreign_key => 'word2_id'
  has_many :synonyms2, :through => :links2, :source => :word
end

وهذا ينبغي أن نفعل ذلك، ولكن الآن يجب أن تحقق مكانين للحصول على كل المرادفات. وأود أن أضيف طريقة التي انضمت هذه، وورد الدرجة الداخل.

def synonyms
  return synonyms1 || synonyms2
end

و|| جي نتائج معا ستنضم إلى صفوف والقضاء مكررة بينهما.

* هذا الرمز لم تختبر.

ونموذج الكلمات:

class Word < ActiveRecord::Base
  has_many :links, :dependent => :destroy
  has_many :synonyms, :through => :links

  def link_to(word)
    synonyms << word
    word.synonyms << self
  end
end

وإعداد :dependent => :destroy على has_many :links سيزيل جميع الروابط المرتبطة بهذا كلمة قبل destroying سجل كلمة.

وينك نموذج:

class Link < ActiveRecord::Base
  belongs_to :word
  belongs_to :synonym, :class_name => "Word"
end

وعلى افتراض أنك تستخدم أحدث القضبان، سوف لا يكون لديك لتحديد المفتاح الخارجي للbelongs_to :synonym. إذا لم تخني، وقدم هذا كمعيار في القضبان 2.

وجدول Word:

name

والجدول الرابط:

word_id
synonym_id

لربط كلمة موجودة كمرادف لكلمة أخرى:

word = Word.find_by_name("feline")
word.link_to(Word.find_by_name("cat"))

لإنشاء كلمة جديدة كمرادف لكلمة أخرى:

word = Word.find_by_name("canine")
word.link_to(Word.create(:name => "dog"))

وكنت مشاهدته من زاوية مختلفة. لأن كل عبارة مرادفة، يجب أن لا تشجع أي واحد منهم ليكون "أفضل". جرب شيئا من هذا القبيل:

class Concept < ActiveRecord::Base
  has_many :words
end

class Word < ActiveRecord::Base
  belongs_to :concept

  validates_presence_of :text
  validates_uniqueness_of :text, :scope => :concept_id

  # A sophisticated association would be better than this.
  def synonyms
    concept.words - [self]
  end
end

والآن يمكنك أن تفعل

word = Word.find_by_text("epiphany")
word.synonyms

ومحاولة لتنفيذ حل سارة جئت عبر 2 قضايا:

أولا، والحل لا يعمل عند الرغبة في تعيين المرادفات عن طريق القيام

word.synonyms << s1 or word.synonyms = [s1,s2]

وأيضا حذف المرادفات غير مباشر لا يعمل بشكل صحيح. وذلك لأن القضبان لا تؤدي إلى after_save_on_create وafter_destroy الاسترجاعات عندما يخلق تلقائيا أو حذف السجلات الارتباط. على الأقل ليس في القضبان 2.3.5 حيث حاولت عليه.

ويمكن ان تكون ثابتة هذه باستخدام: رد after_remove في النموذج الكلمات:: after_add و

has_many :synonyms, :through => :links,
                    :after_add => :after_add_synonym,
                    :after_remove => :after_remove_synonym

وأين الاسترجاعات وطرق سارة، عدلت قليلا:

def after_add_synonym synonym
  if find_synonym_complement(synonym).nil?
    Link.new(:word => synonym, :synonym => self).save
  end
end

def after_remove_synonym synonym
  if complement = find_synonym_complement(synonym)
    complement.destroy
  end
end

protected

def find_synonym_complement synonym
  Link.find(:first, :conditions => ["word_id = ? and synonym_id = ?", synonym.id, self.id])
end

العدد الثاني من الحل سارة هي أن المرادفات أن يكون بعبارة أخرى بالفعل عندما ترتبط مع كلمة جديدة لا تضاف إلى كلمة جديدة، والعكس بالعكس. هنا هو تعديل صغير يعمل على حل هذه المشكلة ويضمن أن جميع المرادفات من مجموعة ترتبط دائما لجميع المرادفات الأخرى في هذه المجموعة:

def after_add_synonym synonym
  for other_synonym in self.synonyms
    synonym.synonyms << other_synonym if other_synonym != synonym and !synonym.synonyms.include?(other_synonym)
  end
  if find_synonym_complement(synonym).nil?
    Link.new(:word => synonym, :synonym => self).save
  end
end 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top