Updating many-to-many relationships

So there seems to be a divergence in how Foreman and Katello handle many-to-many relationships. To give a couple examples of these, one would be architectures which have and belong to many OSes in Foreman. In Katello, content views has and belongs to many repositories There 2-3 options for updating these relationships:

  1. Send in operating_system_ids on PUT /architecture/2
  2. Have add_operating_systems and remove_operating_systems actions that take ids
  3. Both 2 and 3

Foreman looks like it mostly supports 1 while Katello has a combination in its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is simpler while 2 would maybe be easier to use for the user. 3 seems like a good option but would be the most work.

Thoughts?

David

Even though I just followed an existing pattern and implemented a new occurrence of #2, I prefer #1 as it is more RESTful.

Cheers,
Walden

··· ----- Original Message ----- From: "David Davis" To: "foreman-dev" Sent: Tuesday, January 28, 2014 3:01:29 PM Subject: [foreman-dev] Updating many-to-many relationships

So there seems to be a divergence in how Foreman and Katello handle many-to-many relationships. To give a couple examples of these, one would be architectures which have and belong to many OSes in Foreman. In Katello, content views has and belongs to many repositories There 2-3 options for updating these relationships:

  1. Send in operating_system_ids on PUT /architecture/2
  2. Have add_operating_systems and remove_operating_systems actions that take ids
  3. Both 2 and 3

Foreman looks like it mostly supports 1 while Katello has a combination in its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is simpler while 2 would maybe be easier to use for the user. 3 seems like a good option but would be the most work.

Thoughts?

David


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.

There's a 3rd option and that is to PUT the JSON response from GET

GET api/v2/operatingsystems/24

Part of the response includes architectures as a child-node

{
"id": 24,
"name": "CentOs",
"architectures": [
{
"name": "x86_64",
"id": 1
}
]
}

PUT api/v2/operatingsystems/24

And ad another OS in the JSON data

{
"id": 24,
"name": "CentOs",
"architectures": [
{
"name": "x86_64",
"id": 1
},
{
"name": "i386",
"id": 2
}
]
}

Actually, most of the JSON data above is unnecessary. I can just pass in the relationship node with a collection of ids

PUT api/v2/operatingsystems/24

{
"architectures": [
{
"id": 1
},
{
"id": 2
}
]
}

Note that you can NOT add or remove a SINGLE id as in your option #2. I agree with Walden not to implement this.

Below, this example CREATES a record in has_and_belongs_to_many relationship table

PUT api/v2/operatingsystems/24

{
"architectures": [
{
"id": 1
},
{
"id": 2
}
},
{
"id": 3
}
]
}

This DELETES a record in has_and_belongs_to_many relationship table

PUT api/v2/operatingsystems/24

{
"architectures": [
{
"id": 1
}
]
}

Note that this should work with every has_many or has_and_belongs_to_many relationship even if nested routes or child nodes may not appear for in RABL templates for all objects.

In summary, Foreman supports
#1) Array on attribute operatingsystem_ids on PUT /architecture/2

{
"operatingsystem_ids": [24,25,26]
}

#3) Array on child not operatingsystems PUT /architecture/2

{
"operatingsystems": [{"id": 24},{"id": 25},{"id": 26}]
}

David, I hope this helps. I agree that the documentation needs to be better. Can you take the initiative on updating the docs once we reach a final decision.

Thanks,

Joseph

··· ----- Original Message ----- > From: "Walden Raines" > To: foreman-dev@googlegroups.com > Sent: Tuesday, January 28, 2014 10:20:15 PM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > Even though I just followed an existing pattern and implemented a new > occurrence of #2, I prefer #1 as it is more RESTful. > > Cheers, > Walden > > ----- Original Message ----- > From: "David Davis" > To: "foreman-dev" > Sent: Tuesday, January 28, 2014 3:01:29 PM > Subject: [foreman-dev] Updating many-to-many relationships > > So there seems to be a divergence in how Foreman and Katello handle > many-to-many relationships. To give a couple examples of these, one would be > architectures which have and belong to many OSes in Foreman. In Katello, > content views has and belongs to many repositories There 2-3 options for > updating these relationships: > > 1. Send in operating_system_ids on PUT /architecture/2 > 2. Have add_operating_systems and remove_operating_systems actions that take > ids > 3. Both 2 and 3 > > Foreman looks like it mostly supports 1 while Katello has a combination in > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is simpler > while 2 would maybe be easier to use for the user. 3 seems like a good > option but would be the most work. > > Thoughts? > > David > > -- > 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. >

Joseph,

I'll update the docs when we reach a decision. Question though: how did you all add support for the third option you outlined? Does it comes with Rails?

David

··· ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 2:59:08 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > There's a 3rd option and that is to PUT the JSON response from GET > > GET api/v2/operatingsystems/24 > > Part of the response includes architectures as a child-node > > { > "id": 24, > "name": "CentOs", > "architectures": [ > { > "name": "x86_64", > "id": 1 > } > ] > } > > PUT api/v2/operatingsystems/24 > > And ad another OS in the JSON data > > { > "id": 24, > "name": "CentOs", > "architectures": [ > { > "name": "x86_64", > "id": 1 > }, > { > "name": "i386", > "id": 2 > } > ] > } > > Actually, most of the JSON data above is unnecessary. I can just pass in the > relationship node with a collection of ids > > PUT api/v2/operatingsystems/24 > > { > "architectures": [ > { > "id": 1 > }, > { > "id": 2 > } > ] > } > > Note that you can NOT add or remove a SINGLE id as in your option #2. I > agree with Walden not to implement this. > > Below, this example CREATES a record in has_and_belongs_to_many relationship > table > > PUT api/v2/operatingsystems/24 > > { > "architectures": [ > { > "id": 1 > }, > { > "id": 2 > } > }, > { > "id": 3 > } > ] > } > > This DELETES a record in has_and_belongs_to_many relationship table > > PUT api/v2/operatingsystems/24 > > { > "architectures": [ > { > "id": 1 > } > ] > } > > > Note that this should work with every has_many or has_and_belongs_to_many > relationship even if nested routes or child nodes may not appear for in RABL > templates for all objects. > > > In summary, Foreman supports > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > { > "operatingsystem_ids": [24,25,26] > } > > #3) Array on child not operatingsystems PUT /architecture/2 > > { > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > } > > David, I hope this helps. I agree that the documentation needs to be better. > Can you take the initiative on updating the docs once we reach a final > decision. > > Thanks, > > Joseph > > > > > > > > > > > > ----- Original Message ----- > > From: "Walden Raines" > > To: foreman-dev@googlegroups.com > > Sent: Tuesday, January 28, 2014 10:20:15 PM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > Even though I just followed an existing pattern and implemented a new > > occurrence of #2, I prefer #1 as it is more RESTful. > > > > Cheers, > > Walden > > > > ----- Original Message ----- > > From: "David Davis" > > To: "foreman-dev" > > Sent: Tuesday, January 28, 2014 3:01:29 PM > > Subject: [foreman-dev] Updating many-to-many relationships > > > > So there seems to be a divergence in how Foreman and Katello handle > > many-to-many relationships. To give a couple examples of these, one would > > be > > architectures which have and belong to many OSes in Foreman. In Katello, > > content views has and belongs to many repositories There 2-3 options for > > updating these relationships: > > > > 1. Send in operating_system_ids on PUT /architecture/2 > > 2. Have add_operating_systems and remove_operating_systems actions that > > take > > ids > > 3. Both 2 and 3 > > > > Foreman looks like it mostly supports 1 while Katello has a combination in > > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > simpler > > while 2 would maybe be easier to use for the user. 3 seems like a good > > option but would be the most work. > > > > Thoughts? > > > > David > > > > -- > > 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. > > > > -- > 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. >

What about a

PUT api/v2/operatingsystems/24/architectures

??

– bk

··· On 01/29/2014 02:59 AM, Joseph Magen wrote: > There's a 3rd option and that is to PUT the JSON response from GET > > GET api/v2/operatingsystems/24 > > Part of the response includes architectures as a child-node > > { > "id": 24, > "name": "CentOs", > "architectures": [ > { > "name": "x86_64", > "id": 1 > } > ] > } > > PUT api/v2/operatingsystems/24 > > And ad another OS in the JSON data > > { > "id": 24, > "name": "CentOs", > "architectures": [ > { > "name": "x86_64", > "id": 1 > }, > { > "name": "i386", > "id": 2 > } > ] > } > > Actually, most of the JSON data above is unnecessary. I can just pass in the relationship node with a collection of ids > > PUT api/v2/operatingsystems/24 > > { > "architectures": [ > { > "id": 1 > }, > { > "id": 2 > } > ] > } > > Note that you can NOT add or remove a SINGLE id as in your option #2. I agree with Walden not to implement this. > > Below, this example CREATES a record in has_and_belongs_to_many relationship table > > PUT api/v2/operatingsystems/24 > > { > "architectures": [ > { > "id": 1 > }, > { > "id": 2 > } > }, > { > "id": 3 > } > ] > } > > This DELETES a record in has_and_belongs_to_many relationship table > > PUT api/v2/operatingsystems/24 > > { > "architectures": [ > { > "id": 1 > } > ] > } > > > Note that this should work with every has_many or has_and_belongs_to_many relationship even if nested routes or child nodes may not appear for in RABL templates for all objects. > > > In summary, Foreman supports > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > { > "operatingsystem_ids": [24,25,26] > } > > #3) Array on child not operatingsystems PUT /architecture/2 > > { > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > } > > David, I hope this helps. I agree that the documentation needs to be better. Can you take the initiative on updating the docs once we reach a final decision. > > Thanks, > > Joseph > > > > > > > > > > > > ----- Original Message ----- >> From: "Walden Raines" >> To: foreman-dev@googlegroups.com >> Sent: Tuesday, January 28, 2014 10:20:15 PM >> Subject: Re: [foreman-dev] Updating many-to-many relationships >> >> Even though I just followed an existing pattern and implemented a new >> occurrence of #2, I prefer #1 as it is more RESTful. >> >> Cheers, >> Walden >> >> ----- Original Message ----- >> From: "David Davis" >> To: "foreman-dev" >> Sent: Tuesday, January 28, 2014 3:01:29 PM >> Subject: [foreman-dev] Updating many-to-many relationships >> >> So there seems to be a divergence in how Foreman and Katello handle >> many-to-many relationships. To give a couple examples of these, one would be >> architectures which have and belong to many OSes in Foreman. In Katello, >> content views has and belongs to many repositories There 2-3 options for >> updating these relationships: >> >> 1. Send in operating_system_ids on PUT /architecture/2 >> 2. Have add_operating_systems and remove_operating_systems actions that take >> ids >> 3. Both 2 and 3 >> >> Foreman looks like it mostly supports 1 while Katello has a combination in >> its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is simpler >> while 2 would maybe be easier to use for the user. 3 seems like a good >> option but would be the most work. >> >> Thoughts? >> >> David >> >> -- >> 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. >> >

