Rails:改进模型中的 if 语句
Rails: improve if statements in model
我的问题如下:如何改进 rails 模型代码,如下所示:
class Event < ActiveRecord::Base
scope :upcoming, -> { where('date >= ?', Time.now)
.includes(:groups, :creator)
.reorder(date: :asc) }
scope :past, -> { where('date < ?', Time.now)
.includes(:groups, :creator) }
scope :connected, -> (user) {
user_groups_ids = user.groups_teacher.pluck(:id).uniq
joins(:groups).where('groups.id': user_groups_ids).uniq
}
scope :created, -> (user) {
where(user_id: user.id)
}
scope :filtered, -> (args) {
filter = args[:filter]
kind = args[:kind]
if(filter == 'upcoming' && kind == 'connected')
upcoming.connected(args[:user])
elsif(filter == 'upcoming' && kind == 'created')
upcoming.created(args[:user])
elsif(filter == 'past' && kind == 'connected')
past.connected(args[:user])
elsif(filter == 'past' && kind == 'created')
past.created(args[:user])
elsif(filter == 'upcoming')
upcoming
elsif(filter == 'past')
past
else
all
end
}
belongs_to :creator, class_name: "User", foreign_key: "user_id"
has_many :groups, through: :group_events
has_many :group_events
accepts_nested_attributes_for :groups
self.per_page = 5
end
我具体说的是 'filtered' 范围。在我的事件控制器索引 acion 中,我总是从参数中调用提供 'filter' 和 'kind' 的过滤范围来获取正确的事件,但我找不到不使用那些丑陋的 if 语句的方法。我的主要目标是让它变得坚固。
我倾向于将这些东西移到一个单独的 class 中,将其称为 EventQuery 之类的东西,并使用过滤器、种类和用户对其进行初始化。
然后 return 基于事件模型的 ActiveRelation 对象,您随后可以在控制器中使用该对象。您模型中与过滤相关的所有代码都将移到那里。
您的控制器代码如下所示
@event_query = EventQuery.new(filter, kind, current_user)
并且在视图中,您将访问事件查询中的方法 class
@event_query.results
另外一个说明和可能的解决方法,你不需要做'scopes'。一个 class 方法 return 是一个活跃的关系也同样好。
def self.filtered(args)
filter = args[:filter]
kind = args[:kind]
if(filter == 'upcoming' && kind == 'connected')
upcoming.connected(args[:user])
elsif(filter == 'upcoming' && kind == 'created')
upcoming.created(args[:user])
elsif(filter == 'past' && kind == 'connected')
past.connected(args[:user])
elsif(filter == 'past' && kind == 'created')
past.created(args[:user])
elsif(filter == 'upcoming')
upcoming
elsif(filter == 'past')
past
else
all
end
end
您可以使用 switch case 使其更具可读性,并将范围块移动到 class 方法中。
def self.filtered(args)
filter = args[:filter]
kind = args[:kind]
case [filter, kind]
when ['upcoming', 'connected'] then upcoming.connected(args[:user])
when ['upcoming', 'created'] then upcoming.created(args[:user])
when ['past', 'connected'] then past.connected(args[:user])
when ['past', 'created'] then past.created(args[:user])
when ['upcoming', nil] then upcoming
when ['past', nil] then past
else
all
end
end
然后称它为Event.filtered(args)
我的问题如下:如何改进 rails 模型代码,如下所示:
class Event < ActiveRecord::Base
scope :upcoming, -> { where('date >= ?', Time.now)
.includes(:groups, :creator)
.reorder(date: :asc) }
scope :past, -> { where('date < ?', Time.now)
.includes(:groups, :creator) }
scope :connected, -> (user) {
user_groups_ids = user.groups_teacher.pluck(:id).uniq
joins(:groups).where('groups.id': user_groups_ids).uniq
}
scope :created, -> (user) {
where(user_id: user.id)
}
scope :filtered, -> (args) {
filter = args[:filter]
kind = args[:kind]
if(filter == 'upcoming' && kind == 'connected')
upcoming.connected(args[:user])
elsif(filter == 'upcoming' && kind == 'created')
upcoming.created(args[:user])
elsif(filter == 'past' && kind == 'connected')
past.connected(args[:user])
elsif(filter == 'past' && kind == 'created')
past.created(args[:user])
elsif(filter == 'upcoming')
upcoming
elsif(filter == 'past')
past
else
all
end
}
belongs_to :creator, class_name: "User", foreign_key: "user_id"
has_many :groups, through: :group_events
has_many :group_events
accepts_nested_attributes_for :groups
self.per_page = 5
end
我具体说的是 'filtered' 范围。在我的事件控制器索引 acion 中,我总是从参数中调用提供 'filter' 和 'kind' 的过滤范围来获取正确的事件,但我找不到不使用那些丑陋的 if 语句的方法。我的主要目标是让它变得坚固。
我倾向于将这些东西移到一个单独的 class 中,将其称为 EventQuery 之类的东西,并使用过滤器、种类和用户对其进行初始化。
然后 return 基于事件模型的 ActiveRelation 对象,您随后可以在控制器中使用该对象。您模型中与过滤相关的所有代码都将移到那里。
您的控制器代码如下所示
@event_query = EventQuery.new(filter, kind, current_user)
并且在视图中,您将访问事件查询中的方法 class
@event_query.results
另外一个说明和可能的解决方法,你不需要做'scopes'。一个 class 方法 return 是一个活跃的关系也同样好。
def self.filtered(args)
filter = args[:filter]
kind = args[:kind]
if(filter == 'upcoming' && kind == 'connected')
upcoming.connected(args[:user])
elsif(filter == 'upcoming' && kind == 'created')
upcoming.created(args[:user])
elsif(filter == 'past' && kind == 'connected')
past.connected(args[:user])
elsif(filter == 'past' && kind == 'created')
past.created(args[:user])
elsif(filter == 'upcoming')
upcoming
elsif(filter == 'past')
past
else
all
end
end
您可以使用 switch case 使其更具可读性,并将范围块移动到 class 方法中。
def self.filtered(args)
filter = args[:filter]
kind = args[:kind]
case [filter, kind]
when ['upcoming', 'connected'] then upcoming.connected(args[:user])
when ['upcoming', 'created'] then upcoming.created(args[:user])
when ['past', 'connected'] then past.connected(args[:user])
when ['past', 'created'] then past.created(args[:user])
when ['upcoming', nil] then upcoming
when ['past', nil] then past
else
all
end
end
然后称它为Event.filtered(args)