0

I am trying to update an array held in the database however the update action is not working. The array is not updated and no error is shown. Other parameters in the form are correctly updated in the database.

A form sends an array as one of the parameters (in this case responses: []):

"task"=> {"title"=>"tasko uno", "responses"=>["yes", "no", "maybe", "other"] ... }

The update action:

def update
    @task = Task.find(params[:id])
    if @task.update(tasks_params)
      redirect_to edit_task_path
    else
      render 'new'
    end
  end

The params permissions:

private
    def tasks_params
      params.require(:task).permit(:title, :help, :task_type, :taskflow_id, :responses => [])
    end

The database is the out the box sql-lite and the Task model has serialize :responses, Array, the array column is of type text, with a column title responses.

Any help would be much appreciated.

EDIT The migration file:

class CreateTasks < ActiveRecord::Migration
  def change
    create_table :tasks do |t|
      t.string :title
      t.integer :task_type
      t.text :help
      t.text :responses
      t.belongs_to :taskflow
      t.timestamps null: false
    end
  end
end

Update action server log:

Started PATCH "/tasks/1" for 127.0.0.1 at 2016-06-28 12:37:12 +0100
Processing by TasksController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"BL2fI3JDIGfTqWxQHInR/NFI6N/agETaUb97lAZ86PpNmpj1ofQ+TRkHZNdiISyOMlag3geleig6PsaqaWNr8Q==", "task"=>{"title"=>"tasko uno", "help"=>"some help text", "task_type"=>"2", "taskflow_id"=>"1"}, "responses"=>["test1", "test2"], "commit"=>"Update Task", "id"=>"1"}
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" = ? LIMIT 1  [["id", 1]]
   (0.0ms)  begin transaction
   (0.0ms)  commit transaction
  Taskflow Load (0.1ms)  SELECT  "taskflows".* FROM "taskflows" WHERE "taskflows"."id" = ? LIMIT 1  [["id", 1]]
Redirected to http://localhost:3000/taskflows/1/edit
Completed 302 Found in 3ms (ActiveRecord: 0.2ms)

The form - I'm trying to have a form that adds fields dynamically:

<%= bootstrap_form_for @task do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :help %>
  <%= f.text_field :task_type %>
  <%= f.hidden_field :taskflow_id, value: @taskflow.id %>
  <hr>
  <p><strong>Responses</strong></p>

  <div class="admin-task-responses">
  <% if @task.responses %>
    <% @task.responses.each do |r| %>
      <%= render "tasks/task_response", {:res => r} %>
    <% end %>
  <% end %>
  </div>

  <div class="btn btn-primary add-response-btn">
    <span class="glyphicon glyphicon-plus"></span> Add Response
  </div>

  <%= f.submit %>
<% end %>

The partial:

<% if local_assigns.has_key? :res %>
<div class="task-response form-group">
  <%= text_field_tag "responses[]", '', :class => 'form-control', :value => res %>
</div>
<% end %>
RobotEyes
  • 4,929
  • 6
  • 42
  • 57
  • http://stackoverflow.com/questions/23340222/how-to-save-array-to-database-in-rails ? –  Jun 26 '16 at 20:43
  • @gen Thanks but i've already tried that - I'm using `serialize :responses` in the model and have checked `responses` is plural. It's not throwing an error so i'm having difficultly locating what's going on. – RobotEyes Jun 27 '16 at 09:46
  • Please, add your server logs for the update action. Do you know how to use pry? You should examine your object after update. –  Jun 27 '16 at 16:34
  • Also post your migration for this column, and try to pass params without tasks_params method. –  Jun 27 '16 at 16:39
  • @gen thanks, I have added the migration file and the log for the update action. Passing params without task_params throws a forbidden attributes error. I will give pry a go. – RobotEyes Jun 28 '16 at 11:42

2 Answers2

1

Your "responses"=>["test1", "test2"] is outside of the tasks hash, but on the other hand your responses field is a part of the Task model. Most likely, in your form you are using '..._tag' helper to enter your responses, and thus it is not connected to your @task, and it is the reason for not saving or at least for not getting any errors.

If you need more help on this, please add your form to the question.

OR, you can try the following, though, I would not recommend it over adjusting the form:

params[:task][:responses] = params[:responses]

This should work for you:

<%= text_field_tag "task[responses][]", '', :class => 'form-control', :value => res %>
  • ahh. Thank you! I am using text_field_tag in a partial to create a dynamic form that adds fields as required. I have posted the form if you caould help me do this in the correct way. – RobotEyes Jun 28 '16 at 12:21
  • @RobotEyes; I updated my answer with a possible fix for you. –  Jun 28 '16 at 12:28
0

it will be better, if you store "responses" in json formate, so encode it in json and when required decode it back.

so code would be some thing like bellow

private
params[:task][:responses] = params[:task][:responses].to_json
    def tasks_params
      params.require(:task).permit(:title, :help, :task_type, :taskflow_id,   
      :responses )
    end
RobotEyes
  • 4,929
  • 6
  • 42
  • 57
Create Explorer
  • 357
  • 2
  • 20