1

我正在开发一种让用户逐步完成个人资料的方法,有点像 LinkedIn 和其他人所做的那样。根据他们填写信息的位置,他们将被问及以下问题之一:

  • 报名参加跑步
  • 添加目标
  • 添加头像
  • 感谢您完成他们的个人资料

经过一番思考,我想我会使用state_machine gem 来解决这个问题。

我已经将以下内容添加到user模型中:

state_machine :profile_state, :initial => :needs_to_sign_up_to_a_run, :namespace => 'profile' do
  event :signed_up_for_run do
    transition :needs_to_sign_up_to_a_run => :needs_goal
  end

  event :completed_goal do
    transition :needs_goal => :needs_avatar
  end

  event :provided_avatar do
    transition :needs_avatar => :complete
  end

  state :needs_to_sign_up_to_a_run
  state :needs_goal
  state :needs_avatar
  state :complete
end 

但是,我不确定这是定义eventsor的最佳方式transitions

假设用户可以通过多种方式完成目标/头像/注册(即从他们的用户编辑页面,从右侧面板,作为注册流程的一部分)。因此,在实践中,他们可以在目标之前提供化身,因此这completed_goal是不正确的。

也许我可以使用某种验证来确定状态?也许状态机是完全错误的方法。

我喜欢任何关于解决这个设计问题的建议。

4

2 回答 2

1

我想说 state_machine 在这里不是很好的选择。

我会推荐wicked的逐步向导控制器。

这是一个屏幕投射

于 2013-08-13T12:16:55.300 回答
1

继续上面的,我决定使用 Wicked。我实现它如下:

class CallsToActionController < Wicked::WizardController

  layout false

  steps :sign_up_to_run, :add_goal, :add_avatar, :thank

  def show
    @user = current_user
    case step
    when :sign_up_to_run    
      skip_step if @user.attendances.intended.size > 0
    when :add_goal    
      skip_step if @user.goals.count > 0
    when :add_avatar    
      skip_step unless @user.avatar.file.nil?
    end
    render_wizard
  end

  def update
    @user = current_user
    render_wizard
  end

end

这让我有一系列的部分,app/views/calls_to_action例如add_goal

<div id="goalForm">
  <% @goal = current_user.goals.new %>
  <%= render :partial => 'goals/form' %>
</div>

然后我通过标准控制器处理提交:

class GoalsController < ApplicationController

  def create
    @goal = current_user.goals.new(params[:goal])
    respond_to do |format|
      if @goal.save
        format.js
      else
        format.js { render 'reload' }
      end
    end
  end

end

为了将它们联系在一起,因为我希望向导位于页面内的 div 中,因此 javascript 创建操作如下所示:

$("#call-to-action-response").html("<%= escape_javascript(render :partial => 'goals/success') %>");
$("#call-to-action").load("<%= pre_member_calls_to_action_url(:sign_up_to_run) %>").hide().fadeIn('slow');

希望这对尝试类似事情的人有用!

于 2013-08-13T15:29:25.183 回答