5
\$\begingroup\$

I've implemented just as Ryan Bates suggested in his railscast episode, I've got everything working just right, so here is his approach in the controller :

def new
 session[:order_params] ||= {}
 @order = Order.new(session[:order_params])
 @order.current_step = session[:order_step]
 end
 def create
 session[:order_params].deep_merge!(params[:order]) if params[:order]
 @order = Order.new(session[:order_params])
 @order.current_step = session[:order_step]
 if @order.valid?
 if params[:back_button]
 @order.previous_step
 elsif @order.last_step?
 @order.save if @order.all_valid?
 else
 @order.next_step
 end
 session[:order_step] = @order.current_step
 end
 if @order.new_record?
 render "new"
 else
 session[:order_step] = session[:order_params] = nil
 flash[:notice] = "Order saved!"
 redirect_to @order
 end
 end

I'm ok with new method, but I wonder how can the create method be refactored. He said that he will do an episode how to refactor this in the future but he did not yet.

This was my take on he reactoring (more splitting than refactoring):

 def create
 session[:order_params].deep_merge!(params[:order]) if params[:order]
 @order = Order.new(session[:order_params])
 @order.current_step = session[:order_step]
 process_step
 if @order.new_record?
 render "new"
 else
 session[:order_step] = session[:order_params] = nil
 flash[:notice] = "Order saved!"
 redirect_to @order
 end
 end
def process_step
 if @order.valid?
 if params[:back_button]
 @order.previous_step
 elsif @order.last_step?
 @order.save if @order.all_valid?
 else
 @order.next_step
 end
 session[:order_step] = @order.current_step
 end
end
asked Jan 17, 2014 at 13:11
\$\endgroup\$
1
  • \$\begingroup\$ If you found @BroiSatse's answer helpful, please checkmark it. \$\endgroup\$ Commented Feb 27, 2014 at 20:40

1 Answer 1

6
\$\begingroup\$

I would advise you to look at wicked gem: https://github.com/schneems/wicked.

Using this gem you could write:

include Wicked::Wizard
steps <list_of_your_steps>
def new
 session[:order_id] ||= Order.create.id
end
def show
 @order = Order.find(session[:order_id])
end
def update
 @order = Order.find(session[:order_id])
 @order.assign_attributes(params[:order_params])
 @order.current_step = step
 render_wizard @order
end

It will also separate your forms for each step. To add any step-related action you can use step reader:

def update
 @order = Order.find(session[:order_id])
 @order.assign_attributes(params[:order_params])
 @order.current_step = step
 @order.do_sth if step == :my_step 
 render_wizard @order
end

render_wizard automatically tries to save an object and redirects you to the next step or renders current form depending on a result.

answered Feb 3, 2014 at 10:28
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.