2015-10-28 86 views
1

A workout has_many movementsRails 4 dynamic has_many

一個result belongs_to的一個userworkout和可選modified_workout

result型號:

belongs_to :user 
belongs_to :workout 
has_many :movements, through: :workout 
belongs_to :modified_workout, class_name: "Workout" 

現在我user型號:

has_many :workouts, through: :results 
has_many :movements, through: :workouts 

不過,我想結合modified_workout進入userhas_many :movements。如果存在modified_workout關係,我只想返回那些movementsbelong_tomodified_workoutMovementsbelong_toworkout應該不是被退回。如果modified_workout關係不存在(即,modified_workout_id列是null),則返回movements,其屬於workout

喜歡的東西

has_many :movements -> 
    if modified_workout 
    return modified_workout.movements 
    else 
    return workout.movements 

,但作爲對belong_touser所有results運行的scope

+0

這是什麼讓鍛鍊得到修改?常規和修改之間的數據庫列是什麼? –

+0

或者結果是否有兩個鍵? 'modified_workout_id'和'workout_id',兩者都指向'Workout'表格? –

+0

@LannyBose結果有兩個鍵,都指向鍛鍊表。 'workout_id'不能爲null,'modified_workout_id'可以爲null。 –

回答

0

我的做法是,也許過這樣做,它也讓我們到能夠調用直線上升的目標...

User.movements 

我在Workout創造的涵蓋範圍過濾器退出任何已被覆蓋的鍛鍊。

User中,我創建了一個新關聯(original_workouts),它使用該範圍獲得original_movements

最大的缺點是,通過添加兩個活動記錄關聯,它將成爲一個數組,從而阻止後續的範圍設定。

鍛鍊。RB

class Workout 
    has_many :movements 

    has_many :results_as_original, class_name: 'Result', foreign_key: 'workout_id' 
    has_many :results_as_modified, class_name: 'Result', foreign_key: 'modified_workout_id' 

    scope :original_and_not_overridden, -> { 
    joins(:results_as_original).where("results.modified_workout_id IS NULL") 
    } 

result.rb

class Result 
    belongs_to :user 
    belongs_to :workout 
    belongs_to :modified_workout 

user.rb

class User 
    has_many :results 
    has_many :original_workouts, ->{ original_and_not_overridden }, 
           through: :results, source: :workouts 
    has_many :modified_workouts, through: results 
    has_many :original_movements, through: :workouts, source: :movements 
    has_many :modified_workout_movements, through: :modified_workouts 

    def movements 
     (original_workout_movements + modified_workout_movements).uniq 
    end 

的另一種方式來定義運動是利用ID的列表來重新查詢。這將返回一個關係並允許進一步範圍確定。潛在的性能損失呢?

class User 
    def movements 
    ids = original_workout_movements.pluck(:id) + modified_workout_movements.pluck(:id) 
    Movement.where(id: ids) 
    end 
+0

這看起來不錯,謝謝。你認爲修改你的User.movements方法讓SQL數據庫直接查找相關的ID(例如'WHERE id IN(SELECT id FROM ...)或id IN(SELECT id FROM ...)會更有效嗎? )「或類似的東西),因此只執行一個查詢? –

+0

有可能,但它只會是每個用戶一個(或兩個)附加查詢如果您計劃顯示用戶的索引視圖來統計他們的所有移動,這可能會變得昂貴... –

0

我不認爲你需要has_manymovement的關係,因爲您只是訪問鍛鍊或modified_workout的動作。

您可以在result(或在您的user)從那裏你可以訪問運動的東西添加movement方法類似以下內容:

@result=Result.find(id) 
@result.movements() # returns either modified_workout or 
        # workout.movements depending on situation 
or 
@user=User.find(id) 
@user.result.movements() 

而且movements方法看起來像以下:

class Result < ActiveRecord::Base 
    # belong_to and has_many logics goes here 
    belongs_to :user 
    belongs_to :workout 
    belongs_to :modified_workout, class_name: "Workout" 

    def movements 
     unless self.modified_workout.nil? 
      return self.modified_workout.movements 
     else 
      return self.workout.movements 
     end 
    end 
end 

如果這不起作用,那麼巧妙實現多態關聯可能會有所幫助。

+0

如果它是一種實例方法,它應該只是'def movements'。 –

+0

而用戶沒有'modified_workout'。一個'結果'。 –

+0

更新了我的回答,並在帳戶@LannyBose中留言。 – sadaf2605