API v2 adding/removing associations: to wrap parameters or not?

There are two ways to add/remove associations in API v2 for PUT and POST.

The question is which one (or both) are we going to document and support going forward?

  1. pass data attribute *_ids=[array,of,ids] in POST/PUT. This requires that the data attributes are WRAPPED within an object node.
  2. pass child node in PUT/POST data hash similar to what is received in GET. This requires that the data attributes are NOT WRAPPED within an object node.

Example: PUT api/v2/operatingsystems/24

Ex #1) WRAPPED in object node and use *_ids - this works

{
"operatingsystem": {
"name": "CentOs",
"config_template_ids": [36, 12, 40, 4, 3, 1]
}
}

Ex #2) NOT WRAPPED in object node and use child node - this works

PUT api/v2/operatingsystems/24
{
"name": "CentOs",
"config_templates": [
{
"id": 36,
"name": "CentOS-enabled-post"
},
{
"id": 12,
"name": "Grubby Default"
},
{
"id": 40,
"name": "Katello Kickstart Default",
},
{
"id": 4,
"name": "Kickstart Default"
},
{
"id": 3,
"name": "Kickstart default gPXE"
},
{
"id": 1,
"name": "Kickstart default PXElinux"
}
]
}

The examples will NOT work! (even though users may assume that they would)

Ex #3) NOT WRAPPING in object node using *_ids when it NEEDS TO BE. This does NOT give an error, but does NOT update config_template_ids.
params['config_template_ids'] is IGNORED in @operatingsystem.update_attributes(params[:operatingsystem])

{
"name": "CentOs",
"config_template_ids": [36, 12, 40, 4, 3, 1]
}

Ex #4) WRAPPING child node within object node when it SHOULD NOT BE. This gives an ERROR. { "message": "ConfigTemplate(#98749620) expected, got ActiveSupport::HashWithIndifferentAccess(#18888980)"}

{
"operatingsystem": {
"name": "CentOs",
"config_templates": [
{
"id": 36,
"name": "CentOS-enabled-post"
},
{
"id": 12,
"name": "Grubby Default"
},
{
"id": 40,
"name": "Katello Kickstart Default",
},
{
"id": 4,
"name": "Kickstart Default"
},
{
"id": 3,
"name": "Kickstart default gPXE"
},
{
"id": 1,
"name": "Kickstart default PXElinux"
}
]
}
}

Regards,

Joseph

I'd go for #2 and #3, without the 'operatingsystem' extra layer. The
resource is already known via the URL.

··· On Tue, Dec 24, 2013 at 10:07 AM, Joseph Magen wrote:

There are two ways to add/remove associations in API v2 for PUT and POST.

The question is which one (or both) are we going to document and support
going forward?

  1. pass data attribute *_ids=[array,of,ids] in POST/PUT. This requires
    that the data attributes are WRAPPED within an object node.
  2. pass child node in PUT/POST data hash similar to what is received in
    GET. This requires that the data attributes are NOT WRAPPED within an
    object node.

Example: PUT api/v2/operatingsystems/24

Ex #1) WRAPPED in object node and use *_ids - this works

{
“operatingsystem”: {
“name”: “CentOs”,
“config_template_ids”: [36, 12, 40, 4, 3, 1]
}
}

Ex #2) NOT WRAPPED in object node and use child node - this works

PUT api/v2/operatingsystems/24
{
“name”: “CentOs”,
“config_templates”: [
{
“id”: 36,
“name”: “CentOS-enabled-post”
},
{
“id”: 12,
“name”: “Grubby Default”
},
{
“id”: 40,
“name”: “Katello Kickstart Default”,
},
{
“id”: 4,
“name”: “Kickstart Default”
},
{
“id”: 3,
“name”: “Kickstart default gPXE”
},
{
“id”: 1,
“name”: “Kickstart default PXElinux”
}
]
}

The examples will NOT work! (even though users may assume that they would)

