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を使用して、作成するユーザーの権限を確認してジョブを作成します。company_id基本的に、CanCanはcurrent_userの属性がjobの属性と一致するかどうかをチェックしますcompany_id@job.company_id文字列として返されるため、このチェックは失敗します。

確かに、オブジェクトをインスタンス化するときにparams [:company_id] .to_iを使用できますが、これは後で繰り返す必要がある回避策のようです。

質問:@job.company_idジョブActiveModelをより「タイプ認識」にして、呼び出し に対してintを返すようにする方法はありますか?

グーグルでソースコードをチェックactivemodelしましたが、答えが見つからないようです。どんな助けでも大歓迎です。

更新schemaActiveResourceのブロックのように、ActiveModelのブロック のようなものをもっと考えていました。

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

Answering my own question....

mosch's answer suggested to override the getter for company_id in my ActiveModel. However, I would have to repeat this for all of _id attributes in the model. Therefore, I decided to cast all of the '_id' attributes to integers while initializing the object. As follows:

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 に答える