2012-12-08 52 views
3

我有一個名爲update_mobile的操作,並且在其中準備了大量用於RABL JSON請求的實例變量。你可以看到,如果請求包含params[:last_updated]參數,那麼我只能得到自那時起已經更新的模型。這似乎違反了「胖模型,瘦控制器」的方法。我怎樣才能重構這個方法?如何重構Rails控制器操作以消除混亂?

def update_mobile 
    @last_updated = params[:last_updated] 
    if @last_updated.nil? 
     @buddies = @user.friends 
     @courses = @user.courses 
     @friendly_schools = @user.friendly_schools 
     @documents = @user.all_notes 
     @instructors = @user.current_instructors 
     @friendships = @user.friendships 
     @questions = @user.current_questions 
     @answers = @user.current_answers 
     @comments = @user.current_comments 
    else 
     @buddies = @user.friends.select{ |user| user.updated_at > @last_updated } 
     @courses = @user.courses.select{ |course| course.updated_at > @last_updated } 
     @friendly_schools = @user.friendly_schools.select{ |school| school.updated_at > @last_updated } 
     @documents = @user.all_notes.select{ |note| note.updated_at > @last_updated } 
     @instructors = @user.current_instructors.select{ |instructor| instructor.updated_at > @last_updated } 
     @friendships = @user.friendships.select{ |friendship| friendship.updated_at > @last_updated } 
     @questions = @user.current_questions.select{ |question| question.updated_at > @last_updated } 
     @answers = @user.current_answers.select{ |answer| answer.updated_at > @last_updated } 
     @comments = @user.current_comments.select{ |comment| comment.updated_at > @last_updated } 
    end 
    end 
+0

因爲關注更新我在鐵軌方面並不擅長。因此,請謹慎使用此建議:您可以在模型「def self.since_latest」中創建一個方法,並使用該方法的不同集合返回一個哈希值:'{:buddies => friends.select {...},courses => ....'。 您也可以傳遞'@ last_updated'並讓模型中的方法選擇返回哪些條目 – yas4891

回答

4

你應該將代碼從你的模型,然後讓你的模型處理1)參數爲nil和使用ActiveRecord有效地查詢數據庫2)。

在你的控制,有這樣的行爲每個變量:

@friends = @user.friends.updated_since(params[:last_updated]) 

(我已經改名@buddies這裏@friends,因爲我們要在命名系統的東西,以保持一致性)

然後,在你Friend模型,定義一個名爲updated_since一個類的方法,做這種邏輯:

class Friend < ActiveRecord::Base 
    def self.updated_since(last_updated) 
    if last_updated.present? 
     where("updated_at > ?", last_updated) 
    else 
     all 
    end 
    end 
end 
+0

像這樣的方法在Rails中是否已經存在?將'updated_since'方法添加到'ActiveRecord :: Base'或所有模型繼承的另一個模塊不是最好嗎? – ardavis

+0

很酷。你的回答意味着我對我的評論並不太遙遠。 – yas4891

+0

@ardavis:沒有,就我所知,Rails中沒有像這樣的方法。事實上,您可以將代碼移到模塊中。 –

0

如果您使用的是rails 4.x,那麼最簡單的方法是通過Concerns。在每個模型中粘貼相同範圍的副本&,而不是複製&,您可以創建一個總體範圍,並將其簡單地包含在需要的模型中。

# my_app/app/models/concerns/updated_since.rb 
module UpdatedSince 
    extend ActiveSupport::Concern 

    module ClassMethods 
    def updated_since(time) 
     if parsed_time = convert_time(time) 
     where("updated_at >= ?", parsed_time) 
     else 
     all 
     end 
    end 

    private 

     def convert_time(time) 
     Time.zone.parse(time) unless time.blank? 
     rescue ArgumentError 
     self.logger.warn "Invalid updated_since time: <#{time}>" 
     nil 
     end 
    end 
end 

包括在相關機型:

class Friend < ActiveRecord::Base 
    include UpdatedSince 
end 

使用它在你的控制器:

@friends = @user.friends.updated_since(params[:last_updated])