Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails, two models in one form

I have two very similar models Pretreatment and Diagnosis, that belong to the model Patient:

class Pretreatment < ActiveRecord::Base
  belongs_to :patient
  attr_accessible :content
end

class Diagnosis < ActiveRecord::Base
  belongs_to :patient
  attr_accessible :content
end

class Patient < ActiveRecord::Base
  attr_accessible :age, :name, :city, :street, :number
  has_many :anamneses
  has_many :befunds
end

On the Patient show page I'm displaying two forms, one for the Preatreatment and another for the Diagnosis:

<%= form_for([@patient, @patient.preatreatments.build]) do |f| %>
  <div class="field">
    <%= f.label :conten %><br />
    <%= f.text_field :content %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

<%= form_for([@patient, @patient.diagnosiss.build]) do |f| %>
  <div class="field">
    <%= f.label :content %><br />
    <%= f.text_field :content %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

My question is how can I bring the two forms together, so that the user only has to press once the submit button? Im not sure but I think nested attributes is not the right thing to handle it, maybe thefields_for` tag?

Update I tried to use fields_for tag:

   <%= form_for([@patient, @patient.pretreatment.build]) do |f| %>
     <div class="field">
       <%= f.label :content %><br />
       <%= f.text_field :content %>
     </div>
     <%= fields_for([@patient, @patient.diagnosiss.build]) do |u| %>
     <div class="field">
       <%= u.label :content %><br />
       <%= u.text_field :content %>
     </div>
     <% end %>
     <div class="actions">
       <%= f.submit %>
     </div>
   <% end %>

But I get the error:

undefined method `model_name' for Array:Class in <%= fields_for([@patient,@patient.befunds.build]) do |u| %>
like image 788
Em Sta Avatar asked Jun 16 '13 08:06

Em Sta


3 Answers

Use fields_for for the associated models.
There should be no square brackets arround the parameters of fields_for

In your code example, I cannot find the relation between Patient and Diagnosis, and the plural of diagnosis is diagnoses, you can specify this in config/initializers/inflections.rb:

ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'diagnosis','diagnoses'
end

So your Patient model should contain

class Patient < ActiveRecord::Base
  attr_accessible :age, :name, :city, :street, :number
  has_many :diagnoses
end

And you can write in your form:

 <div class="field">
   <%= f.label :content %><br />
   <%= f.text_field :content %>
 </div>
 <%= fields_for(@patient, @patient.diagnoses.build) do |u| %>
 <div class="field">
   <%= u.label :content %><br />
   <%= u.text_field :content %>
 </div>
 <% end %>
 <div class="actions">
   <%= f.submit %>
 </div>
like image 76
Martin M Avatar answered Nov 03 '22 09:11

Martin M


You can achieve that using nested attributes :

patient.rb

class Patient < ActiveRecord::Base
  attr_accessible :age, :name,  :pretreatments_attributes, :diagnosiss_attributes
  has_many :pretreatments
  has_many :diagnosiss

  accepts_nested_attributes_for :pretreatments
  accepts_nested_attributes_for :diagnosiss
end

patients_controller.rb

def show
    @patient = Patient.find(params[:id])
    @patient.pretreatments.build
    @patient.diagnosiss.build
    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @patient }
    end
  end

patients/show.html.erb:

<%= form_for @patient do  |f|%>
    <h3>Pretreatments:</h3>

    <%= f.fields_for :pretreatments do |field| %>
        <%= field.label "Content" %></div>
        <%= field.text_field :content %>
    <% end %>

    <h3>Diagnosis:</h3>

    <%= f.fields_for :diagnosiss do |field| %>
        <%= field.label "Content" %></div>
        <%= field.text_field :content %>
    <% end %>

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

And that all

like image 36
Muntasim Avatar answered Nov 03 '22 09:11

Muntasim


There are a few ways of doing this:

  1. The way the fields_for works is you have a form_for for the parent model and within it you can place fields_for the models which belong to the parent. A good example is given in the Rails Docs
  2. A simple and more extensible option over time but not very "semantic" one would be to use JavaScript/JQuery. You could trigger $("form #new_pretreatments").submit(); and the same for the Diagnosis once a button is clicked.
  3. Maybe instead you could have just one model to store them both. For example a model called Disease. Each time a patient gets a disease a new one is created and it has columns for each the Diagnosis and Pretreatment. It's probably the best option instead of adding another model for each bit of info a patient can have.
like image 2
roryhughes Avatar answered Nov 03 '22 10:11

roryhughes