Rails Multi-step form
I'm writing a quiz app with rails 5. I have got a multi-step form for question building.
Models:
class Mcq < ApplicationRecord
attr_accessor :option_count
has_many :options, dependent: :destroy
belongs_to :quiz
accepts_nested_attributes_for :options
validates :question_text, presence: true
end
class Option < ApplicationRecord
belongs_to :mcq, optional: true
validates :option_text, presence: true
end
Schema:
create_table "mcqs", force: :cascade do |t|
t.string "question_text"
t.boolean "required"
t.boolean "multiselect"
t.integer "quiz_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "options", force: :cascade do |t|
t.string "option_text"
t.integer "mcq_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The first page is for question setup and has the following fields:
- Option Count
- Required (Yes / No)
- No of options that can be selected (Single / Multiple)
The second page is for options and has the following fields:
- Question Text
- Nested Form for Options
Controller:
class McqsController < ApplicationController
def new
session[:current_step] ||= 'setup'
session[:mcq_params] ||= {}
@current_step = session[:current_step]
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
if session[:current_step] == 'options'
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
end
end
def create
if params[:previous_button]
session[:current_step] = 'setup'
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'setup'
save_session(params[:mcq])
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'options'
@mcq = Mcq.new(whitelisted_mcq_params)
@mcq.quiz_id = params[:quiz_id]
@quiz = Quiz.find(params[:quiz_id])
if @mcq.save
session[:current_step] = session[:mcq_params] = nil
redirect_to quiz_new_question_path(@mcq.quiz_id)
else
@current_step = session[:current_step]
render :new
end
end
end
private
def whitelisted_mcq_params
params.require(:mcq)
.permit(:question_text, :multiselect, :required, options_attributes: [:option_text])
end
def save_session(mcq_params)
session[:mcq_params][:option_count] = mcq_params[:option_count].to_i
session[:mcq_params][:required] = mcq_params[:required]
session[:mcq_params][:multiselect] = mcq_params[:multiselect]
session[:current_step] = 'options'
end
end
The above solution works, but the code is messy and difficult to understand. I came across this railscasts episode which does something similar in a cleaner way. I've updated my code as follows:
class Mcq < ApplicationRecord
has_many :options, dependent: :destroy
belongs_to :quiz
attr_writer :current_step
attr_accessor :option_count
accepts_nested_attributes_for :options
validates :question_text, presence: true
def current_step
@current_step || steps.first
end
def steps
%w[setup options]
end
def next_step
self.current_step = steps[steps.index(current_step)+1]
end
def previous_step
self.current_step = steps[steps.index(current_step)-1]
end
def last_step?
current_step == steps.last
end
end
class McqsController < ApplicationController
def new
session[:mcq_params] ||= {}
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
@mcq.current_step = session[:mcq_step]
end
def create
@quiz = Quiz.find(params[:quiz_id])
session[:mcq_params].deep_merge!(params[:mcq]) if params[:mcq]
@mcq = Mcq.new(session[:mcq_params])
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
@mcq.quiz_id = params[:quiz_id]
@mcq.current_step = session[:mcq_step]
if params[:previous_button]
@mcq.previous_step
elsif @mcq.last_step?
@mcq.save if @mcq.valid?
else
@mcq.next_step
end
session[:mcq_step] = @mcq.current_step
if @mcq.new_record?
render "new"
else
session[:mcq_step] = session[:mcq_params] = nil
redirect_to edit_quiz_path(@mcq.quiz_id)
end
end
end
But each time the second page is shown, the no of fields for options doubles or in case of invalid entry only the field for question_text is shown. How do I show the options correctly? Should I just go with my first solution? I'm new to rails and don't know much about the best practices.
Edited :
new.html.erb
<div class="sub-heading">Add a Multiple Choice Question:</div>
<%= render "mcq_#{@mcq.current_step}", quiz: @quiz, mcq: @mcq %>
_mcq_setup.html.erb
<div class="form-container">
<%= form_for [quiz, mcq] do |f| %>
<div class="form-row">
<div class="response-count">How many options should the question have?</div>
<%= f.select(:option_count, (2..5)) %>
</div>
<div class="form-row">
<div class="response-count">How many options can be selected?</div>
<div class="option">
<%= f.radio_button :multiselect, 'false', checked: true %>
<%= f.label :multiselect, 'Just One', value: 'false' %>
</div>
<div class="option">
<%= f.radio_button :multiselect, 'true' %>
<%= f.label :multiselect, 'Multiple', value: 'true' %>
</div>
</div>
<div class="form-row">
<div class="response-count">Is the question required?</div>
<div class="option">
<%= f.radio_button :required, 'true', checked: true %>
<%= f.label :required, 'Yes', value: 'true' %>
</div>
<div class="option">
<%= f.radio_button :required, 'false' %>
<%= f.label :required, 'No', value: 'false' %>
</div>
</div>
<%= f.submit "Continue to the Next Step" %>
<% end %>
</div>
_mcq_options.html.erb
<%= form_for [quiz, mcq] do |f| %>
<%= f.label :question_text, 'What is your question?' %>
<%= f.text_field :question_text %>
<%= f.fields_for :options do |option_fields| %>
<%= option_fields.label :option_text, "Option #{option_fields.options[:child_index] + 1}:" %>
<%= option_fields.text_field :option_text %>
<% end %>
<%= f.hidden_field :multiselect %>
<%= f.hidden_field :required %>
<%= f.submit "Add Question" %>
<%= f.submit "Back to previous step", name: 'previous_button' %>
<% end %>
ruby-on-rails forms
add a comment |
I'm writing a quiz app with rails 5. I have got a multi-step form for question building.
Models:
class Mcq < ApplicationRecord
attr_accessor :option_count
has_many :options, dependent: :destroy
belongs_to :quiz
accepts_nested_attributes_for :options
validates :question_text, presence: true
end
class Option < ApplicationRecord
belongs_to :mcq, optional: true
validates :option_text, presence: true
end
Schema:
create_table "mcqs", force: :cascade do |t|
t.string "question_text"
t.boolean "required"
t.boolean "multiselect"
t.integer "quiz_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "options", force: :cascade do |t|
t.string "option_text"
t.integer "mcq_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The first page is for question setup and has the following fields:
- Option Count
- Required (Yes / No)
- No of options that can be selected (Single / Multiple)
The second page is for options and has the following fields:
- Question Text
- Nested Form for Options
Controller:
class McqsController < ApplicationController
def new
session[:current_step] ||= 'setup'
session[:mcq_params] ||= {}
@current_step = session[:current_step]
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
if session[:current_step] == 'options'
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
end
end
def create
if params[:previous_button]
session[:current_step] = 'setup'
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'setup'
save_session(params[:mcq])
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'options'
@mcq = Mcq.new(whitelisted_mcq_params)
@mcq.quiz_id = params[:quiz_id]
@quiz = Quiz.find(params[:quiz_id])
if @mcq.save
session[:current_step] = session[:mcq_params] = nil
redirect_to quiz_new_question_path(@mcq.quiz_id)
else
@current_step = session[:current_step]
render :new
end
end
end
private
def whitelisted_mcq_params
params.require(:mcq)
.permit(:question_text, :multiselect, :required, options_attributes: [:option_text])
end
def save_session(mcq_params)
session[:mcq_params][:option_count] = mcq_params[:option_count].to_i
session[:mcq_params][:required] = mcq_params[:required]
session[:mcq_params][:multiselect] = mcq_params[:multiselect]
session[:current_step] = 'options'
end
end
The above solution works, but the code is messy and difficult to understand. I came across this railscasts episode which does something similar in a cleaner way. I've updated my code as follows:
class Mcq < ApplicationRecord
has_many :options, dependent: :destroy
belongs_to :quiz
attr_writer :current_step
attr_accessor :option_count
accepts_nested_attributes_for :options
validates :question_text, presence: true
def current_step
@current_step || steps.first
end
def steps
%w[setup options]
end
def next_step
self.current_step = steps[steps.index(current_step)+1]
end
def previous_step
self.current_step = steps[steps.index(current_step)-1]
end
def last_step?
current_step == steps.last
end
end
class McqsController < ApplicationController
def new
session[:mcq_params] ||= {}
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
@mcq.current_step = session[:mcq_step]
end
def create
@quiz = Quiz.find(params[:quiz_id])
session[:mcq_params].deep_merge!(params[:mcq]) if params[:mcq]
@mcq = Mcq.new(session[:mcq_params])
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
@mcq.quiz_id = params[:quiz_id]
@mcq.current_step = session[:mcq_step]
if params[:previous_button]
@mcq.previous_step
elsif @mcq.last_step?
@mcq.save if @mcq.valid?
else
@mcq.next_step
end
session[:mcq_step] = @mcq.current_step
if @mcq.new_record?
render "new"
else
session[:mcq_step] = session[:mcq_params] = nil
redirect_to edit_quiz_path(@mcq.quiz_id)
end
end
end
But each time the second page is shown, the no of fields for options doubles or in case of invalid entry only the field for question_text is shown. How do I show the options correctly? Should I just go with my first solution? I'm new to rails and don't know much about the best practices.
Edited :
new.html.erb
<div class="sub-heading">Add a Multiple Choice Question:</div>
<%= render "mcq_#{@mcq.current_step}", quiz: @quiz, mcq: @mcq %>
_mcq_setup.html.erb
<div class="form-container">
<%= form_for [quiz, mcq] do |f| %>
<div class="form-row">
<div class="response-count">How many options should the question have?</div>
<%= f.select(:option_count, (2..5)) %>
</div>
<div class="form-row">
<div class="response-count">How many options can be selected?</div>
<div class="option">
<%= f.radio_button :multiselect, 'false', checked: true %>
<%= f.label :multiselect, 'Just One', value: 'false' %>
</div>
<div class="option">
<%= f.radio_button :multiselect, 'true' %>
<%= f.label :multiselect, 'Multiple', value: 'true' %>
</div>
</div>
<div class="form-row">
<div class="response-count">Is the question required?</div>
<div class="option">
<%= f.radio_button :required, 'true', checked: true %>
<%= f.label :required, 'Yes', value: 'true' %>
</div>
<div class="option">
<%= f.radio_button :required, 'false' %>
<%= f.label :required, 'No', value: 'false' %>
</div>
</div>
<%= f.submit "Continue to the Next Step" %>
<% end %>
</div>
_mcq_options.html.erb
<%= form_for [quiz, mcq] do |f| %>
<%= f.label :question_text, 'What is your question?' %>
<%= f.text_field :question_text %>
<%= f.fields_for :options do |option_fields| %>
<%= option_fields.label :option_text, "Option #{option_fields.options[:child_index] + 1}:" %>
<%= option_fields.text_field :option_text %>
<% end %>
<%= f.hidden_field :multiselect %>
<%= f.hidden_field :required %>
<%= f.submit "Add Question" %>
<%= f.submit "Back to previous step", name: 'previous_button' %>
<% end %>
ruby-on-rails forms
Might be helpful to see the views.
– SteveTurczyn
Oct 16 '16 at 18:45
I've edited the question to add views.
– meris1889
Oct 16 '16 at 22:33
You could always build a front end form using JavaScript or hold the input in a session hash between requests before deleting it after the request has been submitted following the final page of the form.
– user10634479
Nov 13 '18 at 13:35
add a comment |
I'm writing a quiz app with rails 5. I have got a multi-step form for question building.
Models:
class Mcq < ApplicationRecord
attr_accessor :option_count
has_many :options, dependent: :destroy
belongs_to :quiz
accepts_nested_attributes_for :options
validates :question_text, presence: true
end
class Option < ApplicationRecord
belongs_to :mcq, optional: true
validates :option_text, presence: true
end
Schema:
create_table "mcqs", force: :cascade do |t|
t.string "question_text"
t.boolean "required"
t.boolean "multiselect"
t.integer "quiz_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "options", force: :cascade do |t|
t.string "option_text"
t.integer "mcq_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The first page is for question setup and has the following fields:
- Option Count
- Required (Yes / No)
- No of options that can be selected (Single / Multiple)
The second page is for options and has the following fields:
- Question Text
- Nested Form for Options
Controller:
class McqsController < ApplicationController
def new
session[:current_step] ||= 'setup'
session[:mcq_params] ||= {}
@current_step = session[:current_step]
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
if session[:current_step] == 'options'
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
end
end
def create
if params[:previous_button]
session[:current_step] = 'setup'
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'setup'
save_session(params[:mcq])
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'options'
@mcq = Mcq.new(whitelisted_mcq_params)
@mcq.quiz_id = params[:quiz_id]
@quiz = Quiz.find(params[:quiz_id])
if @mcq.save
session[:current_step] = session[:mcq_params] = nil
redirect_to quiz_new_question_path(@mcq.quiz_id)
else
@current_step = session[:current_step]
render :new
end
end
end
private
def whitelisted_mcq_params
params.require(:mcq)
.permit(:question_text, :multiselect, :required, options_attributes: [:option_text])
end
def save_session(mcq_params)
session[:mcq_params][:option_count] = mcq_params[:option_count].to_i
session[:mcq_params][:required] = mcq_params[:required]
session[:mcq_params][:multiselect] = mcq_params[:multiselect]
session[:current_step] = 'options'
end
end
The above solution works, but the code is messy and difficult to understand. I came across this railscasts episode which does something similar in a cleaner way. I've updated my code as follows:
class Mcq < ApplicationRecord
has_many :options, dependent: :destroy
belongs_to :quiz
attr_writer :current_step
attr_accessor :option_count
accepts_nested_attributes_for :options
validates :question_text, presence: true
def current_step
@current_step || steps.first
end
def steps
%w[setup options]
end
def next_step
self.current_step = steps[steps.index(current_step)+1]
end
def previous_step
self.current_step = steps[steps.index(current_step)-1]
end
def last_step?
current_step == steps.last
end
end
class McqsController < ApplicationController
def new
session[:mcq_params] ||= {}
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
@mcq.current_step = session[:mcq_step]
end
def create
@quiz = Quiz.find(params[:quiz_id])
session[:mcq_params].deep_merge!(params[:mcq]) if params[:mcq]
@mcq = Mcq.new(session[:mcq_params])
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
@mcq.quiz_id = params[:quiz_id]
@mcq.current_step = session[:mcq_step]
if params[:previous_button]
@mcq.previous_step
elsif @mcq.last_step?
@mcq.save if @mcq.valid?
else
@mcq.next_step
end
session[:mcq_step] = @mcq.current_step
if @mcq.new_record?
render "new"
else
session[:mcq_step] = session[:mcq_params] = nil
redirect_to edit_quiz_path(@mcq.quiz_id)
end
end
end
But each time the second page is shown, the no of fields for options doubles or in case of invalid entry only the field for question_text is shown. How do I show the options correctly? Should I just go with my first solution? I'm new to rails and don't know much about the best practices.
Edited :
new.html.erb
<div class="sub-heading">Add a Multiple Choice Question:</div>
<%= render "mcq_#{@mcq.current_step}", quiz: @quiz, mcq: @mcq %>
_mcq_setup.html.erb
<div class="form-container">
<%= form_for [quiz, mcq] do |f| %>
<div class="form-row">
<div class="response-count">How many options should the question have?</div>
<%= f.select(:option_count, (2..5)) %>
</div>
<div class="form-row">
<div class="response-count">How many options can be selected?</div>
<div class="option">
<%= f.radio_button :multiselect, 'false', checked: true %>
<%= f.label :multiselect, 'Just One', value: 'false' %>
</div>
<div class="option">
<%= f.radio_button :multiselect, 'true' %>
<%= f.label :multiselect, 'Multiple', value: 'true' %>
</div>
</div>
<div class="form-row">
<div class="response-count">Is the question required?</div>
<div class="option">
<%= f.radio_button :required, 'true', checked: true %>
<%= f.label :required, 'Yes', value: 'true' %>
</div>
<div class="option">
<%= f.radio_button :required, 'false' %>
<%= f.label :required, 'No', value: 'false' %>
</div>
</div>
<%= f.submit "Continue to the Next Step" %>
<% end %>
</div>
_mcq_options.html.erb
<%= form_for [quiz, mcq] do |f| %>
<%= f.label :question_text, 'What is your question?' %>
<%= f.text_field :question_text %>
<%= f.fields_for :options do |option_fields| %>
<%= option_fields.label :option_text, "Option #{option_fields.options[:child_index] + 1}:" %>
<%= option_fields.text_field :option_text %>
<% end %>
<%= f.hidden_field :multiselect %>
<%= f.hidden_field :required %>
<%= f.submit "Add Question" %>
<%= f.submit "Back to previous step", name: 'previous_button' %>
<% end %>
ruby-on-rails forms
I'm writing a quiz app with rails 5. I have got a multi-step form for question building.
Models:
class Mcq < ApplicationRecord
attr_accessor :option_count
has_many :options, dependent: :destroy
belongs_to :quiz
accepts_nested_attributes_for :options
validates :question_text, presence: true
end
class Option < ApplicationRecord
belongs_to :mcq, optional: true
validates :option_text, presence: true
end
Schema:
create_table "mcqs", force: :cascade do |t|
t.string "question_text"
t.boolean "required"
t.boolean "multiselect"
t.integer "quiz_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "options", force: :cascade do |t|
t.string "option_text"
t.integer "mcq_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The first page is for question setup and has the following fields:
- Option Count
- Required (Yes / No)
- No of options that can be selected (Single / Multiple)
The second page is for options and has the following fields:
- Question Text
- Nested Form for Options
Controller:
class McqsController < ApplicationController
def new
session[:current_step] ||= 'setup'
session[:mcq_params] ||= {}
@current_step = session[:current_step]
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
if session[:current_step] == 'options'
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
end
end
def create
if params[:previous_button]
session[:current_step] = 'setup'
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'setup'
save_session(params[:mcq])
redirect_to new_quiz_mcq_path
elsif session[:current_step] == 'options'
@mcq = Mcq.new(whitelisted_mcq_params)
@mcq.quiz_id = params[:quiz_id]
@quiz = Quiz.find(params[:quiz_id])
if @mcq.save
session[:current_step] = session[:mcq_params] = nil
redirect_to quiz_new_question_path(@mcq.quiz_id)
else
@current_step = session[:current_step]
render :new
end
end
end
private
def whitelisted_mcq_params
params.require(:mcq)
.permit(:question_text, :multiselect, :required, options_attributes: [:option_text])
end
def save_session(mcq_params)
session[:mcq_params][:option_count] = mcq_params[:option_count].to_i
session[:mcq_params][:required] = mcq_params[:required]
session[:mcq_params][:multiselect] = mcq_params[:multiselect]
session[:current_step] = 'options'
end
end
The above solution works, but the code is messy and difficult to understand. I came across this railscasts episode which does something similar in a cleaner way. I've updated my code as follows:
class Mcq < ApplicationRecord
has_many :options, dependent: :destroy
belongs_to :quiz
attr_writer :current_step
attr_accessor :option_count
accepts_nested_attributes_for :options
validates :question_text, presence: true
def current_step
@current_step || steps.first
end
def steps
%w[setup options]
end
def next_step
self.current_step = steps[steps.index(current_step)+1]
end
def previous_step
self.current_step = steps[steps.index(current_step)-1]
end
def last_step?
current_step == steps.last
end
end
class McqsController < ApplicationController
def new
session[:mcq_params] ||= {}
@quiz = Quiz.find(params[:quiz_id])
@mcq = Mcq.new(session[:mcq_params])
@mcq.current_step = session[:mcq_step]
end
def create
@quiz = Quiz.find(params[:quiz_id])
session[:mcq_params].deep_merge!(params[:mcq]) if params[:mcq]
@mcq = Mcq.new(session[:mcq_params])
@option_count = session[:mcq_params]['option_count']
@option_count.times { @mcq.options.build }
@mcq.quiz_id = params[:quiz_id]
@mcq.current_step = session[:mcq_step]
if params[:previous_button]
@mcq.previous_step
elsif @mcq.last_step?
@mcq.save if @mcq.valid?
else
@mcq.next_step
end
session[:mcq_step] = @mcq.current_step
if @mcq.new_record?
render "new"
else
session[:mcq_step] = session[:mcq_params] = nil
redirect_to edit_quiz_path(@mcq.quiz_id)
end
end
end
But each time the second page is shown, the no of fields for options doubles or in case of invalid entry only the field for question_text is shown. How do I show the options correctly? Should I just go with my first solution? I'm new to rails and don't know much about the best practices.
Edited :
new.html.erb
<div class="sub-heading">Add a Multiple Choice Question:</div>
<%= render "mcq_#{@mcq.current_step}", quiz: @quiz, mcq: @mcq %>
_mcq_setup.html.erb
<div class="form-container">
<%= form_for [quiz, mcq] do |f| %>
<div class="form-row">
<div class="response-count">How many options should the question have?</div>
<%= f.select(:option_count, (2..5)) %>
</div>
<div class="form-row">
<div class="response-count">How many options can be selected?</div>
<div class="option">
<%= f.radio_button :multiselect, 'false', checked: true %>
<%= f.label :multiselect, 'Just One', value: 'false' %>
</div>
<div class="option">
<%= f.radio_button :multiselect, 'true' %>
<%= f.label :multiselect, 'Multiple', value: 'true' %>
</div>
</div>
<div class="form-row">
<div class="response-count">Is the question required?</div>
<div class="option">
<%= f.radio_button :required, 'true', checked: true %>
<%= f.label :required, 'Yes', value: 'true' %>
</div>
<div class="option">
<%= f.radio_button :required, 'false' %>
<%= f.label :required, 'No', value: 'false' %>
</div>
</div>
<%= f.submit "Continue to the Next Step" %>
<% end %>
</div>
_mcq_options.html.erb
<%= form_for [quiz, mcq] do |f| %>
<%= f.label :question_text, 'What is your question?' %>
<%= f.text_field :question_text %>
<%= f.fields_for :options do |option_fields| %>
<%= option_fields.label :option_text, "Option #{option_fields.options[:child_index] + 1}:" %>
<%= option_fields.text_field :option_text %>
<% end %>
<%= f.hidden_field :multiselect %>
<%= f.hidden_field :required %>
<%= f.submit "Add Question" %>
<%= f.submit "Back to previous step", name: 'previous_button' %>
<% end %>
ruby-on-rails forms
ruby-on-rails forms
edited Oct 16 '16 at 19:57
meris1889
asked Oct 16 '16 at 14:07
meris1889meris1889
104
104
Might be helpful to see the views.
– SteveTurczyn
Oct 16 '16 at 18:45
I've edited the question to add views.
– meris1889
Oct 16 '16 at 22:33
You could always build a front end form using JavaScript or hold the input in a session hash between requests before deleting it after the request has been submitted following the final page of the form.
– user10634479
Nov 13 '18 at 13:35
add a comment |
Might be helpful to see the views.
– SteveTurczyn
Oct 16 '16 at 18:45
I've edited the question to add views.
– meris1889
Oct 16 '16 at 22:33
You could always build a front end form using JavaScript or hold the input in a session hash between requests before deleting it after the request has been submitted following the final page of the form.
– user10634479
Nov 13 '18 at 13:35
Might be helpful to see the views.
– SteveTurczyn
Oct 16 '16 at 18:45
Might be helpful to see the views.
– SteveTurczyn
Oct 16 '16 at 18:45
I've edited the question to add views.
– meris1889
Oct 16 '16 at 22:33
I've edited the question to add views.
– meris1889
Oct 16 '16 at 22:33
You could always build a front end form using JavaScript or hold the input in a session hash between requests before deleting it after the request has been submitted following the final page of the form.
– user10634479
Nov 13 '18 at 13:35
You could always build a front end form using JavaScript or hold the input in a session hash between requests before deleting it after the request has been submitted following the final page of the form.
– user10634479
Nov 13 '18 at 13:35
add a comment |
1 Answer
1
active
oldest
votes
You may look in direction of state_machine. By using that you can use your steps as states of state machine and use its ability to define validations that only active for given states (look here in state :first_gear, :second_gear do
) so fields that required on second step will be not required on first. Also, it'll allow you to avoid complex checks for the step you currently on (because the state will be persisted in a model) and will be pretty easy to extend with more steps in a future.
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40071198%2frails-multi-step-form%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You may look in direction of state_machine. By using that you can use your steps as states of state machine and use its ability to define validations that only active for given states (look here in state :first_gear, :second_gear do
) so fields that required on second step will be not required on first. Also, it'll allow you to avoid complex checks for the step you currently on (because the state will be persisted in a model) and will be pretty easy to extend with more steps in a future.
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
add a comment |
You may look in direction of state_machine. By using that you can use your steps as states of state machine and use its ability to define validations that only active for given states (look here in state :first_gear, :second_gear do
) so fields that required on second step will be not required on first. Also, it'll allow you to avoid complex checks for the step you currently on (because the state will be persisted in a model) and will be pretty easy to extend with more steps in a future.
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
add a comment |
You may look in direction of state_machine. By using that you can use your steps as states of state machine and use its ability to define validations that only active for given states (look here in state :first_gear, :second_gear do
) so fields that required on second step will be not required on first. Also, it'll allow you to avoid complex checks for the step you currently on (because the state will be persisted in a model) and will be pretty easy to extend with more steps in a future.
You may look in direction of state_machine. By using that you can use your steps as states of state machine and use its ability to define validations that only active for given states (look here in state :first_gear, :second_gear do
) so fields that required on second step will be not required on first. Also, it'll allow you to avoid complex checks for the step you currently on (because the state will be persisted in a model) and will be pretty easy to extend with more steps in a future.
answered Oct 16 '16 at 20:04
Sergey MoiseevSergey Moiseev
2,73822027
2,73822027
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
add a comment |
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
Thanks, but I would like to do this without using any additional plugins or gems.
– meris1889
Oct 16 '16 at 22:15
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
As long as you have only a few steps, you can enforce the same trick with validations using conditional validations.
– Sergey Moiseev
Oct 16 '16 at 22:20
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40071198%2frails-multi-step-form%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Might be helpful to see the views.
– SteveTurczyn
Oct 16 '16 at 18:45
I've edited the question to add views.
– meris1889
Oct 16 '16 at 22:33
You could always build a front end form using JavaScript or hold the input in a session hash between requests before deleting it after the request has been submitted following the final page of the form.
– user10634479
Nov 13 '18 at 13:35