1

My create method does not take any parameters, rather it uses a sister object to assign the values. The fields are almost the same, but not quite.

I would also like to make the create method simpler (instead of doing a .new and then .save).

I would like the code below to be my starting point

controller

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...

model

class Primer3Parameter < ActiveRecord::Base
  has_many :batch_details
end

error

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'

EDIT

After refactoring as suggested below the same error appears:

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:in `create'

EDIT 2

Version 2 of the code

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'

EDIT 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:in `create'

EDIT4

This table has a lot of fields, so not all are pasted below.

I did notice something - the id is the last column, not the first. But it should not matter?

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
port5432
  • 5,889
  • 10
  • 60
  • 97
  • possible duplicate of [What is the easiest way to duplicate an activerecord record?](http://stackoverflow.com/questions/60033/what-is-the-easiest-way-to-duplicate-an-activerecord-record) – Brad Werth Jun 11 '14 at 21:18
  • Note that the two models have many of the same fields but are not identical copies of each other. – port5432 Jun 11 '14 at 21:23

2 Answers2

1

You can use the .except method on the attributes' hash:

primer3_parameter.update_attributes(design_setting.attributes.except(:id, :created_at, :updated_at, :type))

You can also refactor your create action to this:

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
MrYoshiji
  • 54,334
  • 13
  • 124
  • 117
  • Thanks for your suggestion but I am still getting the error on :id & :type. See the edit above. – port5432 Jun 11 '14 at 21:21
  • Are you sure that the `primer_attributes` still contains `:id` and `:type` key/value ? @ardochhigh (you can test it by doing `raiser primer_attributes` inside the create action, you will see the actual content of the hash) – MrYoshiji Jun 11 '14 at 21:24
  • Why would you add `primer_attributes = design_setting.dup`!? It does not make sense. Just use my code without adding piece of code coming from nowhere. It will not work if you change it. – MrYoshiji Jun 11 '14 at 21:30
  • Great, thank you. Now we can debug in peace. When you do `Rails.logger.debug(primer_attributes)`, does it outputs a Hash with the `:id `and `:type` key/value? – MrYoshiji Jun 11 '14 at 21:34
  • Neither :id or :type are in the hash – port5432 Jun 11 '14 at 21:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/55465/discussion-between-ardochhigh-and-mryoshiji). – port5432 Jun 11 '14 at 21:41
0

Ok this did it:

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

Thank you @MrYoshiji for your help.

port5432
  • 5,889
  • 10
  • 60
  • 97