Option #3 is great when you want to rewrite everything, and terrible in all
other cases. Please allow the minimum edit. GET-modify-PUT has two big
problems: race conditions between editors, and large message size. If
you're trying to edit thingy x with parameter y, an URL to x is very
helpful for being specific and atomic.

··· On Wed, Jan 29, 2014 at 7:48 AM, Bryan Kearney wrote:

What about a

PUT api/v2/operatingsystems/24/architectures

??

– bk

On 01/29/2014 02:59 AM, Joseph Magen wrote:

There’s a 3rd option and that is to PUT the JSON response from GET

GET api/v2/operatingsystems/24

Part of the response includes architectures as a child-node

{
“id”: 24,
“name”: “CentOs”,
“architectures”: [
{
“name”: “x86_64”,
“id”: 1
}
]
}

PUT api/v2/operatingsystems/24

And ad another OS in the JSON data

{
“id”: 24,
“name”: “CentOs”,
“architectures”: [
{
“name”: “x86_64”,
“id”: 1
},
{
“name”: “i386”,
“id”: 2
}
]
}

Actually, most of the JSON data above is unnecessary. I can just pass in
the relationship node with a collection of ids

PUT api/v2/operatingsystems/24

{
“architectures”: [
{
“id”: 1
},
{
“id”: 2
}
]
}

Note that you can NOT add or remove a SINGLE id as in your option #2. I
agree with Walden not to implement this.

Below, this example CREATES a record in has_and_belongs_to_many
relationship table

PUT api/v2/operatingsystems/24

{
“architectures”: [
{
“id”: 1
},
{
“id”: 2
}
},
{
“id”: 3
}
]
}

This DELETES a record in has_and_belongs_to_many relationship table

PUT api/v2/operatingsystems/24

{
“architectures”: [
{
“id”: 1
}
]
}

Note that this should work with every has_many or has_and_belongs_to_many
relationship even if nested routes or child nodes may not appear for in
RABL templates for all objects.

In summary, Foreman supports
#1) Array on attribute operatingsystem_ids on PUT /architecture/2

{
“operatingsystem_ids”: [24,25,26]
}

#3) Array on child not operatingsystems PUT /architecture/2

{
“operatingsystems”: [{“id”: 24},{“id”: 25},{“id”: 26}]
}

David, I hope this helps. I agree that the documentation needs to be
better. Can you take the initiative on updating the docs once we reach a
final decision.

Thanks,

Joseph

----- Original Message -----

From: “Walden Raines” walden@redhat.com
To: foreman-dev@googlegroups.com
Sent: Tuesday, January 28, 2014 10:20:15 PM
Subject: Re: [foreman-dev] Updating many-to-many relationships

Even though I just followed an existing pattern and implemented a new
occurrence of #2, I prefer #1 as it is more RESTful.

Cheers,
Walden

----- Original Message -----
From: “David Davis” daviddavis@redhat.com
To: “foreman-dev” foreman-dev@googlegroups.com
Sent: Tuesday, January 28, 2014 3:01:29 PM
Subject: [foreman-dev] Updating many-to-many relationships

So there seems to be a divergence in how Foreman and Katello handle
many-to-many relationships. To give a couple examples of these, one
would be
architectures which have and belong to many OSes in Foreman. In Katello,
content views has and belongs to many repositories There 2-3 options for
updating these relationships:

  1. Send in operating_system_ids on PUT /architecture/2
  2. Have add_operating_systems and remove_operating_systems actions that
    take
    ids
  3. Both 2 and 3

Foreman looks like it mostly supports 1 while Katello has a combination
in
its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is
simpler
while 2 would maybe be easier to use for the user. 3 seems like a good
option but would be the most work.

Thoughts?

David


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.


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.

Hi David,

Rails comes out-of-the-box with support for column_names_ids = [1,2,3,4]

Option #3 I created a before_filter in api/v2/base_controller.rb

Basically, I manipulated the input to convert from an array of JSON objects to get attribute :column_names_ids = [1,2,3,4] which is what Rails likes in the standard update_attributes method
Note, column_names_names = ["name1", "name2"] also works.

Joseph

··· ----- Original Message ----- > From: "David Davis" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 3:13:57 PM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > Joseph, > > I'll update the docs when we reach a decision. Question though: how did you > all add support for the third option you outlined? Does it comes with Rails? > > David > > ----- Original Message ----- > > From: "Joseph Magen" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 2:59:08 AM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > There's a 3rd option and that is to PUT the JSON response from GET > > > > GET api/v2/operatingsystems/24 > > > > Part of the response includes architectures as a child-node > > > > { > > "id": 24, > > "name": "CentOs", > > "architectures": [ > > { > > "name": "x86_64", > > "id": 1 > > } > > ] > > } > > > > PUT api/v2/operatingsystems/24 > > > > And ad another OS in the JSON data > > > > { > > "id": 24, > > "name": "CentOs", > > "architectures": [ > > { > > "name": "x86_64", > > "id": 1 > > }, > > { > > "name": "i386", > > "id": 2 > > } > > ] > > } > > > > Actually, most of the JSON data above is unnecessary. I can just pass in > > the > > relationship node with a collection of ids > > > > PUT api/v2/operatingsystems/24 > > > > { > > "architectures": [ > > { > > "id": 1 > > }, > > { > > "id": 2 > > } > > ] > > } > > > > Note that you can NOT add or remove a SINGLE id as in your option #2. I > > agree with Walden not to implement this. > > > > Below, this example CREATES a record in has_and_belongs_to_many > > relationship > > table > > > > PUT api/v2/operatingsystems/24 > > > > { > > "architectures": [ > > { > > "id": 1 > > }, > > { > > "id": 2 > > } > > }, > > { > > "id": 3 > > } > > ] > > } > > > > This DELETES a record in has_and_belongs_to_many relationship table > > > > PUT api/v2/operatingsystems/24 > > > > { > > "architectures": [ > > { > > "id": 1 > > } > > ] > > } > > > > > > Note that this should work with every has_many or has_and_belongs_to_many > > relationship even if nested routes or child nodes may not appear for in > > RABL > > templates for all objects. > > > > > > In summary, Foreman supports > > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > > { > > "operatingsystem_ids": [24,25,26] > > } > > > > #3) Array on child not operatingsystems PUT /architecture/2 > > > > { > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > } > > > > David, I hope this helps. I agree that the documentation needs to be > > better. > > Can you take the initiative on updating the docs once we reach a final > > decision. > > > > Thanks, > > > > Joseph > > > > > > > > > > > > > > > > > > > > > > > > ----- Original Message ----- > > > From: "Walden Raines" > > > To: foreman-dev@googlegroups.com > > > Sent: Tuesday, January 28, 2014 10:20:15 PM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > Even though I just followed an existing pattern and implemented a new > > > occurrence of #2, I prefer #1 as it is more RESTful. > > > > > > Cheers, > > > Walden > > > > > > ----- Original Message ----- > > > From: "David Davis" > > > To: "foreman-dev" > > > Sent: Tuesday, January 28, 2014 3:01:29 PM > > > Subject: [foreman-dev] Updating many-to-many relationships > > > > > > So there seems to be a divergence in how Foreman and Katello handle > > > many-to-many relationships. To give a couple examples of these, one would > > > be > > > architectures which have and belong to many OSes in Foreman. In Katello, > > > content views has and belongs to many repositories There 2-3 options for > > > updating these relationships: > > > > > > 1. Send in operating_system_ids on PUT /architecture/2 > > > 2. Have add_operating_systems and remove_operating_systems actions that > > > take > > > ids > > > 3. Both 2 and 3 > > > > > > Foreman looks like it mostly supports 1 while Katello has a combination > > > in > > > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > > simpler > > > while 2 would maybe be easier to use for the user. 3 seems like a good > > > option but would be the most work. > > > > > > Thoughts? > > > > > > David > > > > > > -- > > > 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. > > > > > > > -- > > 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. >

To be specific and atomic, then you need to treat the many-to-many relation as its own resource. This is not the case with our example

PUT api/v2/operatingsystems/24

which update all the attributes AND associations for resource operating system #24

