如何在多个模型的会话中存储数据?

时间:2015-08-09 20:23:13

标签: ruby-on-rails ruby session model-view-controller

使用help of @blnc,我们可以在其会话中存储用户的目标。然后,一旦他注册,将该目标保存到他的新帐户并从会话中删除。

作为注册过程中的一个额外步骤,我希望用户在注册之前也能养成习惯。

goals_controller

  def create
    if current_user == nil
        # If there is no user, store the goal values to the session
        session[:goal_name] = goal_params[:name]
        session[:goal_deadline] = goal_params[:deadline]
        redirect_to signup_url
    else
        @goal = current_user.goals.build(goal_params)
        if @goal.save
            track_activity @goal
            redirect_to @goal, notice: 'Goal was successfully created'
        else
            flash.now[:danger] = 'Required Field: "Enter Goal"'
            render 'new'
        end
    end

我模仿了存储目标的行为,但它并没有奏效。当用户创建他的目标,然后习惯,然后注册,在看到他的新帐户时,仅存储目标。这种习惯从未存放过。当我在控制台中搜索它时,它甚至不存在。

我做错了什么?

habits_controller

  def create
    if current_user == nil
      # If there is no user, store the goal values to the session.
      session[:habit_committed] = habit_params[:committed => []]
      session[:habit_date_started] = habit_params[:date_started]
      session[:habit_trigger] = habit_params[:trigger]
      session[:habit_action] = habit_params[:action]
      session[:habit_target] = habit_params[:target]
      session[:habit_reward] = habit_params[:reward]
      session[:habit_order] = habit_params[:order]
      redirect_to signup_url
    else
      @habit = current_user.habits.build(habit_params)
      if @habit.conceal == true
        @habit.save_with_current_level
        redirect_to @habit, notice: 'Habit was successfully created'
      elsif
        @habit.save_with_current_level
        track_activity @habit
        redirect_to @habit, notice: 'Habit was successfully created'
      else
        flash.now[:danger] = 'Required Fields: "Committed to", "Started", and "Enter Habit"'
        render 'new'
      end
    end
  end

  def new
    if current_user == nil
      @habit = Habit.new
    else
      @habit = current_user.habits.build
    end
  end

users_controller

  def create
    @user = User.new(user_params)
    if @user.save
      # Grab the session variable at the same time deleting it
      name = session.delete(:goal_name)
      deadline = session.delete(:goal_deadline)
      committed = session.delete(:habit_committed)
      date_started = session.delete(:habit_date_started)
      trigger = session.delete(:habit_trigger)
      action = session.delete(:habit_action)
      target = session.delete(:habit_target)
      reward = session.delete(:habit_reward)      
      #You can make this more complex for error handling
      @user.goals.create(name: name, deadline: deadline)
      @user.habits.create(committed: committed, date_started: date_started, trigger: trigger, action: action, target: target, reward: reward)
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end

在我发布习惯之后,从终端

Started POST "/habits" for 127.0.0.1 at 2015-08-09 16:56:20 -0400
Processing by HabitsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"IWbim9fUlU0Ix43Z+WGpJkKhbhPyM7o0JeZ1KFY1X5ugGukOs6asvRatior0c7vBfmaRiNmKkl9O1bka5Bdrcg==", "habit"=>{"committed"=>["sun", "mon", "tue", "wed", "thu", "fri", "sat", ""], "date_started(2i)"=>"8", "date_started(3i)"=>"9", "date_started(1i)"=>"2015", "trigger"=>"", "action"=>"test", "target"=>"", "reward"=>"", "tag_list"=>"", "conceal"=>"0"}, "button"=>""}
Redirected to http://0.0.0.0:3000/signup
Completed 302 Found in 11ms (ActiveRecord: 0.0ms)


Started GET "/signup" for 127.0.0.1 at 2015-08-09 16:56:21 -0400
Processing by UsersController#new as HTML
  Rendered shared/_error_messages.html.erb (0.1ms)
  Rendered users/new.html.erb within layouts/application (3.8ms)
  Rendered layouts/_header.html.erb (0.4ms)
Completed 200 OK in 1047ms (Views: 1046.2ms | ActiveRecord: 0.0ms)

1 个答案:

答案 0 :(得分:2)

创建习惯时,您的代码不会检查可能的错误。目标实例,并且很可能是一个简单的错误,会阻止验证,从而阻止数据库中的持久性。即

  @user = User.new(user_params)
    if @user.save
      ...
      @user.goals.create(...) # What if it fails ?
      @user.habits.create(...) # What if it fails ?
      @user.send_activation_email
      ...
      redirect_to root_url
    else
      render 'new'
    end

如果注释行失败,您将无法获得任何反馈,因为您重定向到另一个页面。 如果这些行成功(=返回false),它们将保存目标/习惯,但如果它们失败(并返回false),那么该过程的其余部分将正常执行

你应该这样做:

@user = User.new(user_params)
    if @user.save
      ...
      unless @user.goals.create(...) # unless = if not
        # The warnings variable will be used for user notification
        (warnings ||= []) << "Warning ! Goal was not saved because of validation errors"
        # Use Rails logger for administrative detection of errors
        # => (Rails.logger .warning, .error, .info, .debug) will add to the `rails_root/log/#{environment}` log file, depending on the `:log_level` selected in your configuration
        Rails.logger.warn("Warning, auto-creation of Goal for user #{@user.name} on sign_up failed !")
      end
      unless @user.habits.create(...) # What if it fails ?
        (warnings ||= []) << "Warning ! Habit was not saved because of validation errors"
        Rails.logger.warn("Warning, auto-creation of Habit for user #{@user.name} on sign_up failed !")
      end

      @user.send_activation_email
      ...
      flash[:warning] = warnings.join('<br>').html_safe if warnings # Assuming you have some HTML code that renders flash[:warning]
      redirect_to root_url
    else
      render 'new'
    end

当然你也可以说明为什么它使用

这样的东西失败了
unless goal= @user.goals.create(...)
  (warnings ||= []) << "Warning ! Goal was not saved because of validation errors : #{goal.errors.map{|k,v| "#{k} : #{v}"}.join('<br>')"
end