has_many
の関連オブジェクトを複数作成するform_objectを作成する方法を理解するのに苦労しています。virtus gem。以下はVirtusのRailsフォームオブジェクト:has_many関連
は、フォームオブジェクトはやり過ぎかもしれない不自然な例ですが、それは私が午前問題を示してい:
はその後user
、レコード、および関連するカップルを作成user_form
オブジェクトがあるとしましょうuser_email
記録。ここでのモデルは、次のとおりです。
# models/user.rb
class User < ApplicationRecord
has_many :user_emails
end
# models/user_email.rb
class UserEmail < ApplicationRecord
belongs_to :user
end
私は、ユーザーフォームを表すために、フォームオブジェクトの作成に進む:
# app/forms/user_form.rb
class UserForm
include ActiveModel::Model
include Virtus.model
attribute :name, String
attribute :emails, Array[EmailForm]
validates :name, presence: true
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
puts "The Form is VALID!"
puts "I would proceed to create all the necessary objects by hand"
# user = User.create(name: name)
# emails.each do |email_form|
# UserEmail.create(user: user, email: email_form.email_text)
# end
end
end
一つは、私がattribute :emails, Array[EmailForm]
を持ってUserForm
クラスに気づくでしょう。これは、関連付けられたuser_email
レコードに対して保持されるデータを検証して取得する試みです。ここでuser_email
レコードのEmbedded Value
形式は次のとおりです。
# app/forms/email_form.rb
# Note: this form is an "Embedded Value" Form Utilized in user_form.rb
class EmailForm
include ActiveModel::Model
include Virtus.model
attribute :email_text, String
validates :email_text, presence: true
end
は、今、私が先に行くとuser_formを設定users_controller
が表示されます。
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user_form = UserForm.new
@user_form.emails = [EmailForm.new, EmailForm.new, EmailForm.new]
end
def create
@user_form = UserForm.new(user_form_params)
if @user_form.save
redirect_to @user, notice: 'User was successfully created.'
else
render :new
end
end
private
def user_form_params
params.require(:user_form).permit(:name, {emails: [:email_text]})
end
end
new.html.erb
:
<h1>New User</h1>
<%= render 'form', user_form: @user_form %>
そして_form.html.erb
:
<%= form_for(user_form, url: users_path) do |f| %>
<% if user_form.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user_form.errors.count, "error") %> prohibited this User from being saved:</h2>
<ul>
<% user_form.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<% unique_index = 0 %>
<% f.object.emails.each do |email| %>
<%= label_tag "user_form[emails][#{unique_index}][email_text]","Email" %>
<%= text_field_tag "user_form[emails][#{unique_index}][email_text]" %>
<% unique_index += 1 %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
注:この中でuser_emails
の入力を表示するように簡単に、より多くの従来の方法がある場合フォームオブジェクト:私に教えてください。私はfields_for
を働かせることができませんでした。上に示したように、私はname
の属性を手で書き出す必要がありました。
良いニュースは、フォームがレンダリングないということです。
フォームのHTMLは私にOKになります。
上記の入力が提出された場合:ここではparamsハッシュです:
Parameters: {"utf8"=>"✓", "authenticity_token"=>”abc123==", "user_form"=>{"name"=>"neil", "emails"=>{"0"=>{"email_text"=>"foofoo"}, "1"=>{"email_text"=>"bazzbazz"}, "2"=>{"email_text"=>""}}}, "commit"=>"Create User form"}
paramsハッシュは私には大丈夫です。私が手ログで
私はVirtus社は時代遅れず、したがって、もはや作業フォームオブジェクトのためのソリューションレール中かもしれないと思わせる2つの非推奨の警告:で全部のエラーを出し、その後
DEPRECATION WARNING: Method to_hash is deprecated and will be removed in Rails 5.1, as
ActionController::Parameters
no longer inherits from hash. Using this deprecated behavior exposes potential security problems. If you continue to use this method you may be creating a security vulnerability in your app that can be exploited. Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.2/classes/ActionController/Parameters.html (called from new at (pry):1) DEPRECATION WARNING: Method to_a is deprecated and will be removed in Rails 5.1, asActionController::Parameters
no longer inherits from hash. Using this deprecated behavior exposes potential security problems. If you continue to use this method you may be creating a security vulnerability in your app that can be exploited. Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.2/classes/ActionController/Parameters.html (called from new at (pry):1) NoMethodError: Expected ["0", "foofoo"} permitted: true>] to respond to #to_hash from /Users/neillocal/.rvm/gems/ruby-2.3.1/gems/virtus-1.0.5/lib/virtus/attribute_set.rb:196:in `coerce'
そして、メッセージ次:
Expected ["0", <ActionController::Parameters {"email_text"=>"foofoo"} permitted: true>] to respond to #to_hash
私は近くのどちらかだと、それが機能するためには、小さな何かが欠けていますように私は感じる、または私は(非推奨の警告を経由して)Virtus社は時代遅れで、もはや使用可能であることを実現しています。
- this article:私は見て
リソース。
- this video
私は仕事ではなくreform-rails gemと同じフォームを取得しようとしました。私もそこで問題に遭遇しました。その質問はposted hereです。
ありがとうございます!
編集を承認してください。私は喜んで回答を受け入れられた回答としてマークします。バリデーションが意図どおりに機能するように、いくつかのマイナーチェンジを行い、次にすべての主要な部分にコードを提供します。私はあなたの投稿された答えは、私が立ち往生した部分を介して私を得たので、あなたに信用を与えたい。 – Neil
フォームオブジェクトにvirtus gemを使用する利点を考慮する必要があります。プロジェクトにvirtus gemの依存関係を追加しなくても簡単にフォームオブジェクトを作成できます。 [Railsフォームのオブジェクトの実装はこちら](http://stackoverflow.com/questions/42930117/form-objects-in-rails/43024542#43024542) – Neil
この回答に感謝します。それは私が探していたものです。 私はRails newbです。誰かが 'emails_attributes =(attributes)'を定義する必要がある理由を私に説明することができますか?これを何と呼びますか?このメソッドが定義されていないと、 '@user_form.emails = [EmailForm.new、EmailForm.new、EmailForm.new]'は期待どおりに動作しません。 Railsのどこにこの魔法が起こっていますか? – user3574603