10 Jun Using simple_form for nested attributes models in a has_many relation for only new records
How to create a new nested attribute form for only new records in a has_many relationship using simple_form, well according to this stackoverflow http://stackoverflow.com/questions/14884704/how-to-get-rails-build-and-fields-for-to-create-only-a-new-record-and-not-includ I was trying to create a new records using nested attributes the problem with that solution it is that if the form has error fields the form will be clear and boom after the page reloading you’ll have nothing filled in your form and can you imagine if you form is like 20 or 30 fields that would be a terrible user experience of course so let’s look at my solution using:
– Simple Form from plataformatec.
– Nested Attributes and has_many relationship
– Transactions in rails and rendering errors in form.
– Using service to create the data
Let’s take a closer look at the code:
Spree::User model
has_many :applications, -> { order("created_at DESC")}
has_one :new_application, class_name: 'Application'
accepts_nested_attributes_for :new_application
Code within the controller
def new
@user = find_user
@user.build_new_application
respond_with @user
enda
def find_user
spree_current_user || Spree::User.new
end
def create
service = ServiceApplication.new(application_params, find_user)
@user = service.perform
if @user.valid?
redirect_to root_path, notice: 'Your application is submitted'
else
render 'new'
end
end
private
def application_params
params.require(:user).permit(
:username,
:password,
:new_application_attributes => [
:name,
]
)
end
app/services/application_service.rb
class ApplicationService
def initialize(application_params, user)
@application_params = application_params
@current_user = user
end
def perform
@current_user.transaction do
begin
create_application_and_user
rescue => e
Rails.logger.error "=========== exception creating application ===#{e.inspect}========"
raise ActiveRecord::Rollback
end
end
@current_user
end
def create_application_and_user
@current_user.attributes = @application_params
@current_user.save!
end
end
app/views/applications/new.html.erb
<%= simple_form_for(@user, url: applications_path, method: :post, html: { novalidate: false}) do |f| %>
<p>(*) Indicates required field</p>
<%= render :partial => 'shared/error_messages', :locals => { :target => @user } %>
<%= f.simple_fields_for :new_application do |ff| %>
<%= ff.input :name , label: 'Name:'%>
<% end %>
<%= f.input :username, required: true, label: 'Username:' %>
<%= f.input :password, required: true, label: 'Password:' %>
<% end %>
That’s it I hope you learnt stuff, regards
H.
No Comments