The RESTful way to only add or delete an association (similar to what we did for host_classes and hostgroup_classes) is this below: (Note that BOTH the architecture id and operating system id's already exist)

Create a new association
POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': 1}

object created
{
'id': 555
'operatingsystem_id': 24
'architecture_id': 1
}

Delete an association
DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555

This is similar to what Bryan may thought of when he wrote

> What about a
> PUT api/v2/operatingsystems/24/architectures

But the issue here is that PUT requires an ID of a resource to update.

The 'problem' with the atomic restful way is that most 'simple' API's don't expose the database internals such as id #555 on a join table which is meaningless to the user.

Regards,

Joseph

··· ----- Original Message ----- > From: "Aaron Stone" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 6:12:10 PM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > Option #3 is great when you want to rewrite everything, and terrible in all > other cases. Please allow the minimum edit. GET-modify-PUT has two big > problems: race conditions between editors, and large message size. If > you're trying to edit thingy x with parameter y, an URL to x is very > helpful for being specific and atomic. > > > On Wed, Jan 29, 2014 at 7:48 AM, Bryan Kearney > wrote: > > > What about a > > > > PUT api/v2/operatingsystems/24/architectures > > > > ?? > > > > -- bk > > > > > > On 01/29/2014 02:59 AM, Joseph Magen wrote: > > > >> There's a 3rd option and that is to PUT the JSON response from GET > >> > >> GET api/v2/operatingsystems/24 > >> > >> Part of the response includes architectures as a child-node > >> > >> { > >> "id": 24, > >> "name": "CentOs", > >> "architectures": [ > >> { > >> "name": "x86_64", > >> "id": 1 > >> } > >> ] > >> } > >> > >> PUT api/v2/operatingsystems/24 > >> > >> And ad another OS in the JSON data > >> > >> { > >> "id": 24, > >> "name": "CentOs", > >> "architectures": [ > >> { > >> "name": "x86_64", > >> "id": 1 > >> }, > >> { > >> "name": "i386", > >> "id": 2 > >> } > >> ] > >> } > >> > >> Actually, most of the JSON data above is unnecessary. I can just pass in > >> the relationship node with a collection of ids > >> > >> PUT api/v2/operatingsystems/24 > >> > >> { > >> "architectures": [ > >> { > >> "id": 1 > >> }, > >> { > >> "id": 2 > >> } > >> ] > >> } > >> > >> Note that you can NOT add or remove a SINGLE id as in your option #2. I > >> agree with Walden not to implement this. > >> > >> Below, this example CREATES a record in has_and_belongs_to_many > >> relationship table > >> > >> PUT api/v2/operatingsystems/24 > >> > >> { > >> "architectures": [ > >> { > >> "id": 1 > >> }, > >> { > >> "id": 2 > >> } > >> }, > >> { > >> "id": 3 > >> } > >> ] > >> } > >> > >> This DELETES a record in has_and_belongs_to_many relationship table > >> > >> PUT api/v2/operatingsystems/24 > >> > >> { > >> "architectures": [ > >> { > >> "id": 1 > >> } > >> ] > >> } > >> > >> > >> Note that this should work with every has_many or has_and_belongs_to_many > >> relationship even if nested routes or child nodes may not appear for in > >> RABL templates for all objects. > >> > >> > >> In summary, Foreman supports > >> #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > >> > >> { > >> "operatingsystem_ids": [24,25,26] > >> } > >> > >> #3) Array on child not operatingsystems PUT /architecture/2 > >> > >> { > >> "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > >> } > >> > >> David, I hope this helps. I agree that the documentation needs to be > >> better. Can you take the initiative on updating the docs once we reach a > >> final decision. > >> > >> Thanks, > >> > >> Joseph > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > >> ----- Original Message ----- > >> > >>> From: "Walden Raines" > >>> To: foreman-dev@googlegroups.com > >>> Sent: Tuesday, January 28, 2014 10:20:15 PM > >>> Subject: Re: [foreman-dev] Updating many-to-many relationships > >>> > >>> Even though I just followed an existing pattern and implemented a new > >>> occurrence of #2, I prefer #1 as it is more RESTful. > >>> > >>> Cheers, > >>> Walden > >>> > >>> ----- Original Message ----- > >>> From: "David Davis" > >>> To: "foreman-dev" > >>> Sent: Tuesday, January 28, 2014 3:01:29 PM > >>> Subject: [foreman-dev] Updating many-to-many relationships > >>> > >>> So there seems to be a divergence in how Foreman and Katello handle > >>> many-to-many relationships. To give a couple examples of these, one > >>> would be > >>> architectures which have and belong to many OSes in Foreman. In Katello, > >>> content views has and belongs to many repositories There 2-3 options for > >>> updating these relationships: > >>> > >>> 1. Send in operating_system_ids on PUT /architecture/2 > >>> 2. Have add_operating_systems and remove_operating_systems actions that > >>> take > >>> ids > >>> 3. Both 2 and 3 > >>> > >>> Foreman looks like it mostly supports 1 while Katello has a combination > >>> in > >>> its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > >>> simpler > >>> while 2 would maybe be easier to use for the user. 3 seems like a good > >>> option but would be the most work. > >>> > >>> Thoughts? > >>> > >>> David > >>> > >>> -- > >>> 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. > >>> > >>> > >> > > -- > > 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. >

I like option #3 even better, thanks Joseph.

We may have reached a decision unless there are any dissenting opinions that remain unvoiced.

Cheers,
Walden

··· ----- Original Message ----- From: "Joseph Magen" To: foreman-dev@googlegroups.com Sent: Wednesday, January 29, 2014 8:22:11 AM Subject: Re: [foreman-dev] Updating many-to-many relationships

Hi David,

Rails comes out-of-the-box with support for column_names_ids = [1,2,3,4]

Option #3 I created a before_filter in api/v2/base_controller.rb

Basically, I manipulated the input to convert from an array of JSON objects to get attribute :column_names_ids = [1,2,3,4] which is what Rails likes in the standard update_attributes method
Note, column_names_names = [“name1”, “name2”] also works.

Joseph

----- Original Message -----

From: “David Davis” daviddavis@redhat.com
To: foreman-dev@googlegroups.com
Sent: Wednesday, January 29, 2014 3:13:57 PM
Subject: Re: [foreman-dev] Updating many-to-many relationships

Joseph,

I’ll update the docs when we reach a decision. Question though: how did you
all add support for the third option you outlined? Does it comes with Rails?

David

----- Original Message -----

From: “Joseph Magen” jmagen@redhat.com
To: foreman-dev@googlegroups.com
Sent: Wednesday, January 29, 2014 2:59:08 AM
Subject: Re: [foreman-dev] Updating many-to-many relationships

There’s a 3rd option and that is to PUT the JSON response from GET

GET api/v2/operatingsystems/24

Part of the response includes architectures as a child-node

{
“id”: 24,
“name”: “CentOs”,
“architectures”: [
{
“name”: “x86_64”,
“id”: 1
}
]
}

PUT api/v2/operatingsystems/24

And ad another OS in the JSON data

{
“id”: 24,
“name”: “CentOs”,
“architectures”: [
{
“name”: “x86_64”,
“id”: 1
},
{
“name”: “i386”,
“id”: 2
}
]
}

Actually, most of the JSON data above is unnecessary. I can just pass in
the
relationship node with a collection of ids

PUT api/v2/operatingsystems/24

{
“architectures”: [
{
“id”: 1
},
{
“id”: 2
}
]
}

Note that you can NOT add or remove a SINGLE id as in your option #2. I
agree with Walden not to implement this.

Below, this example CREATES a record in has_and_belongs_to_many
relationship
table

PUT api/v2/operatingsystems/24

{
“architectures”: [
{
“id”: 1
},
{
“id”: 2
}
},
{
“id”: 3
}
]
}

This DELETES a record in has_and_belongs_to_many relationship table

PUT api/v2/operatingsystems/24

{
“architectures”: [
{
“id”: 1
}
]
}

Note that this should work with every has_many or has_and_belongs_to_many
relationship even if nested routes or child nodes may not appear for in
RABL
templates for all objects.

In summary, Foreman supports
#1) Array on attribute operatingsystem_ids on PUT /architecture/2

{
“operatingsystem_ids”: [24,25,26]
}

#3) Array on child not operatingsystems PUT /architecture/2

{
“operatingsystems”: [{“id”: 24},{“id”: 25},{“id”: 26}]
}

David, I hope this helps. I agree that the documentation needs to be
better.
Can you take the initiative on updating the docs once we reach a final
decision.

Thanks,

Joseph

----- Original Message -----

From: “Walden Raines” walden@redhat.com
To: foreman-dev@googlegroups.com
Sent: Tuesday, January 28, 2014 10:20:15 PM
Subject: Re: [foreman-dev] Updating many-to-many relationships

Even though I just followed an existing pattern and implemented a new
occurrence of #2, I prefer #1 as it is more RESTful.

Cheers,
Walden

----- Original Message -----
From: “David Davis” daviddavis@redhat.com
To: “foreman-dev” foreman-dev@googlegroups.com
Sent: Tuesday, January 28, 2014 3:01:29 PM
Subject: [foreman-dev] Updating many-to-many relationships

So there seems to be a divergence in how Foreman and Katello handle
many-to-many relationships. To give a couple examples of these, one would
be
architectures which have and belong to many OSes in Foreman. In Katello,
content views has and belongs to many repositories There 2-3 options for
updating these relationships:

  1. Send in operating_system_ids on PUT /architecture/2
  2. Have add_operating_systems and remove_operating_systems actions that
    take
    ids
  3. Both 2 and 3

Foreman looks like it mostly supports 1 while Katello has a combination
in
its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is
simpler
while 2 would maybe be easier to use for the user. 3 seems like a good
option but would be the most work.

Thoughts?

David


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.


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.


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.

What about something like this?

PUT api/v2/operatingsystems/24 -d {'add_architecture_ids': 1}

Seems like it would be easy to implement, atomic, and RESTful?

David

··· ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Thursday, January 30, 2014 2:42:10 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > To be specific and atomic, then you need to treat the many-to-many relation > as its own resource. This is not the case with our example > > PUT api/v2/operatingsystems/24 > > which update all the attributes AND associations for resource operating > system #24 > > The RESTful way to only add or delete an association (similar to what we did > for host_classes and hostgroup_classes) is this below: (Note that BOTH the > architecture id and operating system id's already exist) > > Create a new association > POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': 1} > > object created > { > 'id': 555 > 'operatingsystem_id': 24 > 'architecture_id': 1 > } > > Delete an association > DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555 > > This is similar to what Bryan may thought of when he wrote > > > What about a > > PUT api/v2/operatingsystems/24/architectures > > But the issue here is that PUT requires an ID of a resource to update. > > The 'problem' with the atomic restful way is that most 'simple' API's don't > expose the database internals such as id #555 on a join table which is > meaningless to the user. > > Regards, > > Joseph > > > > > ----- Original Message ----- > > From: "Aaron Stone" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 6:12:10 PM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > Option #3 is great when you want to rewrite everything, and terrible in all > > other cases. Please allow the minimum edit. GET-modify-PUT has two big > > problems: race conditions between editors, and large message size. If > > you're trying to edit thingy x with parameter y, an URL to x is very > > helpful for being specific and atomic. > > > > > > On Wed, Jan 29, 2014 at 7:48 AM, Bryan Kearney > > wrote: > > > > > What about a > > > > > > PUT api/v2/operatingsystems/24/architectures > > > > > > ?? > > > > > > -- bk > > > > > > > > > On 01/29/2014 02:59 AM, Joseph Magen wrote: > > > > > >> There's a 3rd option and that is to PUT the JSON response from GET > > >> > > >> GET api/v2/operatingsystems/24 > > >> > > >> Part of the response includes architectures as a child-node > > >> > > >> { > > >> "id": 24, > > >> "name": "CentOs", > > >> "architectures": [ > > >> { > > >> "name": "x86_64", > > >> "id": 1 > > >> } > > >> ] > > >> } > > >> > > >> PUT api/v2/operatingsystems/24 > > >> > > >> And ad another OS in the JSON data > > >> > > >> { > > >> "id": 24, > > >> "name": "CentOs", > > >> "architectures": [ > > >> { > > >> "name": "x86_64", > > >> "id": 1 > > >> }, > > >> { > > >> "name": "i386", > > >> "id": 2 > > >> } > > >> ] > > >> } > > >> > > >> Actually, most of the JSON data above is unnecessary. I can just pass > > >> in > > >> the relationship node with a collection of ids > > >> > > >> PUT api/v2/operatingsystems/24 > > >> > > >> { > > >> "architectures": [ > > >> { > > >> "id": 1 > > >> }, > > >> { > > >> "id": 2 > > >> } > > >> ] > > >> } > > >> > > >> Note that you can NOT add or remove a SINGLE id as in your option #2. I > > >> agree with Walden not to implement this. > > >> > > >> Below, this example CREATES a record in has_and_belongs_to_many > > >> relationship table > > >> > > >> PUT api/v2/operatingsystems/24 > > >> > > >> { > > >> "architectures": [ > > >> { > > >> "id": 1 > > >> }, > > >> { > > >> "id": 2 > > >> } > > >> }, > > >> { > > >> "id": 3 > > >> } > > >> ] > > >> } > > >> > > >> This DELETES a record in has_and_belongs_to_many relationship table > > >> > > >> PUT api/v2/operatingsystems/24 > > >> > > >> { > > >> "architectures": [ > > >> { > > >> "id": 1 > > >> } > > >> ] > > >> } > > >> > > >> > > >> Note that this should work with every has_many or > > >> has_and_belongs_to_many > > >> relationship even if nested routes or child nodes may not appear for in > > >> RABL templates for all objects. > > >> > > >> > > >> In summary, Foreman supports > > >> #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > >> > > >> { > > >> "operatingsystem_ids": [24,25,26] > > >> } > > >> > > >> #3) Array on child not operatingsystems PUT /architecture/2 > > >> > > >> { > > >> "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > >> } > > >> > > >> David, I hope this helps. I agree that the documentation needs to be > > >> better. Can you take the initiative on updating the docs once we reach a > > >> final decision. > > >> > > >> Thanks, > > >> > > >> Joseph > > >> > > >> > > >> > > >> > > >> > > >> > > >> > > >> > > >> > > >> > > >> > > >> ----- Original Message ----- > > >> > > >>> From: "Walden Raines" > > >>> To: foreman-dev@googlegroups.com > > >>> Sent: Tuesday, January 28, 2014 10:20:15 PM > > >>> Subject: Re: [foreman-dev] Updating many-to-many relationships > > >>> > > >>> Even though I just followed an existing pattern and implemented a new > > >>> occurrence of #2, I prefer #1 as it is more RESTful. > > >>> > > >>> Cheers, > > >>> Walden > > >>> > > >>> ----- Original Message ----- > > >>> From: "David Davis" > > >>> To: "foreman-dev" > > >>> Sent: Tuesday, January 28, 2014 3:01:29 PM > > >>> Subject: [foreman-dev] Updating many-to-many relationships > > >>> > > >>> So there seems to be a divergence in how Foreman and Katello handle > > >>> many-to-many relationships. To give a couple examples of these, one > > >>> would be > > >>> architectures which have and belong to many OSes in Foreman. In > > >>> Katello, > > >>> content views has and belongs to many repositories There 2-3 options > > >>> for > > >>> updating these relationships: > > >>> > > >>> 1. Send in operating_system_ids on PUT /architecture/2 > > >>> 2. Have add_operating_systems and remove_operating_systems actions that > > >>> take > > >>> ids > > >>> 3. Both 2 and 3 > > >>> > > >>> Foreman looks like it mostly supports 1 while Katello has a combination > > >>> in > > >>> its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > >>> simpler > > >>> while 2 would maybe be easier to use for the user. 3 seems like a good > > >>> option but would be the most work. > > >>> > > >>> Thoughts? > > >>> > > >>> David > > >>> > > >>> -- > > >>> 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. > > >>> > > >>> > > >> > > > -- > > > 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. > > > > -- > 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. >

