In my rails app I have nested attributes. I'm using jquery-ui-sortable
to sort the nested field sets.
On form submit I want to maintain the sorted order and to display the field sets in this when opening in edit mode. I want to save the sorted position of each nested field set in database.
I tried the acts_as_list
gem, but was unable to get it working. I'm currently using the following logic and it works fine.
I want to know whether this logic is correct or not. Kindly give your suggestions on it. Thanks for your responses in advance.
The logic is:
position
for each field set and have
default_scope { order("position ASC") }
in my modelposition
for each field and use this for further processingI get the following raw params:
{
"utf8" => "✓", "_method" => "put", "job" => {
"name" => "my another test",
"fields_attributes" => {
"1" => {
"field_value" => "Id",
"field_id" => "1",
"_destroy" => "false",
"id" => "9"
},
"0" => {
"field_value" => "Name",
"field_id" => "2",
"_destroy" => "false",
"id" => "10"
}
},
"include_header" => "1"
}, "search" => "", "controller" => "jobs", "action" => "update", "id" => "4"
}
permitted: false
and my controller code is:
before_action :set_position, only: :update
def update
@job = Job.where(id: params[:id]).first
if @job.update_attributes(job_params)
redirect_to jobs_url
end
end
def set_position
index = 1
params[:job][:fields_attributes].each do |f, params|
params[:position] = index
index += 1
end
end
def data_job_params
params.require(:job).permit(:name, :user_id, :include_header, fields_attributes: %i(id field_value field_id position _destroy))
end
It's working fine, but I want to know whether I am doing this in the correct way or not.
There are a few things that might be handy here:
Firstly, you could use each_with_index
to iterate through params[:job][:fields_attributes]
- something like:
def set_position
params[:job][:fields_attributes].each_with_index do |(f, fieldset_params), i|
fieldset_params[:position] = index + 1 # << index starts at 0
end
end
You'll also notice that the key to each object in params[:job][:fields_attributes]
is actually the number of the object in the hash, so, if you're happy with it, you could use that:
def set_position
params[:job][:fields_attributes].each do |f, fieldset_params|
fieldset_params[:position] = f
end
end
You'll notice I've changed params
to fieldset_params
in both of these examples - it saves a little confusion / potential errors by not shadowing the outer variable.
You could also have a hidden field in your view code for position
, starting from 1. If you edit your question to include the view code, I can show you how you'd do that.
Hope something in there can help - let me know how you get on!