I followed this page to build my app:
Rails 4 nested attributes and has_many :through associaton in a form
but it shows NOTHING in my VIEW:
(the weird thing is when i typed "f.fields_for :questionnaire_surveRys do |ff|" instead of the right one, it showed me the ocrrect page.
any suggestions will be greatly appreciated.
here are my Models:
questionnaire.rb
class Questionnaire < ActiveRecord::Base
has_many :questionnaire_surveys
has_many :surveys, through: :questionnaire_surveys
accepts_nested_attributes_for :questionnaire_surveys
end
questionnaire_survey.rb
class QuestionnaireSurvey < ActiveRecord::Base
belongs_to :questionnaire
belongs_to :survey
accepts_nested_attributes_for :survey
end
survey.rb
class Survey < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
has_many :questionnaire_surveys
has_many :questionnaires, through: :questionnaire_surveys
end
and this is my questionnaire_controller.rb
def new
@questionnaire = Questionnaire.new
@surveys = Survey.all
end
def questionnaire_params
params.require(:questionnaire).permit(:name, questionnaire_surveys_attributes: [:id, survey_attributes:[:id]])
end
this is my _form.html.erb
<%= form_for(@questionnaire) do |f| %>
<p>
<%= f.label :name %><br/>
<%= f.text_field :name %>
<div class="field">
<%= f.fields_for :questionnaire_surveys do |ff| %>
<%= ff.fields_for :survey do |builder| %>
<% @surveys.each do |survey| %>
<%= builder.check_box :id, {}, survey.id %>
<%= builder.label survey.name %>
<% end %>
<% end %>
<% end %>
</div>
</p>
<div class="actions">
<%= f.submit %>
</div>
UPDATED:
Started POST "/questionnaires" for ::1 at 2015-07-29 22:45:16 +0800
Processing by QuestionnairesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"k4SkRC08PwAHAo1iERmQCkssdQZYgf+uHwofPdeLbXo0O4/psY3Y7i/krQA01omToQ4VLlt/YQDNkcbpLGp86w==", "questionnaire"=>{"name"=>"what just happened", "questionnaire_surveys_attributes"=>{"0"=>{"survey_attributes"=>{"name"=>""}}}}, "commit"=>"Create Questionnaire"}
Unpermitted parameter: name
(0.1ms) begin transaction
SQL (0.7ms) INSERT INTO "questionnaires" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "what just happened"], ["created_at", "2015-07-29 14:45:16.374246"], ["updated_at", "2015-07-29 14:45:16.374246"]]
SQL (0.2ms) INSERT INTO "surveys" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2015-07-29 14:45:16.377439"], ["updated_at", "2015-07-29 14:45:16.377439"]]
SQL (0.1ms) INSERT INTO "questionnaire_surveys" ("questionnaire_id", "survey_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["questionnaire_id", "52"], ["survey_id", "38"], ["created_at", "2015-07-29 14:45:16.378845"], ["updated_at", "2015-07-29 14:45:16.378845"]]
(0.9ms) commit transaction
Redirected to http://localhost:3000/questionnaires/52
Completed 302 Found in 12ms (ActiveRecord: 2.0ms)
UPDATE - 2015/7/31
Started POST "/questionnaires" for ::1 at 2015-07-31 17:46:50 +0800
Processing by QuestionnairesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"t/00prIClAUVdqPFxOnkTaxRPhTdY082PAvHb/VQSO4QQh8LLrNz6z2Qg6fhJv3URnNePN6d0ZjukB67DrFZfw==", "questionnaire"=>{"name"=>"OMG", "questionnaire_surveys_attributes"=>{"0"=>{"survey_attributes"=>{"name"=>""}}}}, "commit"=>"Create Questionnaire"}
(0.2ms) begin transaction
SQL (0.7ms) INSERT INTO "questionnaires" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "OMG"], ["created_at", "2015-07-31 09:46:50.440466"], ["updated_at", "2015-07-31 09:46:50.440466"]]
SQL (0.4ms) INSERT INTO "surveys" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", ""], ["created_at", "2015-07-31 09:46:50.446176"], ["updated_at", "2015-07-31 09:46:50.446176"]]
SQL (0.2ms) INSERT INTO "questionnaire_surveys" ("questionnaire_id", "survey_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["questionnaire_id", "53"], ["survey_id", "39"], ["created_at", "2015-07-31 09:46:50.450001"], ["updated_at", "2015-07-31 09:46:50.450001"]]
(0.9ms) commit transaction
Redirected to http://localhost:3000/questionnaires/53
Completed 302 Found in 22ms (ActiveRecord: 2.4ms)
UPDATE - 2015/8/05
I can't upload pics here, hope this is what you need:
<input placeholder="vision" type="text" name="questionnaire[questionnaire_surveys_attributes][0][survey_attributes][name]" id="questionnaire_questionnaire_surveys_attributes_0_survey_attributes_name">
UPDATE - 2015/8/11
_form.erb.html
<div class="field">
<% @surveys.each do |survey| %>
<%= check_box_tag "questionnaire[questionnaire_surveys_attributes][][survey_id]", survey.id %>
<%= label_tag survey.name %>
<% end %>
</div>
questionnaires_controller.rb
params.require(:questionnaire).permit(:name, questionnaire_surveys_attributes: [:survey_id])
def new
@questionnaire = Questionnaire.new
@surveys = Survey.all
end
UPDATE - 2015/8/17
I misused the has_many :through
and accepts_nested_attributes_for
.
In has_many:xxx :through
case, there is xxx_ids
.
In accepts_nested_attributes_for xxx
case, there is xxx_attributes
.
I used accepts_nested_attributes_for
in both questionnaire.rb
and questionnaire_survey.rb
, which is a mistake.
The correct way to do what I want is use the has_many :through
only.
Then my questionnaire_controller.rb
will have
def questionnaire_params
params.require(:questionnaire).permit(:name, :survey_id=>[])
end
in _form view, it should be
<%= check_box_tag "questionnaire[survey_id][]", survey.id %>
it's much easier now.
@Rich Peck thanks for all your help.
First things first - if you're not seeing the form elements appear, it's because you've not got it set up correctly in the backend.
For the longest time, I tried to set this up and was getting very frustrated that the embedded form would not appear. It wasn't until I sorted it out properly that it worked. It's called graceful degradation (I think) - whereby no error will appear, yet functionality will be impaired.
Firstly, I think you haven't built your associated objects in the controller:
#app/controllers/questionnaire_controller.rb
def new
@questionnaire = Questionnaire.new
# You need to build the associated objects, like this:
@questionnaire.questionnaire_surveys.build.build_survey
@surveys = Survey.all
end
--
Secondly, there is a better way to show checkboxes for your @surveys
object:
<%= ff.fields_for :survey do |survey| %>
<%= survey.collection_check_boxes :survey_ids, @surveys, :id, :name %>
<% end %>
You can read up about collection_check_boxes
here
--
Thirdly, you should definitely learn haml. You could write your entire form like this:
= form_for @questionnaire do |f|
.name
= f.label :name
= f.text_field :name
.field
= f.fields_for :questionnaire_surveys do |ff| %>
= ff.fields_for :survey do |survey| %>
= survey.collection_check_boxes :survey_ids, @surveys, :id, :name
.actions
= f.submit
--
Finally, don't use HTML elements as styling.
<p>
& <br>
should only be used as markup. If you're using them for styling effect, you'll end up causing problems with browser compatibility etc.
You need to let your CSS do the styling (colouring, size, position), and any on-page elements used as ways to separate the content of your application.
Update
Okay, so I've looked at your BitBucket:
@questionnaire.questionnaire_surveys.build.build_survey
in app/controllers/questionnaires_controller.rb#20
If you do that, it should work.
I cannot see any problems with the construct of the models and controllers. Are you sure you've refreshed etc?
I see you're calling <%= render "form" %>
- try putting the form directly in the new
view to test if it will work.
Also, have you tried using a simple way to add the extra fields, like this:
<%= f.fields_for :questionnaire_surveys do |ff| %>
<%= ff.fields_for :survey do |builder| %>
<% @surveys.each do |survey| %>
<%= builder.text_field :name, placeholder: survey.name %>
<% end %>
<% end %>
Finally, if you post your posted parameters after form submit, I'll be in a much stronger position to see any of the errors/problems you may have.
--
You can change your params to the following:
#app/controllers/questionnaires_controller.rb
...
def questionnaire_params
params.require(:questionnaire).permit(:name, questionnaire_surveys_attributes: [:id, survey_attributes:[:name]])
end