返回时强制转换ActiveModel属性

时间:2011-10-27 17:25:39

标签: ruby-on-rails ruby-on-rails-3 type-conversion activemodel

在我的Rails 3.1.1项目中,我有一个与API对话的ActiveModel(摘自Paul Dix的书,因可读性而缩短):

class Job
  include ActiveModel::Validations
  include ActiveModel::Serializers::JSON

  ATTRIBUTES = [ :id,
                 :title,
                 :description,
                 :company_id ]

  attr_accessor *ATTRIBUTES

  validates_presence_of     :title, :description
  validates_numericality_of :company_id, :id

  def initialize(attributes = {})
    self.attributes = attributes
  end

  def attributes
    ATTRIBUTES.inject(
      ActiveSupport::HashWithIndifferentAccess.new
      ) do |result, key|

      result[key] = read_attribute_for_validation(key)
      result
      end
  end

  def attributes=(attrs)
     attrs.each_pair {|k, v| send("#{k}=", v)}
  end

  def read_attribute_for_validation(key)
    send(key)
  end

  # More method definitions...
end

我在我的控制器中实例化@jobnew操作(company_id是路线中的一个关键字:/companies/:company_id/jobs/new),如下所示:

@job = Job.new(company_id: params[:company_id])

然后,使用CanCan,我检查用户创建的权限以创建作业。基本上,CanCan会检查current_user的company_id属性是否与作业的company_id匹配。此检查失败,因为@job.company_id以字符串形式返回。

当然,我可以在实例化对象时使用params [:company_id] .to_i,但这似乎是一种解决方法,我将不得不在以后重复。

问题:有没有办法让我的Job ActiveModel更“感知类型”并让它返回int @job.company_id来电?

我用Google搜索,检查activemodel源代码,但似乎没有找到答案。非常感谢任何帮助。

更新 我正在考虑更多类似于ActiveModel的schema块,就像ActiveResource中的那样。

3 个答案:

答案 0 :(得分:1)

attr_accessor *ATTRIBUTES

创建一个这样的方法:

def company_id
  @company_id
end

你可以用

覆盖它
def company_id
  @company_id.to_i
end

答案 1 :(得分:1)

回答我自己的问题......

mosch的回答建议在我的ActiveModel中覆盖company_id的getter。但是,我必须对模型中的所有_id属性重复此操作。因此,我决定在初始化对象时将所有'_id'属性强制转换为整数。如下:

def attributes=(attrs)
    attrs.each_pair do |k, v|
      if "#{k}".include? "_id"
        send("#{k}=", v.to_i)
      else
        send("#{k}=", v)
      end
    end
end

答案 2 :(得分:0)

我假设你的公司has_many => :jobs?如果是这样,你可以尝试

def new
  @company = Company.find(params[:company_id])
  @job = @company.jobs.new
end