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