DiegoSalazar
DiegoSalazar

Reputation: 13531

RSpec controller testing nested strong parameters

I may or may not have found a bug in the RSpec code that doesn't let it post nested attributes as needed when using accepts_nested_attributes_for.

Here is my controller test:

it 'attaches a file to document' do
  post :create, {
    app_id: @app1.id,
    document: {
      recipient_id: @app2.id,
      delivery_service: 'default',
      attachments_attributes: {
        0 => {
          attachment: fixture_file_upload('files/document.json', 'application/json')
        }
      }
    },
    format: 'json'
  }

  attachment = assigns(:document).attachments.first
  attachment.exists?.should be_true
  attachment.url.should match 'amazon'
end

Here's the documents controller's strong params:

private

def document_params
  params.require(:document).permit(
    :recipient_id,
    :delivery_service,
    :document_id,
    :document_type,
    attachments_attributes:
      [:attachment, :attachment_file_name, :attachment_file_size, :attachment_content_type, :attachment_updated_at]
  )
end

When the test posts to the controller the attachments_attributes get ignored because it doesn't recognize the 0 key. But that's how the attributes are supposed to be and it works live.

When I take the 0 key out and leave just this in the test:

attachments_attributes: {
  attachment: fixture_file_upload('files/document.json', 'application/json')
}

I get undefined method '[]' for Tempfile

Here's that backtrace from my controller up:

# ~/.rvm/gems/ruby-2.0.0-p0/gems/rack-test-0.6.2/lib/rack/test/uploaded_file.rb:40:in `method_missing'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/nested_attributes.rb:452:in `block in assign_nested_attributes_for_collection_association'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/nested_attributes.rb:452:in `map'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/nested_attributes.rb:452:in `assign_nested_attributes_for_collection_association'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/nested_attributes.rb:339:in `attachments_attributes='
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/attribute_assignment.rb:42:in `public_send'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/attribute_assignment.rb:42:in `_assign_attribute'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/attribute_assignment.rb:53:in `block in assign_nested_parameter_attributes'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/attribute_assignment.rb:53:in `each'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/attribute_assignment.rb:53:in `assign_nested_parameter_attributes'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/attribute_assignment.rb:33:in `assign_attributes'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/core.rb:192:in `initialize'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:27:in `new'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:27:in `new'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/reflection.rb:189:in `build_association'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/associations/association.rb:242:in `build_record'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:114:in `build'
# ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-4.0.0/lib/active_record/associations/collection_proxy.rb:229:in `build'
# ./app/controllers/documents_controller.rb:17:in `create'

nested_attributes.rb still expects the attachments_attributes to be indexed but something RSpec is doing doesn't let it go through the strong parameters. Maybe it's just passing the hash straight through rather than as a query string as the browser does? I'll keep digging.

Has anyone else dealt with this before? Thanks!

Upvotes: 1

Views: 1078

Answers (1)

DiegoSalazar
DiegoSalazar

Reputation: 13531

Ok guys... my baaad.

the attributes have to be string indexed. So instead of:

  attachments_attributes: {
    0 => {
      attachment: fixture_file_upload('files/document.json', 'application/json')
    }
  }

I had to do this:

  attachments_attributes: {
    "0" => {
      attachment: fixture_file_upload('files/document.json', 'application/json')
    }
  }

So yea. 0 was supposed to be "0". No bug found here. I'll go sit in the corner now.

Upvotes: 5

Related Questions