[英]How to DRY up this code
我已经为模型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
我想将它们移动到模块中并将其包含在模型中,但是如您所见,tagd_with方法不是多态的,因为我不知道如何引用育儿类(单元,组等)并调用像“全部”这样的方法。 有什么建议吗?
标签型号:
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
您可以调用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
, 在这里看看
编辑您的评论的答案
使用关注点,您可以执行以下操作,每个类都具有您之前提到的方法,但是您不必在每个类(或文件)上重写所有代码:
# 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
我会这样做:
#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
编辑:这是您需要在Tag端建立关联的代码:注意source选项。
class Tag
has_many :taggings
has_many :taggables, :through => :taggings, :source => :taggable
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.