> To be specific and atomic, then you need to treat the many-to-many relation as its own resource. This is not the case with our example
>
> PUT api/v2/operatingsystems/24
>
> which update all the attributes AND associations for resource operating system #24
>
> The RESTful way to only add or delete an association (similar to what we did for host_classes and hostgroup_classes) is this below: (Note that BOTH the architecture id and operating system id's already exist)
>
> Create a new association
> POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': 1}
>
> object created
> {
> 'id': 555
> 'operatingsystem_id': 24
> 'architecture_id': 1
> }
>
> Delete an association
> DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555
>
> This is similar to what Bryan may thought of when he wrote
>
>> What about a
>> PUT api/v2/operatingsystems/24/architectures
>
> But the issue here is that PUT requires an ID of a resource to update.

yeah… I should have put POST.

>
> The 'problem' with the atomic restful way is that most 'simple' API's don't expose the database internals such as id #555 on a join table which is meaningless to the user.

I would make it architectures. That way the join parrt is hidden a bit.

– bk

··· On 01/30/2014 02:42 AM, Joseph Magen wrote:

One point of clarification referring to the thread that I started on Dec 24 with subject: Subject: API v2 adding/removing associations: to wrap parameters or not?

PUT /architecture/2

  1. This works - _ids AND WRAPPED
    {
    "architecture": {
    "operatingsystem_ids": [24,25,26]
    }
    }

  2. This works - child node and NOT WRAPPED (like GET)
    {
    "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}]
    }

  3. This does NOT work - child node and WRAPPED
    {
    "architecture": {
    "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}]
    }
    }

  4. This does NOT work - _ids and NOT WRAPPED
    {
    "operatingsystem_ids": [24,25,26]
    }

4 is the example that I previously gave, but it current doesn't work. If we want #3 and #4 to work, then I need to modify

··· ----- Original Message ----- > From: "Walden Raines" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 4:32:23 PM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > I like option #3 even better, thanks Joseph. > > We may have reached a decision unless there are any dissenting opinions that > remain unvoiced. > > Cheers, > Walden > > > ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 8:22:11 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > Hi David, > > Rails comes out-of-the-box with support for column_names_ids = [1,2,3,4] > > Option #3 I created a before_filter in api/v2/base_controller.rb > > https://github.com/isratrade/foreman/blob/inherit_loc/app/controllers/api/v2/base_controller.rb#L11 > > Basically, I manipulated the input to convert from an array of JSON objects > to get attribute :column_names_ids = [1,2,3,4] which is what Rails likes in > the standard `update_attributes` method > Note, column_names_names = ["name1", "name2"] also works. > > Joseph > > > > ----- Original Message ----- > > From: "David Davis" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 3:13:57 PM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > Joseph, > > > > I'll update the docs when we reach a decision. Question though: how did you > > all add support for the third option you outlined? Does it comes with > > Rails? > > > > David > > > > ----- Original Message ----- > > > From: "Joseph Magen" > > > To: foreman-dev@googlegroups.com > > > Sent: Wednesday, January 29, 2014 2:59:08 AM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > There's a 3rd option and that is to PUT the JSON response from GET > > > > > > GET api/v2/operatingsystems/24 > > > > > > Part of the response includes architectures as a child-node > > > > > > { > > > "id": 24, > > > "name": "CentOs", > > > "architectures": [ > > > { > > > "name": "x86_64", > > > "id": 1 > > > } > > > ] > > > } > > > > > > PUT api/v2/operatingsystems/24 > > > > > > And ad another OS in the JSON data > > > > > > { > > > "id": 24, > > > "name": "CentOs", > > > "architectures": [ > > > { > > > "name": "x86_64", > > > "id": 1 > > > }, > > > { > > > "name": "i386", > > > "id": 2 > > > } > > > ] > > > } > > > > > > Actually, most of the JSON data above is unnecessary. I can just pass in > > > the > > > relationship node with a collection of ids > > > > > > PUT api/v2/operatingsystems/24 > > > > > > { > > > "architectures": [ > > > { > > > "id": 1 > > > }, > > > { > > > "id": 2 > > > } > > > ] > > > } > > > > > > Note that you can NOT add or remove a SINGLE id as in your option #2. I > > > agree with Walden not to implement this. > > > > > > Below, this example CREATES a record in has_and_belongs_to_many > > > relationship > > > table > > > > > > PUT api/v2/operatingsystems/24 > > > > > > { > > > "architectures": [ > > > { > > > "id": 1 > > > }, > > > { > > > "id": 2 > > > } > > > }, > > > { > > > "id": 3 > > > } > > > ] > > > } > > > > > > This DELETES a record in has_and_belongs_to_many relationship table > > > > > > PUT api/v2/operatingsystems/24 > > > > > > { > > > "architectures": [ > > > { > > > "id": 1 > > > } > > > ] > > > } > > > > > > > > > Note that this should work with every has_many or has_and_belongs_to_many > > > relationship even if nested routes or child nodes may not appear for in > > > RABL > > > templates for all objects. > > > > > > > > > In summary, Foreman supports > > > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > > > > { > > > "operatingsystem_ids": [24,25,26] > > > } > > > > > > #3) Array on child not operatingsystems PUT /architecture/2 > > > > > > { > > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > > } > > > > > > David, I hope this helps. I agree that the documentation needs to be > > > better. > > > Can you take the initiative on updating the docs once we reach a final > > > decision. > > > > > > Thanks, > > > > > > Joseph > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ----- Original Message ----- > > > > From: "Walden Raines" > > > > To: foreman-dev@googlegroups.com > > > > Sent: Tuesday, January 28, 2014 10:20:15 PM > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > Even though I just followed an existing pattern and implemented a new > > > > occurrence of #2, I prefer #1 as it is more RESTful. > > > > > > > > Cheers, > > > > Walden > > > > > > > > ----- Original Message ----- > > > > From: "David Davis" > > > > To: "foreman-dev" > > > > Sent: Tuesday, January 28, 2014 3:01:29 PM > > > > Subject: [foreman-dev] Updating many-to-many relationships > > > > > > > > So there seems to be a divergence in how Foreman and Katello handle > > > > many-to-many relationships. To give a couple examples of these, one > > > > would > > > > be > > > > architectures which have and belong to many OSes in Foreman. In > > > > Katello, > > > > content views has and belongs to many repositories There 2-3 options > > > > for > > > > updating these relationships: > > > > > > > > 1. Send in operating_system_ids on PUT /architecture/2 > > > > 2. Have add_operating_systems and remove_operating_systems actions that > > > > take > > > > ids > > > > 3. Both 2 and 3 > > > > > > > > Foreman looks like it mostly supports 1 while Katello has a combination > > > > in > > > > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > > > simpler > > > > while 2 would maybe be easier to use for the user. 3 seems like a good > > > > option but would be the most work. > > > > > > > > Thoughts? > > > > > > > > David > > > > > > > > -- > > > > 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. > > > > > > > > > > -- > > > 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. > > > > -- > 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. >

I like option #3 but I have concerns about race conditions between calls since the GET then PUT is not atomic.

  1. user A GET organization
  2. user B GET organization
  3. user A PUT organization, removing an architecture
  4. user B PUT organization, adding an architecture

In the above, step 3 is effectively lost since step 4 included the architecture that step 3 meant to delete.

To prevent this, some sort of versioning field should be required in the PUTs (@daviddavis suggested that the updated-at could be used). This would result in step 4 failing with an error since step 3 would have changed the version of the object.

Without this, I believe that we will need to have methods to add and remove individual relations.

··· ----- Original Message ----- > From: "Walden Raines" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 9:32:23 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > I like option #3 even better, thanks Joseph. > > We may have reached a decision unless there are any dissenting opinions that > remain unvoiced. > > Cheers, > Walden > > > ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 8:22:11 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > Hi David, > > Rails comes out-of-the-box with support for column_names_ids = [1,2,3,4] > > Option #3 I created a before_filter in api/v2/base_controller.rb > > https://github.com/isratrade/foreman/blob/inherit_loc/app/controllers/api/v2/base_controller.rb#L11 > > Basically, I manipulated the input to convert from an array of JSON objects > to get attribute :column_names_ids = [1,2,3,4] which is what Rails likes in > the standard `update_attributes` method > Note, column_names_names = ["name1", "name2"] also works. > > Joseph > > > > ----- Original Message ----- > > From: "David Davis" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 3:13:57 PM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > Joseph, > > > > I'll update the docs when we reach a decision. Question though: how did you > > all add support for the third option you outlined? Does it comes with > > Rails? > > > > David > > > > ----- Original Message ----- > > > From: "Joseph Magen" > > > To: foreman-dev@googlegroups.com > > > Sent: Wednesday, January 29, 2014 2:59:08 AM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > There's a 3rd option and that is to PUT the JSON response from GET > > > > > > GET api/v2/operatingsystems/24 > > > > > > Part of the response includes architectures as a child-node > > > > > > { > > > "id": 24, > > > "name": "CentOs", > > > "architectures": [ > > > { > > > "name": "x86_64", > > > "id": 1 > > > } > > > ] > > > } > > > > > > PUT api/v2/operatingsystems/24 > > > > > > And ad another OS in the JSON data > > > > > > { > > > "id": 24, > > > "name": "CentOs", > > > "architectures": [ > > > { > > > "name": "x86_64", > > > "id": 1 > > > }, > > > { > > > "name": "i386", > > > "id": 2 > > > } > > > ] > > > } > > > > > > Actually, most of the JSON data above is unnecessary. I can just pass in > > > the > > > relationship node with a collection of ids > > > > > > PUT api/v2/operatingsystems/24 > > > > > > { > > > "architectures": [ > > > { > > > "id": 1 > > > }, > > > { > > > "id": 2 > > > } > > > ] > > > } > > > > > > Note that you can NOT add or remove a SINGLE id as in your option #2. I > > > agree with Walden not to implement this. > > > > > > Below, this example CREATES a record in has_and_belongs_to_many > > > relationship > > > table > > > > > > PUT api/v2/operatingsystems/24 > > > > > > { > > > "architectures": [ > > > { > > > "id": 1 > > > }, > > > { > > > "id": 2 > > > } > > > }, > > > { > > > "id": 3 > > > } > > > ] > > > } > > > > > > This DELETES a record in has_and_belongs_to_many relationship table > > > > > > PUT api/v2/operatingsystems/24 > > > > > > { > > > "architectures": [ > > > { > > > "id": 1 > > > } > > > ] > > > } > > > > > > > > > Note that this should work with every has_many or has_and_belongs_to_many > > > relationship even if nested routes or child nodes may not appear for in > > > RABL > > > templates for all objects. > > > > > > > > > In summary, Foreman supports > > > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > > > > { > > > "operatingsystem_ids": [24,25,26] > > > } > > > > > > #3) Array on child not operatingsystems PUT /architecture/2 > > > > > > { > > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > > } > > > > > > David, I hope this helps. I agree that the documentation needs to be > > > better. > > > Can you take the initiative on updating the docs once we reach a final > > > decision. > > > > > > Thanks, > > > > > > Joseph > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ----- Original Message ----- > > > > From: "Walden Raines" > > > > To: foreman-dev@googlegroups.com > > > > Sent: Tuesday, January 28, 2014 10:20:15 PM > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > Even though I just followed an existing pattern and implemented a new > > > > occurrence of #2, I prefer #1 as it is more RESTful. > > > > > > > > Cheers, > > > > Walden > > > > > > > > ----- Original Message ----- > > > > From: "David Davis" > > > > To: "foreman-dev" > > > > Sent: Tuesday, January 28, 2014 3:01:29 PM > > > > Subject: [foreman-dev] Updating many-to-many relationships > > > > > > > > So there seems to be a divergence in how Foreman and Katello handle > > > > many-to-many relationships. To give a couple examples of these, one > > > > would > > > > be > > > > architectures which have and belong to many OSes in Foreman. In > > > > Katello, > > > > content views has and belongs to many repositories There 2-3 options > > > > for > > > > updating these relationships: > > > > > > > > 1. Send in operating_system_ids on PUT /architecture/2 > > > > 2. Have add_operating_systems and remove_operating_systems actions that > > > > take > > > > ids > > > > 3. Both 2 and 3 > > > > > > > > Foreman looks like it mostly supports 1 while Katello has a combination > > > > in > > > > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > > > simpler > > > > while 2 would maybe be easier to use for the user. 3 seems like a good > > > > option but would be the most work. > > > > > > > > Thoughts? > > > > > > > > David > > > > > > > > -- > > > > 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. > > > > > > > > > > -- > > > 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. > > > > -- > 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. >

David,

You usually don't have a function as a data attribute, even though Rails generate the *_ids magic methods. It's possible what you suggest although not RESTful. In fact, to be RESTful, we should not create any NEW objects with PUT.

Joseph

··· ----- Original Message ----- > From: "David Davis" > To: foreman-dev@googlegroups.com > Sent: Thursday, January 30, 2014 2:21:43 PM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > What about something like this? > > PUT api/v2/operatingsystems/24 -d {'add_architecture_ids': 1} > > Seems like it would be easy to implement, atomic, and RESTful? > > David > > ----- Original Message ----- > > From: "Joseph Magen" > > To: foreman-dev@googlegroups.com > > Sent: Thursday, January 30, 2014 2:42:10 AM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > To be specific and atomic, then you need to treat the many-to-many relation > > as its own resource. This is not the case with our example > > > > PUT api/v2/operatingsystems/24 > > > > which update all the attributes AND associations for resource operating > > system #24 > > > > The RESTful way to only add or delete an association (similar to what we > > did > > for host_classes and hostgroup_classes) is this below: (Note that BOTH the > > architecture id and operating system id's already exist) > > > > Create a new association > > POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': 1} > > > > object created > > { > > 'id': 555 > > 'operatingsystem_id': 24 > > 'architecture_id': 1 > > } > > > > Delete an association > > DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555 > > > > This is similar to what Bryan may thought of when he wrote > > > > > What about a > > > PUT api/v2/operatingsystems/24/architectures > > > > But the issue here is that PUT requires an ID of a resource to update. > > > > The 'problem' with the atomic restful way is that most 'simple' API's don't > > expose the database internals such as id #555 on a join table which is > > meaningless to the user. > > > > Regards, > > > > Joseph > > > > > > > > > > ----- Original Message ----- > > > From: "Aaron Stone" > > > To: foreman-dev@googlegroups.com > > > Sent: Wednesday, January 29, 2014 6:12:10 PM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > Option #3 is great when you want to rewrite everything, and terrible in > > > all > > > other cases. Please allow the minimum edit. GET-modify-PUT has two big > > > problems: race conditions between editors, and large message size. If > > > you're trying to edit thingy x with parameter y, an URL to x is very > > > helpful for being specific and atomic. > > > > > > > > > On Wed, Jan 29, 2014 at 7:48 AM, Bryan Kearney > > > wrote: > > > > > > > What about a > > > > > > > > PUT api/v2/operatingsystems/24/architectures > > > > > > > > ?? > > > > > > > > -- bk > > > > > > > > > > > > On 01/29/2014 02:59 AM, Joseph Magen wrote: > > > > > > > >> There's a 3rd option and that is to PUT the JSON response from GET > > > >> > > > >> GET api/v2/operatingsystems/24 > > > >> > > > >> Part of the response includes architectures as a child-node > > > >> > > > >> { > > > >> "id": 24, > > > >> "name": "CentOs", > > > >> "architectures": [ > > > >> { > > > >> "name": "x86_64", > > > >> "id": 1 > > > >> } > > > >> ] > > > >> } > > > >> > > > >> PUT api/v2/operatingsystems/24 > > > >> > > > >> And ad another OS in the JSON data > > > >> > > > >> { > > > >> "id": 24, > > > >> "name": "CentOs", > > > >> "architectures": [ > > > >> { > > > >> "name": "x86_64", > > > >> "id": 1 > > > >> }, > > > >> { > > > >> "name": "i386", > > > >> "id": 2 > > > >> } > > > >> ] > > > >> } > > > >> > > > >> Actually, most of the JSON data above is unnecessary. I can just pass > > > >> in > > > >> the relationship node with a collection of ids > > > >> > > > >> PUT api/v2/operatingsystems/24 > > > >> > > > >> { > > > >> "architectures": [ > > > >> { > > > >> "id": 1 > > > >> }, > > > >> { > > > >> "id": 2 > > > >> } > > > >> ] > > > >> } > > > >> > > > >> Note that you can NOT add or remove a SINGLE id as in your option #2. > > > >> I > > > >> agree with Walden not to implement this. > > > >> > > > >> Below, this example CREATES a record in has_and_belongs_to_many > > > >> relationship table > > > >> > > > >> PUT api/v2/operatingsystems/24 > > > >> > > > >> { > > > >> "architectures": [ > > > >> { > > > >> "id": 1 > > > >> }, > > > >> { > > > >> "id": 2 > > > >> } > > > >> }, > > > >> { > > > >> "id": 3 > > > >> } > > > >> ] > > > >> } > > > >> > > > >> This DELETES a record in has_and_belongs_to_many relationship table > > > >> > > > >> PUT api/v2/operatingsystems/24 > > > >> > > > >> { > > > >> "architectures": [ > > > >> { > > > >> "id": 1 > > > >> } > > > >> ] > > > >> } > > > >> > > > >> > > > >> Note that this should work with every has_many or > > > >> has_and_belongs_to_many > > > >> relationship even if nested routes or child nodes may not appear for > > > >> in > > > >> RABL templates for all objects. > > > >> > > > >> > > > >> In summary, Foreman supports > > > >> #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > >> > > > >> { > > > >> "operatingsystem_ids": [24,25,26] > > > >> } > > > >> > > > >> #3) Array on child not operatingsystems PUT /architecture/2 > > > >> > > > >> { > > > >> "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > > >> } > > > >> > > > >> David, I hope this helps. I agree that the documentation needs to be > > > >> better. Can you take the initiative on updating the docs once we reach > > > >> a > > > >> final decision. > > > >> > > > >> Thanks, > > > >> > > > >> Joseph > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> > > > >> ----- Original Message ----- > > > >> > > > >>> From: "Walden Raines" > > > >>> To: foreman-dev@googlegroups.com > > > >>> Sent: Tuesday, January 28, 2014 10:20:15 PM > > > >>> Subject: Re: [foreman-dev] Updating many-to-many relationships > > > >>> > > > >>> Even though I just followed an existing pattern and implemented a new > > > >>> occurrence of #2, I prefer #1 as it is more RESTful. > > > >>> > > > >>> Cheers, > > > >>> Walden > > > >>> > > > >>> ----- Original Message ----- > > > >>> From: "David Davis" > > > >>> To: "foreman-dev" > > > >>> Sent: Tuesday, January 28, 2014 3:01:29 PM > > > >>> Subject: [foreman-dev] Updating many-to-many relationships > > > >>> > > > >>> So there seems to be a divergence in how Foreman and Katello handle > > > >>> many-to-many relationships. To give a couple examples of these, one > > > >>> would be > > > >>> architectures which have and belong to many OSes in Foreman. In > > > >>> Katello, > > > >>> content views has and belongs to many repositories There 2-3 options > > > >>> for > > > >>> updating these relationships: > > > >>> > > > >>> 1. Send in operating_system_ids on PUT /architecture/2 > > > >>> 2. Have add_operating_systems and remove_operating_systems actions > > > >>> that > > > >>> take > > > >>> ids > > > >>> 3. Both 2 and 3 > > > >>> > > > >>> Foreman looks like it mostly supports 1 while Katello has a > > > >>> combination > > > >>> in > > > >>> its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > > >>> simpler > > > >>> while 2 would maybe be easier to use for the user. 3 seems like a > > > >>> good > > > >>> option but would be the most work. > > > >>> > > > >>> Thoughts? > > > >>> > > > >>> David > > > >>> > > > >>> -- > > > >>> 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. > > > >>> > > > >>> > > > >> > > > > -- > > > > 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. > > > > > > > -- > > 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. >

> From: "Bryan Kearney" <bryan.kearney@gmail.com>
> To: foreman-dev@googlegroups.com
> Sent: Thursday, January 30, 2014 3:13:37 PM
> Subject: Re: [foreman-dev] Updating many-to-many relationships
>
> > To be specific and atomic, then you need to treat the many-to-many relation
> > as its own resource. This is not the case with our example
> >
> > PUT api/v2/operatingsystems/24
> >
> > which update all the attributes AND associations for resource operating
> > system #24
> >
> > The RESTful way to only add or delete an association (similar to what we
> > did for host_classes and hostgroup_classes) is this below: (Note that BOTH
> > the architecture id and operating system id's already exist)
> >
> > Create a new association
> > POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': 1}
> >
> > object created
> > {
> > 'id': 555
> > 'operatingsystem_id': 24
> > 'architecture_id': 1
> > }
> >
> > Delete an association
> > DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555
> >
> > This is similar to what Bryan may thought of when he wrote
> >
> >> What about a
> >> PUT api/v2/operatingsystems/24/architectures
> >
> > But the issue here is that PUT requires an ID of a resource to update.
>
>
> yeah… I should have put POST.
>
> >
> > The 'problem' with the atomic restful way is that most 'simple' API's don't
> > expose the database internals such as id #555 on a join table which is
> > meaningless to the user.
>
> I would make it architectures. That way the join parrt is hidden a bit.

POST api/v2/operatingsystems/24/architectures -d {'id': 1}

This would be confusing, since in RESTful style, a POST on a collection (architectures) creates a new architecture.

··· ----- Original Message ----- > On 01/30/2014 02:42 AM, Joseph Magen wrote:

– bk


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.

One thing about updating association ids is that they're more susceptible to collisions. For example, let's say an architecture has os_ids [1,2,3]. If user A PUTs os_ids [2,3] and then user B PUTs os_ids [1,2,3,4], then user B will be undoing user A's changes. I don't think this necessarily necessitates add/remove actions but I am wondering if we should worry about solving this now instead of when it could become a problem?

David

··· ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 10:14:35 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > One point of clarification referring to the thread that I started on Dec 24 > with subject: Subject: API v2 adding/removing associations: to wrap > parameters or not? > > PUT /architecture/2 > 1) This works - _ids AND WRAPPED > { > "architecture": { > "operatingsystem_ids": [24,25,26] > } > } > > 2) This works - child node and NOT WRAPPED (like GET) > { > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > } > > 3) This does NOT work - child node and WRAPPED > { > "architecture": { > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}]\ > } > } > > 4) This does NOT work - _ids and NOT WRAPPED > { > "operatingsystem_ids": [24,25,26] > } > > > # 4 is the example that I previously gave, but it current doesn't work. If we > want #3 and #4 to work, then I need to modify > https://github.com/theforeman/foreman/blob/develop/app/controllers/api/v2/base_controller.rb#L59-71 > > > > > ----- Original Message ----- > > From: "Walden Raines" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 4:32:23 PM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > I like option #3 even better, thanks Joseph. > > > > We may have reached a decision unless there are any dissenting opinions > > that > > remain unvoiced. > > > > Cheers, > > Walden > > > > > > ----- Original Message ----- > > From: "Joseph Magen" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 8:22:11 AM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > Hi David, > > > > Rails comes out-of-the-box with support for column_names_ids = [1,2,3,4] > > > > Option #3 I created a before_filter in api/v2/base_controller.rb > > > > https://github.com/isratrade/foreman/blob/inherit_loc/app/controllers/api/v2/base_controller.rb#L11 > > > > Basically, I manipulated the input to convert from an array of JSON objects > > to get attribute :column_names_ids = [1,2,3,4] which is what Rails likes in > > the standard `update_attributes` method > > Note, column_names_names = ["name1", "name2"] also works. > > > > Joseph > > > > > > > > ----- Original Message ----- > > > From: "David Davis" > > > To: foreman-dev@googlegroups.com > > > Sent: Wednesday, January 29, 2014 3:13:57 PM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > Joseph, > > > > > > I'll update the docs when we reach a decision. Question though: how did > > > you > > > all add support for the third option you outlined? Does it comes with > > > Rails? > > > > > > David > > > > > > ----- Original Message ----- > > > > From: "Joseph Magen" > > > > To: foreman-dev@googlegroups.com > > > > Sent: Wednesday, January 29, 2014 2:59:08 AM > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > There's a 3rd option and that is to PUT the JSON response from GET > > > > > > > > GET api/v2/operatingsystems/24 > > > > > > > > Part of the response includes architectures as a child-node > > > > > > > > { > > > > "id": 24, > > > > "name": "CentOs", > > > > "architectures": [ > > > > { > > > > "name": "x86_64", > > > > "id": 1 > > > > } > > > > ] > > > > } > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > And ad another OS in the JSON data > > > > > > > > { > > > > "id": 24, > > > > "name": "CentOs", > > > > "architectures": [ > > > > { > > > > "name": "x86_64", > > > > "id": 1 > > > > }, > > > > { > > > > "name": "i386", > > > > "id": 2 > > > > } > > > > ] > > > > } > > > > > > > > Actually, most of the JSON data above is unnecessary. I can just pass > > > > in > > > > the > > > > relationship node with a collection of ids > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > { > > > > "architectures": [ > > > > { > > > > "id": 1 > > > > }, > > > > { > > > > "id": 2 > > > > } > > > > ] > > > > } > > > > > > > > Note that you can NOT add or remove a SINGLE id as in your option #2. > > > > I > > > > agree with Walden not to implement this. > > > > > > > > Below, this example CREATES a record in has_and_belongs_to_many > > > > relationship > > > > table > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > { > > > > "architectures": [ > > > > { > > > > "id": 1 > > > > }, > > > > { > > > > "id": 2 > > > > } > > > > }, > > > > { > > > > "id": 3 > > > > } > > > > ] > > > > } > > > > > > > > This DELETES a record in has_and_belongs_to_many relationship table > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > { > > > > "architectures": [ > > > > { > > > > "id": 1 > > > > } > > > > ] > > > > } > > > > > > > > > > > > Note that this should work with every has_many or > > > > has_and_belongs_to_many > > > > relationship even if nested routes or child nodes may not appear for in > > > > RABL > > > > templates for all objects. > > > > > > > > > > > > In summary, Foreman supports > > > > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > > > > > > { > > > > "operatingsystem_ids": [24,25,26] > > > > } > > > > > > > > #3) Array on child not operatingsystems PUT /architecture/2 > > > > > > > > { > > > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > > > } > > > > > > > > David, I hope this helps. I agree that the documentation needs to be > > > > better. > > > > Can you take the initiative on updating the docs once we reach a final > > > > decision. > > > > > > > > Thanks, > > > > > > > > Joseph > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ----- Original Message ----- > > > > > From: "Walden Raines" > > > > > To: foreman-dev@googlegroups.com > > > > > Sent: Tuesday, January 28, 2014 10:20:15 PM > > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > > > Even though I just followed an existing pattern and implemented a new > > > > > occurrence of #2, I prefer #1 as it is more RESTful. > > > > > > > > > > Cheers, > > > > > Walden > > > > > > > > > > ----- Original Message ----- > > > > > From: "David Davis" > > > > > To: "foreman-dev" > > > > > Sent: Tuesday, January 28, 2014 3:01:29 PM > > > > > Subject: [foreman-dev] Updating many-to-many relationships > > > > > > > > > > So there seems to be a divergence in how Foreman and Katello handle > > > > > many-to-many relationships. To give a couple examples of these, one > > > > > would > > > > > be > > > > > architectures which have and belong to many OSes in Foreman. In > > > > > Katello, > > > > > content views has and belongs to many repositories There 2-3 options > > > > > for > > > > > updating these relationships: > > > > > > > > > > 1. Send in operating_system_ids on PUT /architecture/2 > > > > > 2. Have add_operating_systems and remove_operating_systems actions > > > > > that > > > > > take > > > > > ids > > > > > 3. Both 2 and 3 > > > > > > > > > > Foreman looks like it mostly supports 1 while Katello has a > > > > > combination > > > > > in > > > > > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 is > > > > > simpler > > > > > while 2 would maybe be easier to use for the user. 3 seems like a > > > > > good > > > > > option but would be the most work. > > > > > > > > > > Thoughts? > > > > > > > > > > David > > > > > > > > > > -- > > > > > 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. > > > > > > > > > > > > > -- > > > > 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. > > > > > > > -- > > 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. > > > > -- > 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 meant more RESTful than having separate PUT actions but point taken.

