You'll see in my code I've got a "has_many => belongs_to" models association and a nested form in the new actions's view.
Plus, I've used Using two separate fields for the same parameter in a Rails form handler?
The problem is the "prix" attribute (in the "Projet" model) is recorded in the database, but not the "nom" attribute (in the "Activite" model).
Maybe the problem is around the strong parameters, but I thinks it's all good in my code... Or maybe in the code I've found on the other Stackoverflow question I've linked.
There is french words in my code : activite is activity, projet is project, nom is name, prix is price, very easy :)
Thank's for your help !
app/model/projet.rb :
class Projet < ActiveRecord::Base
has_many :activites
accepts_nested_attributes_for :activites,
reject_if: lambda {|attributes| attributes['nom'].blank?}
end
app/models/activite.rb :
class Activite < ActiveRecord::Base
belongs_to :projet
def acttext=(value)
@acttext = value if value
prepare_act
end
def actselect=(value)
@actselect = value if value
prepare_act
end
def acttext
@acttext || self.nom
end
def actselect
@actselect || self.nom
end
private
def prepare_act
self.nom = acttext if acttext
self.nom = actselect if actselect
end
end
app/controllers/projets_controller.rb :
class ProjetsController < ApplicationController
def new
@projet = Projet.new
@activites_options = Activite.pluck(:nom).uniq
2.times { @projet.activites.new}
end
def create
@projet = Projet.new(projet_params)
if @projet.save
redirect_to @projet
else
render 'new'
end
end
private
def projet_params
params.require(:projet).permit(:prix, activites_attributes: [:id, :nom, :heures, :minutes, :acttext, :actselect])
end
end
app/views/projets/new.html.erb :
<div>
<%= form_for @projet do |f| %>
<%= f.label :prix %><br>
<%= f.text_area :prix %><br>
<ul>
<%= f.fields_for :activites do |activites_form| %>
<li>
<%= activites_form.label :choisissez_un_type_dactivité %>
<%= activites_form.select :actselect, @activites_options, {include_blank: true} %>
<%= activites_form.label :ou_créez_en_un_nouveau %>
<%= activites_form.text_field :acttext %><br>
<%= activites_form.label :heures %>
<%= activites_form.text_field :heures %>
<%= activites_form.label :minutes %>
<%= activites_form.text_field :minutes %>
</li>
<br>
<% end %>
</ul>
<p><%= f.submit "Créer le projet" %></p>
<% end %>
</div>
In order for virtual attributes to work, you'll also need to define a setter and a getter. This can be done by either defining the getters and setters explicitly yourself or by using attr_accessor
.
Example using attr_accessor
:
class Activite < ActiveRecord::Base
attr_accessor :nom
....
end
Example defining both setter and getter manually:
class Activite < ActiveRecord::Base
....
def nom=(value)
super
end
def nom
@nom
end
end
For the second issue with your class naming due to them being French, you'd also want specify the class_name
option on both has_many
and belongs_to
to specify your non english class names as follows:
class Projet < ActiveRecord::Base
has_many :activites, class_name: 'Activite'
end
Similarly, for Activite
model:
class Activite < ActiveRecord::Base
belongs_to :projet, class_name: 'Projet'
end