如何干掉这段代码

时间:2014-04-07 11:56:01

标签: ruby-on-rails ruby-on-rails-4

我已经为模型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

2 个答案:

答案 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 
  • 已经有一个名为ActsAsTaggable的gem(或插件),它基本上以这种方式工作。但是看到解释而不仅仅是告诉使用宝石更好。

编辑:这是在标记结束时设置关联所需的代码:注意源选项。

class Tag
  has_many :taggings
  has_many :taggables, :through => :taggings, :source => :taggable