EDIT: Solution at bottom and selected answer.
I've been working with Formtastic for a while and for the most part like how it simplifies form creation. Unfortunately, I've run into a snag with using checkboxes. For some reason after I save/submit my form, the checkboxes are not getting checked.
Code Snippets
= ff.input :answer, :as => :check_boxes, :collection => ff.object.survey_question.options, :label => ff.object.survey_question.question
-- .options collection method seen below:
def options
opts = {}
survey_options.each do |option|
opts[option.option] = option.id.to_s
end
opts
end
Submission
The form returns the following (truncated) params:
params[:response][:question_responses_attributes] =
{
"0"=>
{"answer"=>"42", "id"=>"1175"},
...,
"3"=>
{"answer"=>["", "52", "54", "56"], "id"=>"1178"},
...
}
Which writes to the database as
--- - '' - '52' - '54' - '56'
I haven't been able to get the checkboxes (using the code input above) UNLESS there is only ONE answer checked. And only if the I strip out everything on submission and store the response in a custom format.
E.G.
params[:response][:question_responses_attributes].each do |key, values|
if values[:answer].is_a?(Array)
values[:answer] = values[:answer].delete_if {|x| x == ""}.join(",")
end
end
will strip out the first blank option, and then split the array into a comma delimited string.
52,54,56
What I've tried so far
= ff.input :answer, :as => :check_boxes, :collection => ff.object.survey_question.options, :checked => ff.object.answer.scan(/\w+/), :label => ff.object.survey_question.question
which splits the answer into an array.
= ff.input :answer, :as => :check_boxes, :collection => ff.object.survey_question.options, :label => ff.object.survey_question.question, :input_html => {:checked => true}
which checks ALL of the check boxes.
= ff.input :answer, :as => :check_boxes, :collection => ff.object.survey_question.options, :label => ff.object.survey_question.question, :input_html => {:checked => ff.object.answer.scan(/\w+/)}
which also checks ALL of the check boxes.
NOTE:
= ff.input :answer, :as => :check_boxes, :collection => ff.object.survey_question.options, :label => ff.object.survey_question.question
WORKS if there is only ONE checked answer (56) and I custom format the params before I save them to the database
Other Options??
Are there ANY other options? According to the Formtastic WIKI they no longer support :selected or :checked and offered another option setting a default value to be used in the after initialize model or in controller with a select and text box. I have not been able to find a working way to do so with checkboxes.
I'm open to using an extra bit of js code to check the boxes after the fact, but I would rather do it as the form is rendered with rails...
Thanks in advance for your help!
EDIT
I finally solved this issue. It had nothing to do with how the data was getting saved and everything to do with how I was passing the data to Formtastic.
First, I had to create join table between the question response table and the survey option table. Then I had to format how the data was accessing ALL of the survey options (based on the question) and ALL of the checked options for the question response:
class QuestionResponse
has_many :question_response_options
has_many :survey_options, :through => :question_response_options
# Takes all the survey options that are stored in the join
# table and puts the id's into an array
def question_response_options
opts = []
self.survey_options.each do |option|
opts << option.id.to_s
end
opts
end
end
class QuestionResponseOption
belongs_to :question_response
belongs_to :survey_option
end
class SurveyQuestion < ActiveRecord::Base
# Creates hash of option name to id
# { "Law and Order" => 13 }
def options
opts = {}
survey_options.each do |option|
opts[option.option] = option.id.to_s
end
opts
end
end
Then in Formtastic, I had to change up how I sent information across:
= ff.input :question_response_options, :as => :check_boxes, :collection => ff.object.survey_question.options, :for => :question_response_options
The input had to be for the join table, the collection needed to be all of the options for the given question, and the :for let me join the two by ID.
Only thing I had to do after that is save the checked options myself, which I did in the controller.