2013-05-20 37 views
0

我想更改用戶workout_id在用戶表中,一旦他完成他的鍛鍊。我無法弄清楚如何做到這一點。以下是我試圖弄清楚的兩種方法。更改用戶表中的字段after_create的記錄滿足條件

嘗試1:如果在控制器中聲明,當真正的增量用戶workout_id把一個 - 問題是if語句只有當條件已經成爲事實經過,因此用戶需要設法完成額外的他的訓練已經完成後進行鍛鍊。

實施例:

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回調在模型中。 - 這不起作用,因爲我無法訪問模型中的會話信息,所以我無法知道用戶是什麼,他們的workout_id是什麼,以及他們是否完成了鍛鍊。

必須有一個簡單的解決方案來解決這個問題,但我完全難住!

謝謝!

編輯:

當與鍛鍊的exercise_id的陣列是由用戶的completed_set exercise_is的陣列相匹配的鍛鍊完成。所以當下列代碼爲真時:

@totalExercisesInWorkout.included_in?(@completedExercises) 

.include_in?是Array類的擴展,如果第二個數組包含第一個數組中的所有值,則該類只會返回true。

鍛鍊has_many練習 當用戶「完成」練習時,該練習和相關信息(如user_id,workout_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

+0

第二種方法似乎是正確的,但我需要更多地瞭解你的模型結構和關聯。你可以發佈更多關於這些信息 - 還有什麼讓鍛鍊「完成」? – PinnyM

+0

當然,現在更新! – Arel

+0

剛剛更新了問題。讓我知道你是否需要更具體的東西。 – Arel

回答

1

after_create回調CompletedSet將是這個最好的地方:

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]) 
    ... 
+0

謝謝!我正在努力實現這一點。 – Arel

+0

什麼是「user.update_workout_if_needed!」應該做的?這種方法是我最困惑的地方。如果我無法獲得用戶數據,我怎麼知道用戶鍛鍊是否需要更新? – Arel

+0

Ohhhh。你可以在一個模型中定義一個方法,並在另一個模型中調用它? – Arel

相關問題