0

I am using high_voltage for create various number of landing pages.

On these pages I have different fields for creation User model. Each form has email and random other fields.

For example:

# views/pages/home1.html.erb
<%= simple_form_for(User.new) do |f| %>
  <%= f.input :email %>
  <%= f.input :first_name %>
  <%= f.button :submit, 'Sign up' %>
<% end %>

# views/pages/home2.html.erb
<%= simple_form_for(User.new) do |f| %>
  <%= f.input :email %>
  <%= f.input :last_name %>
  <%= f.button :submit, 'Sign up' %>
<% end %>

And then I have controller for creating User.

class UserController < ApplicationController
  def create
    @user = User.new(params[:user])

    if @user.save
      redirect_to root_path
    else
      render 'pages/home' # I don't know what should be here
    end
  end
end

The issue is that when someone write wrong email address I want to render correct template but right now I render 'pages/home'.

tomekfranek
  • 6,852
  • 8
  • 45
  • 80

3 Answers3

1

I have answered a similar post here: Render partial from static page

Here is the commit with the code for submitting data and displaying errors: https://github.com/harlow/high_voltage_demo/commit/0cdbca5b0fe898d27df22787498fc7e350e81422

At a high level we'll need a way to know which form was submitted (in order to render the correct form if errors occur). This could be accomplished by creating different actions in the controller.

# config/routes.rb
resources :users, only: [] do
  member do
    post 'short_form'
    post 'long_form'
  end
end

The controller would have two separate actions:

class UserController < ApplicationController
  def short_form
    @user = User.new(short_form_params)
    @user.save
  end

  def long_form
    @user = User.new(long_form_params)
    @user.save
  end

  private

  def short_form_params
    params.permit(:user).require(:first_name, :last_name, :email)
  end

  def long_form_params
    params.permit(:user).require(:field1, :field2, :field3)
  end
end

If you're using a partial for each form, we can inject the User.new as the local variable user in the partial.

# views/pages/home.html.erb
<%= render 'users/short_form', user: User.new %>

# views/users/_short_form.html.erb
<div id="short_form">
  <%= simple_form_for user, remote: true, url: create_user_short_form do |f| %>
    <%= f.input :email %>
    <%= f.input :first_name %>
    <%= f.button :submit, 'Sign up' %>
  <% end %>
</div>

# views/users/_long_form.html.erb
<div id="long_form">
  <%= simple_form_for user, remote: true, url: create_user_long_form do |f| %>
    <%= f.input :email %>
    <%= f.input :last_name %>
    <%= f.button :submit, 'Sign up' %>
  <% end %>
</div>

And the response from the controller will render the .js.erb file and check whether it's valid or not and return the correct response:

# views/users/short_form.js.erb
<% if @user.persisted? %>
   # you could redirect the user with JavaScript
   window.location.href = '<%= root_url %>';
   # or dynamically update the content of the page to let the User know their request was submitted
   $('#short_form').html('Thank you for your submission!'); 
<% else %>
   # this will replace the contents of the Form with the errors in it
   $('#short_form').html('<%= j render 'users/short_form', user: @user %>');
<% end %>

Hope this all makes sense. Let me know if you have any follow-up questions.

Community
  • 1
  • 1
harlow
  • 844
  • 9
  • 17
0

I haven't used high_voltage, but based on the link you gave it appears that it's designed for static pages, not forms like you're using, so I think you're a little outside of its normal use case. There are other gems that support multi-step wizards.

That said, you could probably just store the page information in a hidden field on the form, and in your controller, verify that it's one of the legitimate template options and if so render that, otherwise default to 'pages/home' or return a 403 error or whatever seems most appropriate.

sockmonk
  • 4,195
  • 24
  • 40
-1

Can't you just send current_template to server in hidden field ? if user has validation errors just fetch name of current template and render it!

in views

  <%= form_for @user do %>
    <%= hidden_field_tag : template, __FILE__ %>
  <% end %>

in controller

 if @user.save 
   #redirect 
 else
   render "home/#{params[:template]}"
 end

Just a thought!

Naveed
  • 11,057
  • 2
  • 44
  • 63
  • Agreed, except you also want to verify that params[:template] has a valid template for that page, and not another template from the app that the user isn't normally authorized to view. Hidden fields can be tampered with. – sockmonk Apr 24 '13 at 14:23
  • Yeah, than session could come for rescue :) – Naveed Apr 24 '13 at 14:26
  • @regedarek If you are worried over the hidden field why not try the or http referrer approach Sure that too can be tampered but not that easily. Also I hard to find the logic behind your `else` statement I presume that create action is a post action what it suppose to do is create user why do want to have common logic to redirect them to some page on create action also it hard to make a post request as oppose to get so why is `render 'pages/home'` since as you said you want to render same form when there is validation error – Viren Apr 25 '13 at 10:26
  • I added render 'pages/home' as example. – tomekfranek Apr 25 '13 at 11:56
  • @regedarek not sure what you meant by that but I believe the else part would render the page back since validation error has occurred which has not allowed the object to be saved, dont you feel that make sense – Viren Apr 25 '13 at 16:00