如何在 Rails 5.2 上使用 Ruby 创建嵌套属性的子集
How to create a subset of nested attibutes with Ruby on Rails 5.2
我的应用程序是一个以多种语言描述业务规则的知识库。名称和描述的翻译被设计为嵌套属性。它们不存在于母版 table 中,仅存在于翻译中 table:
id :integer not null, primary key
field_name :string(30) not null
language :string(2) not null
translation :text
created_at :datetime not null
updated_at :datetime not null
业务规则可以有多种翻译,如模型中声明的那样:
has_many :name_translations, -> { where("field_name='name'") }, class_name: 'Translation'
has_many :description_translations, -> { where("field_name='description'") }, class_name: 'Translation'
创建时,我在业务规则控制器中初始化这些翻译:
def new
@business_rule = BusinessRule.new
@business_rule.name_translations.build(language: user_language, field_name: 'name')
@business_rule.name_translations.build(language: user_language, field_name: 'description')
end
在 _form.html.rb 中,我只想显示当前用户语言的翻译。当然,在创建规则时,只有一种语言可用,但由于我使用相同的表单进行更新,因此我需要过滤嵌套翻译并仅保留当前用户的语言:
<div class="row">
<div class="col-md-1 text-right"> <%= t('Name')%>:
</div>
<%= f.fields_for :name_translations, @business_rule.name_translations.where('language=?', user_language) do |naming| %>
<div class="col-md-8">
<%= naming.text_field :translation, :class => "col-md-10" %>
</div>
<div class="col-md-1">
<%= naming.hidden_field :field_name, :value => 'name' %>
</div>
<div class="col-md-1">
<%= naming.hidden_field :language, :value => user_language %>
</div>
<% end %>
</div>
这适用于编辑现有业务规则。但对于业务规则创建,嵌套字段不显示。
如果我删除
@business_rule.name_translations.where('language=?', user_language)
expression,显示输入的字段。但这不符合编辑要求,因为所有翻译也都显示了。
我怀疑这个表达式查询的是数据库中的嵌套属性,而不是控制器中 new 方法初始化的属性。
有没有办法避免这种情况,或者过滤传递给 fields_for[=40= 的 :name_translations ] 方法 ?
感谢您的帮助!
如果我没理解错的话,您不需要为 new
操作过滤 :name_translations。因此,在表单中您可以使用 persisted?
来检查记录是否存在:
<%= f.fields_for :name_translations, @business_rule.name_translations.where('language=?', user_language) if @business_rule.persisted? do |naming| %>
...
<% end %>
因此,您可以仅为现有记录过滤嵌套属性。
我的应用程序是一个以多种语言描述业务规则的知识库。名称和描述的翻译被设计为嵌套属性。它们不存在于母版 table 中,仅存在于翻译中 table:
id :integer not null, primary key
field_name :string(30) not null
language :string(2) not null
translation :text
created_at :datetime not null
updated_at :datetime not null
业务规则可以有多种翻译,如模型中声明的那样:
has_many :name_translations, -> { where("field_name='name'") }, class_name: 'Translation'
has_many :description_translations, -> { where("field_name='description'") }, class_name: 'Translation'
创建时,我在业务规则控制器中初始化这些翻译:
def new
@business_rule = BusinessRule.new
@business_rule.name_translations.build(language: user_language, field_name: 'name')
@business_rule.name_translations.build(language: user_language, field_name: 'description')
end
在 _form.html.rb 中,我只想显示当前用户语言的翻译。当然,在创建规则时,只有一种语言可用,但由于我使用相同的表单进行更新,因此我需要过滤嵌套翻译并仅保留当前用户的语言:
<div class="row">
<div class="col-md-1 text-right"> <%= t('Name')%>:
</div>
<%= f.fields_for :name_translations, @business_rule.name_translations.where('language=?', user_language) do |naming| %>
<div class="col-md-8">
<%= naming.text_field :translation, :class => "col-md-10" %>
</div>
<div class="col-md-1">
<%= naming.hidden_field :field_name, :value => 'name' %>
</div>
<div class="col-md-1">
<%= naming.hidden_field :language, :value => user_language %>
</div>
<% end %>
</div>
这适用于编辑现有业务规则。但对于业务规则创建,嵌套字段不显示。
如果我删除
@business_rule.name_translations.where('language=?', user_language)
expression,显示输入的字段。但这不符合编辑要求,因为所有翻译也都显示了。
我怀疑这个表达式查询的是数据库中的嵌套属性,而不是控制器中 new 方法初始化的属性。
有没有办法避免这种情况,或者过滤传递给 fields_for[=40= 的 :name_translations ] 方法 ?
感谢您的帮助!
如果我没理解错的话,您不需要为 new
操作过滤 :name_translations。因此,在表单中您可以使用 persisted?
来检查记录是否存在:
<%= f.fields_for :name_translations, @business_rule.name_translations.where('language=?', user_language) if @business_rule.persisted? do |naming| %>
...
<% end %>
因此,您可以仅为现有记录过滤嵌套属性。