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

在@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) 

在创建Habit&Goal实例时,您的代码不会检查可能的错误,并且很可能是一个简单的错误会阻止validation,从而阻止数据库中的持久性。 即

  @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('
').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('
')" end