在我的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
来电?
我用Google搜索,检查activemodel
源代码,但似乎没有找到答案。非常感谢任何帮助。
更新
我正在考虑更多类似于ActiveModel的schema
块,就像ActiveResource中的那样。
答案 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