David

··· ----- Original Message ----- > From: "Joseph Magen" > To: foreman-dev@googlegroups.com > Sent: Thursday, January 30, 2014 7:48:20 AM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > David, > > You usually don't have a function as a data attribute, even though Rails > generate the *_ids magic methods. It's possible what you suggest although > not RESTful. In fact, to be RESTful, we should not create any NEW objects > with PUT. > > Joseph > > > ----- Original Message ----- > > From: "David Davis" > > To: foreman-dev@googlegroups.com > > Sent: Thursday, January 30, 2014 2:21:43 PM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > What about something like this? > > > > PUT api/v2/operatingsystems/24 -d {'add_architecture_ids': 1} > > > > Seems like it would be easy to implement, atomic, and RESTful? > > > > David > > > > ----- Original Message ----- > > > From: "Joseph Magen" > > > To: foreman-dev@googlegroups.com > > > Sent: Thursday, January 30, 2014 2:42:10 AM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > To be specific and atomic, then you need to treat the many-to-many > > > relation > > > as its own resource. This is not the case with our example > > > > > > PUT api/v2/operatingsystems/24 > > > > > > which update all the attributes AND associations for resource operating > > > system #24 > > > > > > The RESTful way to only add or delete an association (similar to what we > > > did > > > for host_classes and hostgroup_classes) is this below: (Note that BOTH > > > the > > > architecture id and operating system id's already exist) > > > > > > Create a new association > > > POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': > > > 1} > > > > > > object created > > > { > > > 'id': 555 > > > 'operatingsystem_id': 24 > > > 'architecture_id': 1 > > > } > > > > > > Delete an association > > > DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555 > > > > > > This is similar to what Bryan may thought of when he wrote > > > > > > > What about a > > > > PUT api/v2/operatingsystems/24/architectures > > > > > > But the issue here is that PUT requires an ID of a resource to update. > > > > > > The 'problem' with the atomic restful way is that most 'simple' API's > > > don't > > > expose the database internals such as id #555 on a join table which is > > > meaningless to the user. > > > > > > Regards, > > > > > > Joseph > > > > > > > > > > > > > > > ----- Original Message ----- > > > > From: "Aaron Stone" > > > > To: foreman-dev@googlegroups.com > > > > Sent: Wednesday, January 29, 2014 6:12:10 PM > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > Option #3 is great when you want to rewrite everything, and terrible in > > > > all > > > > other cases. Please allow the minimum edit. GET-modify-PUT has two big > > > > problems: race conditions between editors, and large message size. If > > > > you're trying to edit thingy x with parameter y, an URL to x is very > > > > helpful for being specific and atomic. > > > > > > > > > > > > On Wed, Jan 29, 2014 at 7:48 AM, Bryan Kearney > > > > wrote: > > > > > > > > > What about a > > > > > > > > > > PUT api/v2/operatingsystems/24/architectures > > > > > > > > > > ?? > > > > > > > > > > -- bk > > > > > > > > > > > > > > > On 01/29/2014 02:59 AM, Joseph Magen wrote: > > > > > > > > > >> There's a 3rd option and that is to PUT the JSON response from GET > > > > >> > > > > >> GET api/v2/operatingsystems/24 > > > > >> > > > > >> Part of the response includes architectures as a child-node > > > > >> > > > > >> { > > > > >> "id": 24, > > > > >> "name": "CentOs", > > > > >> "architectures": [ > > > > >> { > > > > >> "name": "x86_64", > > > > >> "id": 1 > > > > >> } > > > > >> ] > > > > >> } > > > > >> > > > > >> PUT api/v2/operatingsystems/24 > > > > >> > > > > >> And ad another OS in the JSON data > > > > >> > > > > >> { > > > > >> "id": 24, > > > > >> "name": "CentOs", > > > > >> "architectures": [ > > > > >> { > > > > >> "name": "x86_64", > > > > >> "id": 1 > > > > >> }, > > > > >> { > > > > >> "name": "i386", > > > > >> "id": 2 > > > > >> } > > > > >> ] > > > > >> } > > > > >> > > > > >> Actually, most of the JSON data above is unnecessary. I can just > > > > >> pass > > > > >> in > > > > >> the relationship node with a collection of ids > > > > >> > > > > >> PUT api/v2/operatingsystems/24 > > > > >> > > > > >> { > > > > >> "architectures": [ > > > > >> { > > > > >> "id": 1 > > > > >> }, > > > > >> { > > > > >> "id": 2 > > > > >> } > > > > >> ] > > > > >> } > > > > >> > > > > >> Note that you can NOT add or remove a SINGLE id as in your option > > > > >> #2. > > > > >> I > > > > >> agree with Walden not to implement this. > > > > >> > > > > >> Below, this example CREATES a record in has_and_belongs_to_many > > > > >> relationship table > > > > >> > > > > >> PUT api/v2/operatingsystems/24 > > > > >> > > > > >> { > > > > >> "architectures": [ > > > > >> { > > > > >> "id": 1 > > > > >> }, > > > > >> { > > > > >> "id": 2 > > > > >> } > > > > >> }, > > > > >> { > > > > >> "id": 3 > > > > >> } > > > > >> ] > > > > >> } > > > > >> > > > > >> This DELETES a record in has_and_belongs_to_many relationship table > > > > >> > > > > >> PUT api/v2/operatingsystems/24 > > > > >> > > > > >> { > > > > >> "architectures": [ > > > > >> { > > > > >> "id": 1 > > > > >> } > > > > >> ] > > > > >> } > > > > >> > > > > >> > > > > >> Note that this should work with every has_many or > > > > >> has_and_belongs_to_many > > > > >> relationship even if nested routes or child nodes may not appear for > > > > >> in > > > > >> RABL templates for all objects. > > > > >> > > > > >> > > > > >> In summary, Foreman supports > > > > >> #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > > >> > > > > >> { > > > > >> "operatingsystem_ids": [24,25,26] > > > > >> } > > > > >> > > > > >> #3) Array on child not operatingsystems PUT /architecture/2 > > > > >> > > > > >> { > > > > >> "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > > > >> } > > > > >> > > > > >> David, I hope this helps. I agree that the documentation needs to > > > > >> be > > > > >> better. Can you take the initiative on updating the docs once we > > > > >> reach > > > > >> a > > > > >> final decision. > > > > >> > > > > >> Thanks, > > > > >> > > > > >> Joseph > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> ----- Original Message ----- > > > > >> > > > > >>> From: "Walden Raines" > > > > >>> To: foreman-dev@googlegroups.com > > > > >>> Sent: Tuesday, January 28, 2014 10:20:15 PM > > > > >>> Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > >>> > > > > >>> Even though I just followed an existing pattern and implemented a > > > > >>> new > > > > >>> occurrence of #2, I prefer #1 as it is more RESTful. > > > > >>> > > > > >>> Cheers, > > > > >>> Walden > > > > >>> > > > > >>> ----- Original Message ----- > > > > >>> From: "David Davis" > > > > >>> To: "foreman-dev" > > > > >>> Sent: Tuesday, January 28, 2014 3:01:29 PM > > > > >>> Subject: [foreman-dev] Updating many-to-many relationships > > > > >>> > > > > >>> So there seems to be a divergence in how Foreman and Katello handle > > > > >>> many-to-many relationships. To give a couple examples of these, one > > > > >>> would be > > > > >>> architectures which have and belong to many OSes in Foreman. In > > > > >>> Katello, > > > > >>> content views has and belongs to many repositories There 2-3 > > > > >>> options > > > > >>> for > > > > >>> updating these relationships: > > > > >>> > > > > >>> 1. Send in operating_system_ids on PUT /architecture/2 > > > > >>> 2. Have add_operating_systems and remove_operating_systems actions > > > > >>> that > > > > >>> take > > > > >>> ids > > > > >>> 3. Both 2 and 3 > > > > >>> > > > > >>> Foreman looks like it mostly supports 1 while Katello has a > > > > >>> combination > > > > >>> in > > > > >>> its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 > > > > >>> is > > > > >>> simpler > > > > >>> while 2 would maybe be easier to use for the user. 3 seems like a > > > > >>> good > > > > >>> option but would be the most work. > > > > >>> > > > > >>> Thoughts? > > > > >>> > > > > >>> David > > > > >>> > > > > >>> -- > > > > >>> 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. > > > > >>> > > > > >>> > > > > >> > > > > > -- > > > > > 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. > > > > > > > > > > -- > > > 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. > > > > -- > 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 are correct… but this for me is when the REST WILL SOLVE ALL ISSUES
argument starts to fail. Haveing a resource which is

