Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails, edit action does not populate the form correctly with many instances of the same model

I'm new to Rails and I'm doing my first project. Also, English is not my native language so bear with me, please.

The problem I'm having is that I have a form with multiple instances of the same model, the data is being created correctly but when I try to edit it the form is populated in the wrong way.

I'm making an app to check if everything goes according to the rules. The items to be checked are in a nested association Chapters->Subchapters->Checks

Every time the checks are submitted a CheckRound is created and the information of every check is stored separately in CheckResults.

CheckRounds

has_many :check_results, inverse_of: :check_round, dependent: :destroy
accepts_nested_attributes_for :check_results, reject_if: proc { |att| att['observation'].blank? }

CheckResults

belongs_to :check_round, optional: true, inverse_of: :check_results
belongs_to :check

Chapters

has_many :subchapters

Subchapters

belongs_to: chapter
has_many: checks

Checks

belongs_to :subchapter
has_many :check_results

The form displays all the Chapters and the nested Subchapters and Checks. Every Check displays its name and has a text_area as an input.

The user can fill none or many Checks.

<%= form_for(@check_round, :url => {:action => 'update', :client_id => @client.id, :project_id => @project.id}) do |f| %>
  <% @chapters.each do |chapter| %>
    <%= chapter.name %>
    <% chapter.subchapters.each do |subchapter| %>
      <%= subchapter.name %>
      <% subchapter.checks.each do |check| %>
         <%= f.fields_for :check_results do |result| %>
            <%= check.name %>
            <%= result.hidden_field(:check_id, :value => check.id) %>
            <%= result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s) %>
        <% end %>
      <% end %>
   <% end %>
  <% end %>
<% end %>

The controller is

def edit
  @check_round = CheckRound.includes(:check_results).find(params[:id])
  @chapters = Chapter.includes(subchapters: :checks).where("segment_id = ?", @project.segment_id).sorted
end

If for example, I submit that check.id = 3 has the observation = "bad" when I go to edit every check has "bad" in its observation regardless of its id.

I want to know how can I show in edit all the checks with a blank observation but the ones that were created.

Thanks in advance for your time!

like image 622
leogar07 Avatar asked Sep 30 '17 00:09

leogar07


1 Answers

Here is the solution i've promised.

Sinds you have already defined that check results with blank observations had to be rejected and there will to much logic involved in your erb for its own sake, i would put it all in an helper method so your erb will be cleaner. Something like this:

#helpers/check_rounds_helper.rb

def edit_or_instantiate_nested_check_results(f, check_round, check, new_check_result)
  if check.check_results
    f.fields_for :check_results, check_round.check_results.where(check_id: check.id) do |result|
      result.hidden_field(:check_id, :value => check.id)
      result.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
    end #end for the already present check results
    # if u want to add a new check result event if the check is populated
    f.fields_for :check_results, new_check_result do |new|
      new.hidden_field(:check_id, :value => check.id)
      new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
    end #end for the new check result
  else #if there is no existing check result nest a form for a new one
    f.fields_for :check_results, new_check_result do |new|
      new.hidden_field(:check_id, :value => check.id)
      new.text_area(:observation, rows: 4, :id =>'obs' + check.id.to_s)
    end #end for the new check result
  end #end if statement
end

Then in your view:

<%= form_for(@check_round, :url => {:action => 'update', :client_id => @client.id, :project_id => @project.id}) do |f| %>
  <% @chapters.each do |chapter| %>
    <%= chapter.name %>
    <% chapter.subchapters.each do |subchapter| %>
      <%= subchapter.name %>
      <% subchapter.checks.each do |check| %>
         <%= check.name %>
         <% new_check_result = CheckResult.new(check_round_id: @check_round.id, check_id = check.id) %>
         <%= edit_or_instantiate_nested_check_results(f, @check_round, check, new_check_result) %>
      <% end %>
   <% end %>
  <% end %>
<% end %>

And that shoud be it ;). Let me know if it did the trick :D!

KR,

like image 135
Patrick Cyiza Avatar answered Nov 14 '22 15:11

Patrick Cyiza