rails:活动记录忽略的字符串参数

时间:2014-07-20 15:32:38

标签: ruby-on-rails activerecord ruby-on-rails-4 actioncontroller

在轨道4.1.4应用程序中,模型不处理某些参数,可能取决于它们的类型。在发出如下所示的POST请求时,所有参数都会得到正确处理,并且新配方会使用正确的值保存到数据库中:

POST /api/v0/recipes HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: f49d43b3-9007-9687-a24f-92e7e7c873bd

{"recipe":{"name":"Spaghetti Carbonara","description":"Catchy description", "body":"Steps here","preparation_time":200,"category_id":"1","ingredients_attributes":[{"food_id":2,"quantity":100,"unit":"g"}, {"food_id":2,"quantity":150,"unit":"g"}]}}

请注意,preparation_time的值作为整数传递,category_id的值作为字符串传递。但是,当准备时间的值作为字符串传递时,就像category_id那样,验证失败,抱怨每个模型的验证规则需要preparation_time

这是失败的请求:

POST /api/v0/recipes HTTP/1.1
Host: localhost:3000
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 70500362-9573-8684-bdaf-8dd0a0b3b05d

{"recipe":{"name":"Spaghetti Carbonara","description":"Catchy description", "body":"Steps here","preparation_time":"200","category_id":"1","ingredients_attributes":[{"food_id":2,"quantity":100,"unit":"g"}, {"food_id":2,"quantity":150,"unit":"g"}]}}

以下是该请求的日志,其中显示preparation_time参数已正确到达:

Started POST "/api/v0/recipes" for 10.0.2.2 at 2014-07-20 17:11:08 +0200
Processing by Api::V0::RecipesController#create as */*
  Parameters: {"recipe"=>{"name"=>"Spaghetti Carbonara 2", "description"=>"Catchy description", "body"=>"Steps here", "preparation_time"=>"200", "category_id"=>"1", "ingredients_attributes"=>[{"food_id"=>2, "quantity"=>100, "unit"=>"g"}, {"food_id"=>2, "quantity"=>150, "unit"=>"g"}]}}
   (0.2ms)  begin transaction
  Food Load (1.3ms)  SELECT  "foods".* FROM "foods"  WHERE "foods"."id" = ? LIMIT 1  [["id", 2]]
  CACHE (0.0ms)  SELECT  "foods".* FROM "foods"  WHERE "foods"."id" = ? LIMIT 1  [["id", 2]]
  Recipe Exists (0.4ms)  SELECT  1 AS one FROM "recipes"  WHERE "recipes"."name" = 'Spaghetti Carbonara 2' LIMIT 1
   (0.2ms)  rollback transaction
Completed 422 Unprocessable Entity in 44ms (Views: 0.3ms | ActiveRecord: 2.1ms)

响应包含一条错误消息,指出未设置preparation_time参数:

{"preparation_time":["can't be blank","is not a number"]}

状态为422 Unprocessable Entity

category_idpreparation_time的验证规则完全相同:

  validates :preparation_time, presence: true, numericality: { only_integer: true, greater_than: 0 }
  validates :category_id, presence: true, numericality: { only_integer: true, greater_than: 0 }

为什么只用一个参数就会发生这种情况?这是我缺少的东西吗?它是rails中的错误吗?

1 个答案:

答案 0 :(得分:1)

您需要更改prepare_time列的类型。你可以这样做:

rails generate migration change_preparation_time_column

然后在生成的迁移中:

class ChangePreparationTimeColumn < ActiveRecord::Migration

  def change
    #change preparation time columntype from time to integer
    change_column :recipes, :preparation_time, :integer
  end
end

如果出于某种原因,您希望将类型保留为时间但确保首先转换参数,则可以始终在模型中执行以下操作(尽管我建议您执行前者)

Class Recipe
    ...

    before_save :convert_prep_time

    def convert_prep_time
      self.preparation_time = self.preparation_time.to_i unless self.preparation_time.blank?
    end

end