不记录嵌套形式中的虚拟属性
Virtual attributes in nested forms are not recorded
您会在我的代码中看到我在新操作的视图中有一个 "has_many => belongs_to" 模型关联和一个嵌套表单。
另外,我用过Using two separate fields for the same parameter in a Rails form handler?
问题是 "prix" 属性(在 "Projet" 模型中)记录在数据库中,而不是 "nom" 属性(在 "Activite" 模型中) .
也许问题出在强参数上,但我认为在我的代码中一切都很好...
或者可能在我在链接的其他 Whosebug 问题上找到的代码中。
我的代码中有法语单词:activite 是 activity,projet 是项目,nom 是名称,prix 是价格,非常简单:)
感谢您的帮助!
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>
为了使虚拟属性起作用,您还需要定义一个 setter 和一个 getter。这可以通过自己明确定义 getters 和 setters 或使用 attr_accessor
.
来完成
使用 attr_accessor
的示例:
class Activite < ActiveRecord::Base
attr_accessor :nom
....
end
手动定义 setter 和 getter 的示例:
class Activite < ActiveRecord::Base
....
def nom=(value)
super
end
def nom
@nom
end
end
对于您的 class 命名的第二个问题,因为它们是法语,您还需要在 has_many
和 belongs_to
上指定 class_name
选项以按如下方式指定您的非英语 class 名称:
class Projet < ActiveRecord::Base
has_many :activites, class_name: 'Activite'
end
同样,对于 Activite
模型:
class Activite < ActiveRecord::Base
belongs_to :projet, class_name: 'Projet'
end
您会在我的代码中看到我在新操作的视图中有一个 "has_many => belongs_to" 模型关联和一个嵌套表单。
另外,我用过Using two separate fields for the same parameter in a Rails form handler?
问题是 "prix" 属性(在 "Projet" 模型中)记录在数据库中,而不是 "nom" 属性(在 "Activite" 模型中) .
也许问题出在强参数上,但我认为在我的代码中一切都很好... 或者可能在我在链接的其他 Whosebug 问题上找到的代码中。
我的代码中有法语单词:activite 是 activity,projet 是项目,nom 是名称,prix 是价格,非常简单:)
感谢您的帮助!
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>
为了使虚拟属性起作用,您还需要定义一个 setter 和一个 getter。这可以通过自己明确定义 getters 和 setters 或使用 attr_accessor
.
使用 attr_accessor
的示例:
class Activite < ActiveRecord::Base
attr_accessor :nom
....
end
手动定义 setter 和 getter 的示例:
class Activite < ActiveRecord::Base
....
def nom=(value)
super
end
def nom
@nom
end
end
对于您的 class 命名的第二个问题,因为它们是法语,您还需要在 has_many
和 belongs_to
上指定 class_name
选项以按如下方式指定您的非英语 class 名称:
class Projet < ActiveRecord::Base
has_many :activites, class_name: 'Activite'
end
同样,对于 Activite
模型:
class Activite < ActiveRecord::Base
belongs_to :projet, class_name: 'Projet'
end