2013-12-24 1 views
0

Я новичок в рубине и рубинах. Мне нужно реализовать сложную мечению двигатель:Rails: has_many: через ассоциацию только с одной стороны

  • каждый тег может иметь 0 или больше синонимов (да, так же, как на SO)

  • должна быть иерархией тегов: то есть суб -tags и супер-теги. Скажем, у меня три тэга: programming, ruby и c. Затем programming является супер-тегом как ruby, так и c, и когда я вводил теги для элемента о рубине, нет необходимости вводить тег programming, я могу пометить его только ruby. Когда я ввожу теги, все супертеги должны быть добавлены рекурсивно. (На самом деле это странно, я никогда не видел какой-либо теги двигателя с помощью этой функции, я действительно чувствую отсутствие)

  • каждого пользователь должен иметь свой собственный набор тегов, то есть каждый Tagbelongs_toUser. Теги не являются общедоступными для всех, они являются частными для своего владельца.

Кажется, я не могу использовать acts_as_taggable_on драгоценный камень, верно? Поэтому я должен реализовать свою собственную. На самом деле я уже внедрил класс Tag, который поддерживает иерархию, синонимы и материалы пользователей, кажется, работает. Но есть много вопросов, как сделать что-то с этим.

Я пытаюсь декомпилировать acts_as_taggable_on, это действительно сложно для новичка, как я ..

Итак, есть много вопросов, но я собираюсь быть более точным в настоящее время:

Предположим, у меня есть класс Item, который я хочу быть помеченным. Насколько я понимаю, я должен использовать ассоциацию has_many :through, как на Item, так и на стороне Tag. И поэтому создайте промежуточную таблицу с полями item_id и tag_id.

BUT: Я хочу, чтобы мой механизм маркировки был универсальным! Поэтому я не хочу добавлять к Tag модели, связанные с Item.

Итак, единственный реальный вопрос: это вообще нормально, чтобы создать has_many :through ассоциацию только на Item стороне?

И, во-вторых, если у кого-то есть предложения по тому, что я объяснил, я был бы рад их видеть.

ответ

1

Далее с большим ответом swapnilabnave, я объясню, что вы ищете:

Я рекомендовал бы разбивая вашу проблему в более модульных вопросы

Ваш вопрос: можете ли вы использовать has_many :through для отношения. Ответ, как объяснил, «да», но это не решит проблему в целом


Иерархия Теги

Как уже упоминалось, ваши теги будут иметь «родителей» и другие пункты

Хотя у меня нет большого опыта с этим в Rails, в CakePHP это будет известно как tree structure. CakePHP обрабатывает это, имея 3 столбца - parent_id, left, right. В основном это позволяет приложению показывать различные элементы в вашем дереве, основываясь на том, какие числа используются в этих трех столбцах.

В вашем случае я бы порекомендовал разместить столбец в базе данных tags, в которой вы будете может назначить супер тег, если требуется (кажется, у вас есть только один супертег для тега?). Вы могли бы справиться с этим в вашей модели, используя self-referencing association технику, которая swapnilabnave отправил, чтобы дать возможность вызова super_tag так:

@tag.super_tag 

И важное замечание будет то, что это будет работать только тогда, когда вы могли иметь только один super_tag пер тег. Если вы хотите неограниченное количество супер тегов в теге, вы могли бы сделать это:

class Tag < ActiveRecord::Base 
    has_many :sub_tags, class_name: "Tag", :foreign_key => "super_tag_id" 

    has_many :tag_super_tags, class_name: "TagSuperTag", :foreign_key => "super_tag_id" 
    has_many :super_tags, :through => :tag_super_tags 
end 

Class TagSuperTag 
    belongs_to :tag 
    belongs_to :super_tag, :class => "Tag" 
end 

Хотя я не уверен, что если соединить код модели будет работать, то мы надеемся показать вам идею здесь.Это позволило бы создать автореферентное присоединиться модель под названием TagSuperTag, и позволяют вам иметь таблицу, как это:

tag_super_tags 
id | tag_id | super_tag_id | created_at | updated_at 

tags (no need for super_tag_id) 
id | user_id | name | etc 

Это позволит вам добавить столько супер тегов, как вы хотите, чтобы каждый тег


пользователь имеет много тегов

Поскольку каждый пользователь будет иметь много тегов, вы можете просто использовать стандартные has_many ассоциации, как это:

class User < ActiveRecord::Base 
    has_many :tags 
end 

class Tag < ActiveRecord::Base 
belongs_to :user 
end 

Это означает, что каждый тег будет иметь user_id колонки, чтобы выступать в качестве foreign_key


Тегов Универсального

Создания метки универсальной (не только для item) потребует a polymorphic association, и что кажется объединенной моделью

Как описал swapnilabnave, этот jo в модели может быть доступна любая модель, которая хочет использовать ее для хранения тегов, что позволяет вам связать с ней любую модель. Вот как вы можете сделать это:

class TaggedItem < ActiveRecord::Base 
    belongs_to :taggable, polymorphic: true 
    belongs_to :tag 
end 

tagged_items 
id | taggable_type | taggable_id | tag_id | created_at | updated_at 

Это позволит вам ссылаться на эту модель от любого другого, например:

class Post < ActiveRecord::Base 
    has_many :tagged_items, :class_name => "TaggedItem", :as => :taggable, :dependent => :destroy 
    has_many :tags, :through => :tagged_items 
end 

class Email < ActiveRecord::Base 
    has_many :tagged_items, :class_name => "TaggedItem", :as => :taggable, :dependent => :destroy 
    has_many :tags, :through => :tagged_items 
end 

И модель Tag должна has_many :tagged_items тоже:

class Tag < ActiveRecord::Base 
    has_many :tagged_items, :class_name => "TaggedItem", :foreign_key => "tag_id", :dependent => :destroy 
end 

Надеюсь, что это поможет

+0

Большое спасибо за подробное объяснение. –

2

Я могу предложить вам несколько вещей, которые могут помочь некоторым/большинству ваших заявлений о проблемах.

должна быть иерархия тегов

самостоятельной ссылочной has_many ассоциации могут быть использованы Creating a model that has a tree structure

class Tag < ActiveRecord::Base 
    has_many :sub_tags, class_name: "Tag", :foreign_key => "super_tag_id" 
    belongs_to :super_tag, class_name: "Tag" 
end 

Я хочу, чтобы мой мечение двигатель должен быть универсальным!Поэтому я не хочу добавлять к модели тегов все, что связано с пунктом

Маркировка должна быть полиморфной, так как ее широко применима в том виде, как она используется.

class TaggedItem < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :taggable, polymorphic: true 
end 

это вообще нормально, чтобы создать has_many: через ассоциацию только на стороне товара?

Я думаю, да, has_may through - это путь. Так что ваша Item модели может выглядеть

class Item < ActiveRecord::Base 
    has_many :tags, as: :taggable, through: :tagged_items 
end 
+0

Большое спасибо, я не был знаком с 'polymorphic'. –

Смежные вопросы