我已经为模型Unit,Group和Event实现了一个标记系统,目前,每个都有自己的方法add_tags和self.tagged_with实例。
def add_tags(options=[])
transaction do
options.each do |tag|
self.tags << Tag.find_by(name: tag)
end
end
end
和
def self.tagged_with(tags=[])
units = Unit.all
tags.each do |tag|
units = units & Tag.find_by_name(tag).units
end
units
end
end
我想将它们移动到一个模块中并将它们包含在模型中,但正如您所看到的,tagged_with方法不是多态的,因为我不知道如何引用父母类(Unit,Group)等等,并称为&#34; all&#34;在他们。有什么建议吗?
标记模型:
Class Tag < ActiveRecord::Base
has_and_belongs_to_many: units, :join_table => :unit_taggings
has_and_belongs_to_many: groups, :join_table => :group_taggings
has_and_belongs_to_many: events, :join_table => :event_taggings
end
答案 0 :(得分:1)
您可以致电self.class
获取当前课程,如下所示:
def self.tagged_with(tags=[])
klass = self.class
units = klass.all
tags.each do |tag|
units = units & Tag.find_by_name(tag).units
end
units
end
end
self.class
应该返回Unit
或任何类,调用类对象(self.class.tagged_with
)上的任何方法都与Unit.tagged_with
我建议你使用Concerns
,看看here
编辑回答您的评论
使用关注点你可以做类似的事情,每个类都有你之前提到过的方法,但你不必在每个类(或文件)上重写所有代码:
# app/models/concerns/taggable.rb
module Taggable
extend ActiveSupport::Concern
module ClassMethods
def self.tagged_with(tags=[])
klass = self.class
units = klass.all
tags.each do |tag|
units = units & Tag.find_by_name(tag).units
end
units
end
end
end
end
# app/models/unit.rb
class Unit
include Taggable
...
end
# app/models/group.rb
class Group
include Taggable
...
end
# app/models/event.rb
class Event
include Taggable
...
end
答案 1 :(得分:1)
我会这样做:
#table: taggings, fields: tag_id, taggable type (string), taggable id
class Tagging
belongs_to :tag
belongs_to :taggable, :polymorphic => true
现在在lib中创建一个模块 - 让我们称它为“ActsAsTaggable”*
module ActsAsTaggable
def self.included(base)
base.extend(ClassMethods)
base.class_eval do
#common associations, callbacks, validations etc go here
has_many :taggings, :as => :taggable, :dependent => :destroy
has_many :tags, :through => :taggings
end
end
#instance methods can be defined in the normal way
#class methods go in here
module ClassMethods
end
end
现在,您可以在任何想要制作标签的班级中执行此操作
include ActsAsTaggable
编辑:这是在标记结束时设置关联所需的代码:注意源选项。
class Tag
has_many :taggings
has_many :taggables, :through => :taggings, :source => :taggable