I find it difficult to determine how to create a form_object that creates several related objects to associate has_manywith virtus gem .
The following is a contrived example in which a form object can be overflowing, but it shows the problem I am facing:
Suppose there is an object user_formthat creates a record user, and then a pair associated with the user_emailrecords. Here are the models:
class User < ApplicationRecord
has_many :user_emails
end
class UserEmail < ApplicationRecord
belongs_to :user
end
I move on to creating a form object to represent the user form:
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"
end
end
In the classroom, UserFormyou can see what I have attribute :emails, Array[EmailForm]. This is an attempt to check and record the data that will be stored for related records user_email. Here is the form Embedded Valueto write user_email:
class EmailForm
include ActiveModel::Model
include Virtus.model
attribute :email_text, String
validates :email_text, presence: true
end
users_controller, user_form.
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 :

: 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 , , :
: to_hash Rails 5.1, ActionController::Parameters . . , , . , : http://api.rubyonrails.org/v5.0.2/classes/ActionController/Parameters.html ( new at (pry): 1) DEPRECATION: to_a Rails 5.1, ActionController::Parameters . . , , . , : http://api.rubyonrails.org/v5.0.2/classes/ActionController/Parameters.html ( new at (pry): 1) NoMethodError: [ "0", "foofoo" } : true > ], #to_hash /Users/neillocal/.rvm/gems/ruby-2.3.1/gems/virtus-1.0.5/lib/virtus/attribute_set.rb:196: `coerce '
:
Expected ["0", <ActionController::Parameters {"email_text"=>"foofoo"} permitted: true>] to respond to
, , - , , , ( ).
, :
, gem. . .
!