I am trying to 'debug' the update method of my TasksController's such that it can automatically update the related 'tags' that are sent over http using JSON API. I am not sure what is the correct way for doing this.
Here are my models:
class Task < ApplicationRecord
has_many :task_tags
has_many :tags, through: :task_tags
validates :title, presence: true
validates :title, uniqueness: true
end
class Tag < ApplicationRecord
has_many :task_tags
has_many :tasks, through: :task_tags
validates :title, presence: true
validates :title, uniqueness: true
end
class TaskTag < ApplicationRecord
belongs_to :task
belongs_to :tag
validates :task_id, presence: true
validates :tag_id, presence: true
end
So the Task model and Tag model are related to each other in a many-to-many relationship, which is resolved via TaskTag model. Nothing profound.
The data is sent to the model via JSON API using Postman, which I cannot change. Here is the data being sent in the Postman's PATCH action in the 'body' is as shown below:
{"data":
{ "type":"tasks",
"id":"2",
"attributes":{
"title":"Updated Task Title",
"tags": ["Urgent", "Home"]
}
}
}
My ActiveModel Serializer is working correctly for the JSON API and therefore, I believe that I am receiving the correct data in my TasksController's 'update' action shown below:
class Api::V1::TasksController < ApplicationController
...
def update
task = Task.find(params[:id])
byebug
if task.update_attributes(task_params)
render json: task, status: 201
else
render json: { errors: task.errors.full_messages }, status: 422
end
end
...
private
def task_params
ActiveModelSerializers::Deserialization.jsonapi_parse(params)
end
end
See the 'byebug' statement in my update method? The program breaks correctly there. At the byebug prompt in the terminal, I typed in 'task_params' to see what is returned by it. Here is the output:
[21, 30] in /Users/bharat/scout/todo_api_app/app/controllers/api/v1/tasks_controller.rb
21: end
22:
23: def update
24: task = Task.find(params[:id])
25: byebug
=> 26: if task.update_attributes(task_params)
27: render json: task, status: 201
28: else
29: render json: { errors: task.errors.full_messages }, status: 422
30: end
(byebug) task_params
{:title=>"Updated Task Title", :tags=>["Urgent", "Home"], :id=>"2"}
(byebug)
So it boils down to receiving the hash with the key ':tags' that has an array of tag title values. My question is: what is the Rails way of automatically creating the tags? I can always extract the :tags key value array and programmatically do it. In the past, I have done this sort of thing using accepts_nested_attributes_for when using the HTML forms as front end. But this is the first time that I am dealing with the JSON API. I suspect this is a more generic question though than the JSON API since serialization/de-serialization is working correctly.
Sorry for the long winded question, but there was no other way that I could think of to shorten it.