api/v2/operatingsystems_architectures_relationship

is just nasty in IMHO. I would prefer a POST to
api/v2/operatingsystems/24/architectures which either does a CREATE or
FIND based on the presence of hte ID attribute. But, that is just me :slight_smile:

<rant>BTw… I am still waiting for the REST client which actually
parses the url fragments which REST produces to "follow" the api" </rant>

– bk

··· On 01/30/2014 08:19 AM, Joseph Magen wrote: > ----- Original Message ----- >> From: "Bryan Kearney" >> To: foreman-dev@googlegroups.com >> Sent: Thursday, January 30, 2014 3:13:37 PM >> Subject: Re: [foreman-dev] Updating many-to-many relationships >> >> On 01/30/2014 02:42 AM, Joseph Magen wrote: >>> To be specific and atomic, then you need to treat the many-to-many relation >>> as its own resource. This is not the case with our example >>> >>> PUT api/v2/operatingsystems/24 >>> >>> which update all the attributes AND associations for resource operating >>> system #24 >>> >>> The RESTful way to only add or delete an association (similar to what we >>> did for host_classes and hostgroup_classes) is this below: (Note that BOTH >>> the architecture id and operating system id's already exist) >>> >>> Create a new association >>> POST api/v2/operatingsystems/24/architectures_operatingsystems -d {'id': 1} >>> >>> object created >>> { >>> 'id': 555 >>> 'operatingsystem_id': 24 >>> 'architecture_id': 1 >>> } >>> >>> Delete an association >>> DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555 >>> >>> This is similar to what Bryan may thought of when he wrote >>> >>>> What about a >>>> PUT api/v2/operatingsystems/24/architectures >>> >>> But the issue here is that PUT requires an ID of a resource to update. >> >> >> yeah... I should have put POST. >> >>> >>> The 'problem' with the atomic restful way is that most 'simple' API's don't >>> expose the database internals such as id #555 on a join table which is >>> meaningless to the user. >> >> I would make it architectures. That way the join parrt is hidden a bit. > > > POST api/v2/operatingsystems/24/architectures -d {'id': 1} > > This would be confusing, since in RESTful style, a POST on a collection (architectures) creates a new architecture.

