1

在我的 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

@job我在我的控制器中实例化new操作(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调用?

我四处搜索,检查activemodel源代码,但似乎没有找到答案。任何帮助是极大的赞赏。

更新 我正在考虑更多类似schemaActiveModel 的块,就像 ActiveResource 中的块一样。

4

3 回答 3

1
attr_accessor *ATTRIBUTES

创建一个这样的方法:

def company_id
  @company_id
end

你可以用

def company_id
  @company_id.to_i
end
于 2011-10-27T18:12:07.607 回答
1

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

mosch 的回答建议company_id在我的 ActiveModel 中覆盖 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
于 2011-10-28T15:40:34.637 回答
0

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

def new
  @company = Company.find(params[:company_id])
  @job = @company.jobs.new
end
于 2011-10-27T18:03:34.657 回答