使用安全参数克隆对象

时间:2014-06-11 21:12:57

标签: ruby-on-rails

我的create方法不接受任何参数,而是使用姐妹对象来分配值。这些领域几乎相同,但并不完全相同。

我还想让create方法更简单(而不是使用.new,然后是.save)。

我希望下面的代码成为我的起点

控制器

def create
   design_setting = DesignSetting.first    
   primer3_parameter = Primer3Parameter.new
   primer3_parameter.update_attributes(design_setting.attributes)
   primer3_parameter.save
   render json: primer3_parameter, root: false
end

 def safe_params
    params.permit(:generated, :status, :p3_file_id, :p3_file_flag,

...etc...

模型

class Primer3Parameter < ActiveRecord::Base
  has_many :batch_details
end

错误

Started POST "/api/primer3_parameters" for 10.0.2.2 at 2014-06-11 23:15:38 +0200
Processing by Api::Primer3ParametersController#create as JSON
  Parameters: {"base"=>{}}
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
  DesignSetting Load (1.1ms)  SELECT "design_settings".* FROM "design_settings" ORDER BY "design_settings"."id" ASC LIMIT 1
  (0.2ms)  BEGIN
   (0.3ms)  ROLLBACK
   Completed 500 Internal Server Error in 350ms

  ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes for      Primer3Parameter: type, id):
    app/controllers/api/primer3_parameters_controller.rb:12:in `create'

编辑

按照以下建议重构后,会出现同样的错误:

Started POST "/api/primer3_parameters" for 10.0.2.2 at 2014-06-11 23:27:25 +0200
Processing by Api::Primer3ParametersController#create as JSON
  Parameters: {"base"=>{}}
  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
  DesignSetting Load (1.2ms)  SELECT "design_settings".* FROM "design_settings" ORDER BY "design_settings"."id" ASC LIMIT 1
Completed 500 Internal Server Error in 172ms

ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes for     Primer3Parameter: type, id):

app / controllers / api / primer3_parameters_controller.rb:12:在'create'

编辑2

代码的第2版

def create
   design_setting = DesignSetting.first    
   primer_attributes = design_setting.attributes.except(:id, :created_at, :updated_at, :type) 
   primer_attributes = design_setting.dup
   Rails.logger.debug("attributes #{primer_attributes}") 
   primer3_parameter = Primer3Parameter.create(primer_attributes)
   render json: primer3_parameter, root: false
end

Started POST "/api/primer3_parameters" for 10.0.2.2 at 2014-06-11 23:33:21 +0200
Processing by Api::Primer3ParametersController#create as JSON
  Parameters: {"base"=>{}}
  User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
  DesignSetting Load (1.5ms)  SELECT "design_settings".* FROM "design_settings" ORDER BY "design_settings"."id" ASC LIMIT 1
attributes #<DesignSetting:0x0000000cca1988>
Completed 500 Internal Server Error in 163ms

NoMethodError (undefined method `stringify_keys' for #<DesignSetting:0x0000000cca1988>):
  app/controllers/api/primer3_parameters_controller.rb:14:in `create'

编辑3

 def create
   design_setting = DesignSetting.first    
   primer_attributes = design_setting.attributes.except(:id, :type, :created_at, :updated_at)  
   primer3_parameter = Primer3Parameter.create(primer_attributes)
   render json: primer3_parameter, root: false
 end


ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes for     Primer3Parameter: type, id):

app / controllers / api / primer3_parameters_controller.rb:12:在'create'

EDIT4

此表格中包含 lot 字段,因此并非所有字段都粘贴在下方。

我注意到了一些事情 - id是最后一列,而不是第一列。但这没关系?

DesignSetting Load (1.3ms)  SELECT "design_settings".* FROM "design_settings" ORDER BY "design_settings"."id" ASC LIMIT 1
parms: {"type"=>nil, "user_id"=>nil, "generated"=>nil, "status"=>nil, "p3_file_type"=>nil, "p3_file_id"=>"empty", "p3_file_flag"=>false, "p3_comment"=>"empty", "sequence_excluded_region"=>"empty", "sequence_force_left_end"=>nil

2 个答案:

答案 0 :(得分:1)

您可以在属性'hash:

上使用.except方法
primer3_parameter.update_attributes(design_setting.attributes.except(:id, :created_at, :updated_at, :type))

您还可以将创建操作重构为:

def create
  design_setting = DesignSetting.first    
  primer_attributes = design_setting.attributes.except(:id, :type, :created_at, :updated_at)  
  primer3_parameter = Primer3Parameter.create(primer_attributes)
  render json: primer3_parameter, root: false
end

答案 1 :(得分:0)

好的,这样做了:

design_setting = DesignSetting.first
p = Primer3Parameter.new
p.attributes = design_setting.attributes.select{ |k, v| not %w{id type user_id created_at updated_at}.include?(k) }
p.save

感谢@MrYoshiji的帮助。