0

我想在用户完成锻炼后更改用户表中的用户锻炼 ID。我不知道该怎么做。以下是我试图解决这个问题的两种方法。

尝试 1:在控制器中放置一条 if 语句,当 true 增加用户的锻炼 ID 时 - 问题是 if 语句仅在条件已经为 true 时通过,因此用户需要在锻炼结束后尝试完成额外的锻炼完全的。

例子:

def create
    @completed_set = CompletedSet.new(params[:completed_set])

    if @totalExercisesInWorkout.included_in?(@completedExercises) == true
      raise "it worked!"
    end

    respond_to do |format|
      if @completed_set.save
        format.html { redirect_to profile_path, notice: 'Successfully completed set.' }
        format.json { render json: @completed_set, status: :created, location: @completed_set }
      else
        format.html { render action: "new" }
        format.json { render json: @completed_set.errors, status: :unprocessable_entity }
      end
    end
  end

尝试 2在模型中使用after_save回调。- 这不起作用,因为我无法访问模型中的会话信息,所以我不知道用户是什么,他们的锻炼 ID 是什么,以及他们是否完成了锻炼。

这个问题必须有一个简单的解决方案,但我完全被难住了!

谢谢!

编辑:

当具有锻炼的锻炼ID的数组与用户的已完成集锻炼身体的数组匹配时,锻炼就完成了。因此,当以下代码为真时:

@totalExercisesInWorkout.included_in?(@completedExercises)

。包括?是 Array 类的扩展,如果第二个数组包含第一个数组中的所有值,则仅返回 true。

锻炼has_many练习 当用户“完成”锻炼时,该锻炼和相关信息(例如 user_id、锻炼 ID 等)存储在 completed_set 表中。

在我的方法中,application_controller我有一种initialize_vars方法可以找到我需要了解的有关用户及其锻炼的所有信息。这里是:

def initialize_vars
    @workout = Workout.find(current_user.workout_id)
    @user_program = current_user.program
    @user_cycle = Cycle.find(current_user.cycle_id)
    @user_group = Group.find(current_user.group_id)

    @exercise = @workout.exercises
    @workout_exercise = @workout.workout_exercises

    # Array needs to have an exercise for every set in the exercise
    @exercisesInWorkout = @workout.exercises.pluck(:exercise_id)
    # Array of the sets in the users current workout
    @workoutSets = @workout_exercise.pluck(:sets)
    # Array of exercises user has completed in current workout
    @completedExercises = CompletedSet.where(:user_id => current_user.id).pluck(:exercise_id) 
    # Array of exercise_id's in workout times the number of sets for each exercise
    @totalExercisesInWorkout = @exercisesInWorkout.zip(@workoutSets).map { |n1, n2| [n1] * n2 }.flatten

    #Total number of reps a user has completed
    @repsCompleted = CompletedSet.where(:user_id => current_user.id).pluck(:repetitions).sum

    #Total amount of weight a user has lifted
    @weightLifted = CompletedSet.where(:user_id => current_user.id).pluck(:weight).sum
  end

编辑2:

我在这里学到了很多东西。我重构了我的代码。这是它现在的样子。

Class User

def cycle
    Cycle.find(cycle_id)
  end

  def group
    Group.find(group_id)
  end

  def workout
    Workout.find(workout_id)
  end

  def completed_exercise_ids_array(user)
    CompletedSet.where(workout_id: workout_id, user_id: user).pluck(:exercise_id)
  end

  def sets_in_workout_array
    workout.workout_exercises.pluck(:sets)
  end

  def exercises_in_workout_times_sets_array
    workout.workout_exercises.pluck(:exercise_id).zip(sets_in_workout_array).map { |n1, n2| [n1] * n2 }.flatten
  end

  def update_workout_if_needed!
    if exercises_in_workout_times_sets_array.included_in?(completed_exercise_ids_array)
      self.workout.id = self.workout.next_workout_id
      save!
    end
  end

# Methods for progress area
  def total_reps_completed(user)
    CompletedSet.where(user_id: user).sum(:repetitions)
  end

  def total_weight_lifted(user)
    CompletedSet.where(user_id: user).sum(:weight)
  end

还有我的 application_controller

class ApplicationController 

# Application wide instance variables go here. Just don't forget to call initialize_vars in the controllers you want to call these variables in.
  def initialize_vars
    @user_workout = current_user.workout
    @user_cycle = current_user.cycle
    @user_group = current_user.group

    @exercise = @user_workout.exercises

    # Array of the sets in the users current workout
    @workoutSets = current_user.sets_in_workout_array

    # Array of exercises user has completed in current workout
    @completedExercises = current_user.completed_exercise_ids_array(current_user) 

    # Array of exercise_id's in workout times the number of sets for each exercise
    @totalExercisesInWorkout = current_user.exercises_in_workout_times_sets_array

  end

我将一些逻辑移至 profile_controller

4

1 回答 1

1

CompletedSet的after_create回调将是最好的地方:

class CompletedSet < ActiveRecord::Base
  belongs_to :user
  belongs_to :workout
  belongs_to :exercise

  after_create :update_user_workout

  def update_user_workout
    user.update_workout_if_needed!
  end
end

class User < ActiveRecord::Base
  has_many :completed_sets
  belongs_to :workout

  def completed_exercise_ids
    completed_sets.where(workout_id: workout_id).pluck(:exercise_id)
  end

  def update_workout_if_needed!
    if completed_exercise_ids.included_in?(workout.workout_exercises.pluck(:exercise_id))
      self.workout = Workout.next(workout)
      save!
    end
  end
end

class Workout < ActiveRecord::Base
  has_many :workout_exercises
  has_many :exercises, through: :workout_exercises

  # some logic to determine the next workout - modify as needed
  def self.next(workout)
    where("workouts.sequence > ?", workout.sequence).order(:sequence).first
  end
end

此解决方案假定您已将 与current_user控制器操作中的 CompletedSet相关联create(我没有看到):

def create
  @completed_set = current_user.completed_sets.build(params[:completed_set])
  ...
于 2013-05-20T21:19:44.827 回答