Yes, this would be the case. If B puts [1,2,3,4], then it puts back the OS that A deleted.

We do have an example were we POST and DELETE on the join table resource for host classes and hostgroup classes.

We renamed the paths to puppetclass_ids

However, I'm not convinced this should be done for every has has_and_belongs_to_many relationship. And btw, it can't be done on regular has_many relationships.

Joseph

··· ----- Original Message ----- > From: "David Davis" > To: foreman-dev@googlegroups.com > Sent: Wednesday, January 29, 2014 5:21:54 PM > Subject: Re: [foreman-dev] Updating many-to-many relationships > > One thing about updating association ids is that they're more susceptible to > collisions. For example, let's say an architecture has os_ids [1,2,3]. If > user A PUTs os_ids [2,3] and then user B PUTs os_ids [1,2,3,4], then user B > will be undoing user A's changes. I don't think this necessarily > necessitates add/remove actions but I am wondering if we should worry about > solving this now instead of when it could become a problem? > > David > > ----- Original Message ----- > > From: "Joseph Magen" > > To: foreman-dev@googlegroups.com > > Sent: Wednesday, January 29, 2014 10:14:35 AM > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > One point of clarification referring to the thread that I started on Dec 24 > > with subject: Subject: API v2 adding/removing associations: to wrap > > parameters or not? > > > > PUT /architecture/2 > > 1) This works - _ids AND WRAPPED > > { > > "architecture": { > > "operatingsystem_ids": [24,25,26] > > } > > } > > > > 2) This works - child node and NOT WRAPPED (like GET) > > { > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > } > > > > 3) This does NOT work - child node and WRAPPED > > { > > "architecture": { > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}]\ > > } > > } > > > > 4) This does NOT work - _ids and NOT WRAPPED > > { > > "operatingsystem_ids": [24,25,26] > > } > > > > > > # 4 is the example that I previously gave, but it current doesn't work. If > > we > > want #3 and #4 to work, then I need to modify > > https://github.com/theforeman/foreman/blob/develop/app/controllers/api/v2/base_controller.rb#L59-71 > > > > > > > > > > ----- Original Message ----- > > > From: "Walden Raines" > > > To: foreman-dev@googlegroups.com > > > Sent: Wednesday, January 29, 2014 4:32:23 PM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > I like option #3 even better, thanks Joseph. > > > > > > We may have reached a decision unless there are any dissenting opinions > > > that > > > remain unvoiced. > > > > > > Cheers, > > > Walden > > > > > > > > > ----- Original Message ----- > > > From: "Joseph Magen" > > > To: foreman-dev@googlegroups.com > > > Sent: Wednesday, January 29, 2014 8:22:11 AM > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > Hi David, > > > > > > Rails comes out-of-the-box with support for column_names_ids = [1,2,3,4] > > > > > > Option #3 I created a before_filter in api/v2/base_controller.rb > > > > > > https://github.com/isratrade/foreman/blob/inherit_loc/app/controllers/api/v2/base_controller.rb#L11 > > > > > > Basically, I manipulated the input to convert from an array of JSON > > > objects > > > to get attribute :column_names_ids = [1,2,3,4] which is what Rails likes > > > in > > > the standard `update_attributes` method > > > Note, column_names_names = ["name1", "name2"] also works. > > > > > > Joseph > > > > > > > > > > > > ----- Original Message ----- > > > > From: "David Davis" > > > > To: foreman-dev@googlegroups.com > > > > Sent: Wednesday, January 29, 2014 3:13:57 PM > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > Joseph, > > > > > > > > I'll update the docs when we reach a decision. Question though: how did > > > > you > > > > all add support for the third option you outlined? Does it comes with > > > > Rails? > > > > > > > > David > > > > > > > > ----- Original Message ----- > > > > > From: "Joseph Magen" > > > > > To: foreman-dev@googlegroups.com > > > > > Sent: Wednesday, January 29, 2014 2:59:08 AM > > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > > > There's a 3rd option and that is to PUT the JSON response from GET > > > > > > > > > > GET api/v2/operatingsystems/24 > > > > > > > > > > Part of the response includes architectures as a child-node > > > > > > > > > > { > > > > > "id": 24, > > > > > "name": "CentOs", > > > > > "architectures": [ > > > > > { > > > > > "name": "x86_64", > > > > > "id": 1 > > > > > } > > > > > ] > > > > > } > > > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > > > And ad another OS in the JSON data > > > > > > > > > > { > > > > > "id": 24, > > > > > "name": "CentOs", > > > > > "architectures": [ > > > > > { > > > > > "name": "x86_64", > > > > > "id": 1 > > > > > }, > > > > > { > > > > > "name": "i386", > > > > > "id": 2 > > > > > } > > > > > ] > > > > > } > > > > > > > > > > Actually, most of the JSON data above is unnecessary. I can just > > > > > pass > > > > > in > > > > > the > > > > > relationship node with a collection of ids > > > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > > > { > > > > > "architectures": [ > > > > > { > > > > > "id": 1 > > > > > }, > > > > > { > > > > > "id": 2 > > > > > } > > > > > ] > > > > > } > > > > > > > > > > Note that you can NOT add or remove a SINGLE id as in your option #2. > > > > > I > > > > > agree with Walden not to implement this. > > > > > > > > > > Below, this example CREATES a record in has_and_belongs_to_many > > > > > relationship > > > > > table > > > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > > > { > > > > > "architectures": [ > > > > > { > > > > > "id": 1 > > > > > }, > > > > > { > > > > > "id": 2 > > > > > } > > > > > }, > > > > > { > > > > > "id": 3 > > > > > } > > > > > ] > > > > > } > > > > > > > > > > This DELETES a record in has_and_belongs_to_many relationship table > > > > > > > > > > PUT api/v2/operatingsystems/24 > > > > > > > > > > { > > > > > "architectures": [ > > > > > { > > > > > "id": 1 > > > > > } > > > > > ] > > > > > } > > > > > > > > > > > > > > > Note that this should work with every has_many or > > > > > has_and_belongs_to_many > > > > > relationship even if nested routes or child nodes may not appear for > > > > > in > > > > > RABL > > > > > templates for all objects. > > > > > > > > > > > > > > > In summary, Foreman supports > > > > > #1) Array on attribute operatingsystem_ids on PUT /architecture/2 > > > > > > > > > > { > > > > > "operatingsystem_ids": [24,25,26] > > > > > } > > > > > > > > > > #3) Array on child not operatingsystems PUT /architecture/2 > > > > > > > > > > { > > > > > "operatingsystems": [{"id": 24},{"id": 25},{"id": 26}] > > > > > } > > > > > > > > > > David, I hope this helps. I agree that the documentation needs to be > > > > > better. > > > > > Can you take the initiative on updating the docs once we reach a > > > > > final > > > > > decision. > > > > > > > > > > Thanks, > > > > > > > > > > Joseph > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ----- Original Message ----- > > > > > > From: "Walden Raines" > > > > > > To: foreman-dev@googlegroups.com > > > > > > Sent: Tuesday, January 28, 2014 10:20:15 PM > > > > > > Subject: Re: [foreman-dev] Updating many-to-many relationships > > > > > > > > > > > > Even though I just followed an existing pattern and implemented a > > > > > > new > > > > > > occurrence of #2, I prefer #1 as it is more RESTful. > > > > > > > > > > > > Cheers, > > > > > > Walden > > > > > > > > > > > > ----- Original Message ----- > > > > > > From: "David Davis" > > > > > > To: "foreman-dev" > > > > > > Sent: Tuesday, January 28, 2014 3:01:29 PM > > > > > > Subject: [foreman-dev] Updating many-to-many relationships > > > > > > > > > > > > So there seems to be a divergence in how Foreman and Katello handle > > > > > > many-to-many relationships. To give a couple examples of these, one > > > > > > would > > > > > > be > > > > > > architectures which have and belong to many OSes in Foreman. In > > > > > > Katello, > > > > > > content views has and belongs to many repositories There 2-3 > > > > > > options > > > > > > for > > > > > > updating these relationships: > > > > > > > > > > > > 1. Send in operating_system_ids on PUT /architecture/2 > > > > > > 2. Have add_operating_systems and remove_operating_systems actions > > > > > > that > > > > > > take > > > > > > ids > > > > > > 3. Both 2 and 3 > > > > > > > > > > > > Foreman looks like it mostly supports 1 while Katello has a > > > > > > combination > > > > > > in > > > > > > its v2 api of 1 and 2 (but not 3). I can see advantages to all: 1 > > > > > > is > > > > > > simpler > > > > > > while 2 would maybe be easier to use for the user. 3 seems like a > > > > > > good > > > > > > option but would be the most work. > > > > > > > > > > > > Thoughts? > > > > > > > > > > > > David > > > > > > > > > > > > -- > > > > > > 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. > > > > > > > > > > > > > > > > -- > > > > > 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. > > > > > > > > > > -- > > > 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. > > > > > > > -- > > 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. >

