I am currently struggling with building up a multi step form where every step creates a model instance.
In this case I have 3 models:
- UserPlan
- Connection
- GameDashboard
Since the association is like that:
An user
has an user_plan
A connection
belongs to an user_plan
A game_dashboard
belongs to a connection
I would like to create a wizard to allow the current_user to create a game_dashboard going through a multi-step form where he is also creating connection and user_plan instance.
For this purpose I looked at Wicked gem and I started creating the logic from game_dashboard (which is the last). As soon as I had to face with form generating I felt like maybe starting from the bottom was not the better solution.
That’s why I am here to ask for help:
What would be the better way to implement this wizard? Starting from the bottom (game_dashboard) or starting from the top (use_plan)?
Since I’m not asking help for code at the moment I didn’t write any controller’s or model’s logic, in case it would be helpful to someone I will put it!
Thanks a lot
CodePudding user response:
The simplest way would be to rely on the standard MVC pattern of Rails.
Just use the create
and update
controller methods to link to the next model's form (instead of to a show
or index
view)
E.g.
class UserPlansController < ApplicationController
...
def create
if @user_plan = UserPlan.create(user_plan_params)
# the next step in the form wizard process:
redirect_to new_connection_path(user_id: current_user, user_plan_id: @user_plan.reload.id)
else
@user_plan = UserPlan.new(user: current_user)
render :new
end
end
...
# something similar for #update action
end
For routes, you have two options:
You could nest everything:
# routes.rb
resources :user do
resources :user_plan do
resources :connection do
resources : game_dashboard
end
end
end
Pro:
This would make setting your associations in your controllers easier because all your routes would have what you need. E.g.:
/users/:user_id/user_plans/:user_plan_id/connections/:connection_id/game_dashboards/:game_dashboard_id
Con:
Your routes and link helpers would be very long and intense towards the "bottom". E.g.
game_dashboard_connection_user_plan_user_path(:user_id, :user_plan_id, :connection_id, :game_dashboard)
You could just manually link your wizard "steps" together
Pro:
The URLs and helpers aren't so crazy. E.g.
new_connection_path(user_plan_id: @user_plan.id)
With one meaningful URL variable: user_plan_id=1
, you can look up everything upstream. e.g.:
@user_plan = UserPlan.find(params['user_plan_id'])
@user = @user_plan.user
Con:
(not much of a "con" because you probably wind up doing this anyway)
If you need to display information about "parent" records, you have to perform model lookups in your controllers first:
class GameDashboardController < ApplicationController
# e.g. URL: /game_dashboards/new?connection_id=1
def new
@connection = Connection.find(params['connection_id'])
@user_plan = @connection.user_plan
@user = @user_plan.user
@game_dashboard = GameDashboard.new(connection: @connection)
end
end