ActiveRecord集合和自定义方法

时间:2011-02-09 00:57:18

标签: ruby-on-rails ruby activerecord

我正在尝试创建一个factory_build类方法,用于在ActiveRecord集合中创建Redirect对象(参见下文)。

例如 @ website.redirects.factory_build(:code => 301)会返回PermenantRedirect对象的新实例。但是,即使我能够调用factory_build类方法,我也无法访问@website的primary_key。有没有办法从集合内部访问@ website.id或者我被迫将其传递给方法调用?任何其他建议也会受到欢迎,也许我不会用正确的方法来解决这个问题。感谢。

class Website < ActiveRecord::Base
  has_many :redirects
  has_many :permenant_redirects
  has_many :temporary_redirects
end

# Redirect is an abstract class it uses Rails Single Table Inheritance
class Redirect < ActiveRecord::Base
  def self.factory_build(attributes)
    status_code = attributes.delete(:code)
    case status_code
      when 301
        Website.find( ... ).permenant_redirects.new(attributes)
      when 302
        Website.find( ... ).temporary_redirects.new(attributes)
      else
        raise InvalidStatusCodeError
    end
  end
end

class TemporaryRedirect < Redirect
  def status
    302
  end
end

class PermenantRedirect < Redirect
  def status
    301
  end
end

1 个答案:

答案 0 :(得分:0)

您需要访问此关系的范围才能正确构建这些对象。这可用于类方法:

class Redirect < ActiveRecord::Base
  def self.factory_build(attributes)
    redirect_type =
      case (status_code = attributes.delete(:code))
      when 301
        PermanentRedirect
      when 302
        TemporaryRedirect
      else
        Redirect
      end

    redirect_type.new(attributes.merge(scoped.scope_for_create))
  end
end

我冒昧地干掉你的创作代码,因为那里有很多重复。另请注意,仅仅为了执行关系而调用find会浪费资源。如果您知道记录的ID,只需将其作为属性传递,除非您有充分的理由首先检索它。

scoped.scope_for_create调用返回当前范围或范围定义的属性。这些通常采用{ 'website_id' => 101 }之类的形式,可以传递给您的创建调用。