>>> From: "Bryan Kearney" <bryan.kearney@gmail.com>
>>> To: foreman-dev@googlegroups.com
>>> Sent: Thursday, January 30, 2014 3:13:37 PM
>>> Subject: Re: [foreman-dev] Updating many-to-many relationships
>>>
>>>> To be specific and atomic, then you need to treat the many-to-many
>>>> relation
>>>> as its own resource. This is not the case with our example
>>>>
>>>> PUT api/v2/operatingsystems/24
>>>>
>>>> which update all the attributes AND associations for resource operating
>>>> system #24
>>>>
>>>> The RESTful way to only add or delete an association (similar to
>>>> what we
>>>> did for host_classes and hostgroup_classes) is this below: (Note
>>>> that BOTH
>>>> the architecture id and operating system id's already exist)
>>>>
>>>> Create a new association
>>>> POST api/v2/operatingsystems/24/architectures_operatingsystems -d
>>>> {'id': 1}
>>>>
>>>> object created
>>>> {
>>>> 'id': 555
>>>> 'operatingsystem_id': 24
>>>> 'architecture_id': 1
>>>> }
>>>>
>>>> Delete an association
>>>> DELETE api/v2/operatingsystems/24/architectures_operatingsystems/555
>>>>
>>>> This is similar to what Bryan may thought of when he wrote
>>>>
>>>>> What about a
>>>>> PUT api/v2/operatingsystems/24/architectures
>>>>
>>>> But the issue here is that PUT requires an ID of a resource to update.
>>>
>>>
>>> yeah… I should have put POST.
>>>
>>>>
>>>> The 'problem' with the atomic restful way is that most 'simple'
>>>> API's don't
>>>> expose the database internals such as id #555 on a join table which is
>>>> meaningless to the user.
>>>
>>> I would make it architectures. That way the join parrt is hidden a bit.
>>
>>
>> POST api/v2/operatingsystems/24/architectures -d {'id': 1}
>>
>> This would be confusing, since in RESTful style, a POST on a
>> collection (architectures) creates a new architecture.
>
>
> You are correct… but this for me is when the REST WILL SOLVE ALL ISSUES
> argument starts to fail. Haveing a resource which is
>
> api/v2/operatingsystems_architectures_relationship
>
> is just nasty in IMHO. I would prefer a POST to
> api/v2/operatingsystems/24/architectures which either does a CREATE or
> FIND based on the presence of hte ID attribute. But, that is just me :slight_smile:

+1

Even though it might be confusing I tend to agree with what Bryan
described. Sending all remaining associated ids every time I want to add
another one is not very pleasant.

··· On 01/30/2014 02:31 PM, Bryan Kearney wrote: > On 01/30/2014 08:19 AM, Joseph Magen wrote: >> ----- Original Message ----- >>> On 01/30/2014 02:42 AM, Joseph Magen wrote:

BTw… I am still waiting for the REST client which actually
parses the url fragments which REST produces to “follow” the api"

– bk