1

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.rband 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.

Community
  • 1
  • 1
  • Okay thank you for the params! It seems something is being submitted for the nested attributes - `Unpermitted parameter: name`. I would highly recommend you add that to your controller and try again - I'll update my ansewr – Richard Peck Jul 30 '15 at 18:35
  • please see UPDATE - 2015/7/31. And I don't think it can be work, because it submit nothing in the params. Can we try collection_check_boxes instead of text_field. `1. <%= builder.text_field :name, placeholder: survey.name %>` `2. <%= survey.collection_check_boxes :survey_ids, @surveys, :id, :name %>` neither of codes works. – Tien Shun Lo Jul 31 '15 at 10:08
  • It will work and we will make it work. – Richard Peck Aug 01 '15 at 11:43
  • I hope so, nothing found in my side, do you have any new suggestions? – Tien Shun Lo Aug 04 '15 at 02:12
  • Okay, still says you're submitting the nested attributes which means the form is either hidden or something else is preventing it from loading: `"questionnaire"=>{"name"=>"OMG", "questionnaire_surveys_attributes"=>{"0"=>{"survey_attributes"=>{"name"=>""}}}}`. Can you go onto your form, right-click, select `inspect element` and send me the screenshot? This will show whether the form actually has the elements or not. It should have, considering the parameters are being sent. – Richard Peck Aug 04 '15 at 18:56
  • please see update - 20150805 – Tien Shun Lo Aug 05 '15 at 12:36
  • can we try 2. `<%= survey.collection_check_boxes :survey_ids, @surveys, :id, :name %>` – Tien Shun Lo Aug 05 '15 at 12:49
  • Thanks for the update. So it seems the input *is* being put on the page? You can do #2 if you want (I'd have done it already). When you say you "can't see" the input, are you sure you don't have any CSS obstructing it? – Richard Peck Aug 06 '15 at 07:59
  • No, i don't have any CSS. Don't you think the ZERO here is weird?`"questionnaire[questionnaire_surveys_attributes][0][survey_attributes][name]"` – Tien Shun Lo Aug 06 '15 at 23:22
  • No, it's a standard principle in computing to start with `0` - from what I can see, your embedded form *is* showing. – Richard Peck Aug 07 '15 at 07:31
  • The solution of my friend created the code like: "questionnaire[questionnaire_surveys_attributes][][survey_attributes][na‌​me]" – which has no ZERO in it. And it does work fine. – Tien Shun Lo Aug 09 '15 at 03:24
  • Oh nice! So it works now? How did you get the form to show?? – Richard Peck Aug 09 '15 at 08:10
  • please see the UPDATE - 2015/8/11 – Tien Shun Lo Aug 11 '15 at 04:45

1 Answers1

0

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:

  1. You need to uncomment @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
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Thanks for your respond, however, it seems not working in my case. The story is that I built the Survey first, then I want to associate surveys with the questionnaire. The way I did which is wrong is because I try build and associate them at the same time, according to my friend. – Tien Shun Lo Jul 24 '15 at 10:12
  • You are right about " if you're not seeing the form elements appear, it's because you've not got it set up correctly in the backend." It shows nothing when I called <% @surveys.each do |survey| %> , because there is nothing in the :questionnaire_surveys. I was thinking it (@questionnaire.questionnaire_surveys.build.build_survey) might be work, but it still showed nothing. – Tien Shun Lo Jul 24 '15 at 10:14
  • My friend's suggestion is: `
    ` `<% @surveys.each do |survey| %>` `<%= check_box_tag "questionnaire[questionnaire_surveys_attributes][][survey_id]", survey.id %>` `<%= label_tag survey.name %>` `<% end %>` `
    `
    – Tien Shun Lo Jul 24 '15 at 10:20
  • You shouldn't need any of that if you've built the objects in the controller. – Richard Peck Jul 24 '15 at 20:13
  • Can you post a github repo of your code? There might be some other issue in the models! – Richard Peck Jul 24 '15 at 20:16
  • I have a bitbucket repo, is it ok? https://bitbucket.org/tienshunlo/surveysays Check the questionnaire branch. Thank you. – Tien Shun Lo Jul 25 '15 at 00:26
  • Models look okay. As long as you're building the objects, they should work. – Richard Peck Jul 26 '15 at 09:00
  • It's still not working. I just post my posted parameters after form submit, hope it's what you need. Thanks for all your help. – Tien Shun Lo Jul 29 '15 at 14:51