3

我有一个名为的操作update_mobile,其中我正在准备在 RABL JSON 请求中使用的大量实例变量。可以看到,如果请求中包含params[:last_updated]参数,那么我只获取到了此后更新的模型。这似乎违反了“胖模型,瘦控制器”的方法。我怎样才能重构这个方法?

  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
4

2 回答 2

4

您应该将代码移出您的模型并让您的模型处理 1) 参数nil和 2) 使用 ActiveRecord 有效地查询数据库。

在您的控制器中,为每个变量设置如下行:

@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
于 2012-12-08T21:39:16.900 回答
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])
于 2015-01-05T20:05:53.550 回答