Ex #3) NOT WRAPPING in object node using *_ids when it NEEDS TO BE. This
does NOT give an error, but does NOT update config_template_ids.
params[‘config_template_ids’] is IGNORED in
@operatingsystem.update_attributes(params[:operatingsystem])

{
“name”: “CentOs”,
“config_template_ids”: [36, 12, 40, 4, 3, 1]
}

Ex #4) WRAPPING child node within object node when it SHOULD NOT BE. This
gives an ERROR. { “message”: “ConfigTemplate(#98749620) expected, got
ActiveSupport::HashWithIndifferentAccess(#18888980)”}

{
“operatingsystem”: {
“name”: “CentOs”,
“config_templates”: [
{
“id”: 36,
“name”: “CentOS-enabled-post”
},
{
“id”: 12,
“name”: “Grubby Default”
},
{
“id”: 40,
“name”: “Katello Kickstart Default”,
},
{
“id”: 4,
“name”: “Kickstart Default”
},
{
“id”: 3,
“name”: “Kickstart default gPXE”
},
{
“id”: 1,
“name”: “Kickstart default PXElinux”
}
]
}
}

Regards,

Joseph


You received this message because you are subscribed to the Google Groups
"foreman-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to foreman-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Daniel Lobato

@elobatoss
blog.daniellobato.me
daniellobato.me

GPG: http://keys.gnupg.net/pks/lookup?op=get&search=0x7A92D6DD38D6DE30

> From: "Daniel Lobato" <elobatocs@gmail.com>
> To: foreman-dev@googlegroups.com
> Sent: Tuesday, December 24, 2013 12:02:24 PM
> Subject: Re: [foreman-dev] API v2 adding/removing associations: to wrap parameters or not?
>
> I'd go for #2 and #3, without the 'operatingsystem' extra layer. The
> resource is already known via the URL.

A typical update method is is a controller

  def update
    process_response @operatingsystem.update_attributes(params[:operatingsystem])
  end

If there is no "operatingsystem' node, then parameters are supposed to be wrapped by initializers/wrap_parameters.rb, but they are not. Here is the Rails log of PUT for method #3 (that doesn't work)

Started PUT "/api/v2/operatingsystems/24" for 127.0.0.1 at 2013-12-24 12:58:49 +0200
Processing by Api::V2::OperatingsystemsController#update as JSON
Parameters: {"name"=>"CentOs", "config_template_ids"=>[36, 12, 40, 4, 3, 1, 33], "apiv"=>"v2", "id"=>"24", "operatingsystem"=>{"name"=>"CentOs"}}

As you see, only the "name" attribute was wrapped inside "operatingsystem" and "config_template_ids" was not. Therefore, the call update_attributes(params[:operatingsystem]) does not use the "config_template_ids" parameter.

Does anybody know how to modify initializers/wrap_parameters.rb to get this to work.

··· ----- Original Message -----

On Tue, Dec 24, 2013 at 10:07 AM, Joseph Magen jmagen@redhat.com wrote:

There are two ways to add/remove associations in API v2 for PUT and POST.

The question is which one (or both) are we going to document and support
going forward?

  1. pass data attribute *_ids=[array,of,ids] in POST/PUT. This requires
    that the data attributes are WRAPPED within an object node.
  2. pass child node in PUT/POST data hash similar to what is received in
    GET. This requires that the data attributes are NOT WRAPPED within an
    object node.

Example: PUT api/v2/operatingsystems/24

Ex #1) WRAPPED in object node and use *_ids - this works

{
“operatingsystem”: {
“name”: “CentOs”,
“config_template_ids”: [36, 12, 40, 4, 3, 1]
}
}

Ex #2) NOT WRAPPED in object node and use child node - this works

PUT api/v2/operatingsystems/24
{
“name”: “CentOs”,
“config_templates”: [
{
“id”: 36,
“name”: “CentOS-enabled-post”
},
{
“id”: 12,
“name”: “Grubby Default”
},
{
“id”: 40,
“name”: “Katello Kickstart Default”,
},
{
“id”: 4,
“name”: “Kickstart Default”
},
{
“id”: 3,
“name”: “Kickstart default gPXE”
},
{
“id”: 1,
“name”: “Kickstart default PXElinux”
}
]
}

The examples will NOT work! (even though users may assume that they would)

Ex #3) NOT WRAPPING in object node using *_ids when it NEEDS TO BE. This
does NOT give an error, but does NOT update config_template_ids.
params[‘config_template_ids’] is IGNORED in
@operatingsystem.update_attributes(params[:operatingsystem])

{
“name”: “CentOs”,
“config_template_ids”: [36, 12, 40, 4, 3, 1]
}

Ex #4) WRAPPING child node within object node when it SHOULD NOT BE. This
gives an ERROR. { “message”: “ConfigTemplate(#98749620) expected, got
ActiveSupport::HashWithIndifferentAccess(#18888980)”}

{
“operatingsystem”: {
“name”: “CentOs”,
“config_templates”: [
{
“id”: 36,
“name”: “CentOS-enabled-post”
},
{
“id”: 12,
“name”: “Grubby Default”
},
{
“id”: 40,
“name”: “Katello Kickstart Default”,
},
{
“id”: 4,
“name”: “Kickstart Default”
},
{
“id”: 3,
“name”: “Kickstart default gPXE”
},
{
“id”: 1,
“name”: “Kickstart default PXElinux”
}
]
}
}

Regards,

Joseph


You received this message because you are subscribed to the Google Groups
"foreman-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to foreman-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Daniel Lobato

@elobatoss
blog.daniellobato.me
daniellobato.me

GPG: http://keys.gnupg.net/pks/lookup?op=get&search=0x7A92D6DD38D6DE30


You received this message because you are subscribed to the Google Groups
"foreman-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to foreman-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

I know you can call this in your controller:

wrap_parameters :include => [:config_template_ids]

You could maybe write a filter that scans the model for has_many associations and then calls wrap_parameters with a list of the association_ids columns.

In Katello, we're using AngularJS to PUT back to the API so we're not wrapping anything (I'm not sure how hard it would be for us to do so). Moreover, we PUT back a modified version of what we GET for show/index. Therefore, I think option #2 would be the only feasible option for us.

David

··· ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Tuesday, December 24, 2013 6:09:30 AM > Subject: Re: [foreman-dev] API v2 adding/removing associations: to wrap parameters or not? > > ----- Original Message ----- > > From: "Daniel Lobato" > > To: foreman-dev@googlegroups.com > > Sent: Tuesday, December 24, 2013 12:02:24 PM > > Subject: Re: [foreman-dev] API v2 adding/removing associations: to wrap > > parameters or not? > > > > I'd go for #2 and #3, without the 'operatingsystem' extra layer. The > > resource is already known via the URL. > > A typical update method is is a controller > > def update > process_response > @operatingsystem.update_attributes(params[:operatingsystem]) > end > > If there is no "operatingsystem' node, then parameters are *supposed* to be > wrapped by initializers/wrap_parameters.rb, but they are not. Here is the > Rails log of PUT for method #3 (that doesn't work) > > Started PUT "/api/v2/operatingsystems/24" for 127.0.0.1 at 2013-12-24 > 12:58:49 +0200 > Processing by Api::V2::OperatingsystemsController#update as JSON > Parameters: {"name"=>"CentOs", "config_template_ids"=>[36, 12, 40, 4, 3, 1, > 33], "apiv"=>"v2", "id"=>"24", "operatingsystem"=>{"name"=>"CentOs"}} > > As you see, only the "name" attribute was wrapped inside "operatingsystem" > and "config_template_ids" was not. Therefore, the call > update_attributes(params[:operatingsystem]) does not use the > "config_template_ids" parameter. > > Does anybody know how to modify initializers/wrap_parameters.rb to get this > to work. > > > > > > > > > On Tue, Dec 24, 2013 at 10:07 AM, Joseph Magen wrote: > > > > > There are two ways to add/remove associations in API v2 for PUT and POST. > > > > > > The question is which one (or both) are we going to document and support > > > going forward? > > > > > > 1) pass data attribute *_ids=[array,of,ids] in POST/PUT. This requires > > > that the data attributes are WRAPPED within an object node. > > > 2) pass child node in PUT/POST data hash similar to what is received in > > > GET. This requires that the data attributes are NOT WRAPPED within an > > > object node. > > > > > > Example: PUT api/v2/operatingsystems/24 > > > > > > Ex #1) WRAPPED in object node and use *_ids - this works > > > > > > { > > > "operatingsystem": { > > > "name": "CentOs", > > > "config_template_ids": [36, 12, 40, 4, 3, 1] > > > } > > > } > > > > > > Ex #2) NOT WRAPPED in object node and use child node - this works > > > > > > PUT api/v2/operatingsystems/24 > > > { > > > "name": "CentOs", > > > "config_templates": [ > > > { > > > "id": 36, > > > "name": "CentOS-enabled-post" > > > }, > > > { > > > "id": 12, > > > "name": "Grubby Default" > > > }, > > > { > > > "id": 40, > > > "name": "Katello Kickstart Default", > > > }, > > > { > > > "id": 4, > > > "name": "Kickstart Default" > > > }, > > > { > > > "id": 3, > > > "name": "Kickstart default gPXE" > > > }, > > > { > > > "id": 1, > > > "name": "Kickstart default PXElinux" > > > } > > > ] > > > } > > > > > > > > > The examples will NOT work! (even though users may assume that they > > > would) > > > > > > Ex #3) NOT WRAPPING in object node using *_ids when it NEEDS TO BE. This > > > does NOT give an error, but does NOT update config_template_ids. > > > params['config_template_ids'] is IGNORED in > > > @operatingsystem.update_attributes(params[:operatingsystem]) > > > > > > { > > > "name": "CentOs", > > > "config_template_ids": [36, 12, 40, 4, 3, 1] > > > } > > > > > > Ex #4) WRAPPING child node within object node when it SHOULD NOT BE. > > > This > > > gives an ERROR. { "message": "ConfigTemplate(#98749620) expected, got > > > ActiveSupport::HashWithIndifferentAccess(#18888980)"} > > > > > > { > > > "operatingsystem": { > > > "name": "CentOs", > > > "config_templates": [ > > > { > > > "id": 36, > > > "name": "CentOS-enabled-post" > > > }, > > > { > > > "id": 12, > > > "name": "Grubby Default" > > > }, > > > { > > > "id": 40, > > > "name": "Katello Kickstart Default", > > > }, > > > { > > > "id": 4, > > > "name": "Kickstart Default" > > > }, > > > { > > > "id": 3, > > > "name": "Kickstart default gPXE" > > > }, > > > { > > > "id": 1, > > > "name": "Kickstart default PXElinux" > > > } > > > ] > > > } > > > } > > > > > > Regards, > > > > > > Joseph > > > > > > -- > > > You received this message because you are subscribed to the Google Groups > > > "foreman-dev" group. > > > To unsubscribe from this group and stop receiving emails from it, send an > > > email to foreman-dev+unsubscribe@googlegroups.com. > > > For more options, visit https://groups.google.com/groups/opt_out. > > > > > > > > > > > -- > > Daniel Lobato > > > > @elobatoss > > blog.daniellobato.me > > daniellobato.me > > > > GPG: http://keys.gnupg.net/pks/lookup?op=get&search=0x7A92D6DD38D6DE30 > > > > -- > > You received this message because you are subscribed to the Google Groups > > "foreman-dev" group. > > To unsubscribe from this group and stop receiving emails from it, send an > > email to foreman-dev+unsubscribe@googlegroups.com. > > For more options, visit https://groups.google.com/groups/opt_out. > > > > -- > You received this message because you are subscribed to the Google Groups > "foreman-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to foreman-dev+unsubscribe@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. >