我的问题如下:如何改进这样的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
我特别在谈论&#39;过滤&#39;范围。在我的事件控制器索引acion我总是调用过滤范围提供&#39;过滤&#39;并且&#39; kind&#39;从params获得适当的事件,但我找不到使用那些丑陋if语句的方法。我的主要目标是让它变得坚固。
答案 0 :(得分:1)
您可以使用switch case使其更具可读性,并将范围块移动到类方法中。
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)
答案 1 :(得分:0)
我倾向于将这些东西移到一个单独的类中,称之为类似EventQuery,并使用filter,kind和user初始化它。
然后根据您可以在控制器中使用的事件模型返回ActiveRelation对象。模型中与过滤相关的所有代码都将移动到那里。
您的控制器代码看起来像
@event_query = EventQuery.new(filter, kind, current_user)
在视图中,您将访问Event Query类中的方法
@event_query.results
另一个注意事项和可能的解决方案,您不需要制作“范围”。返回活动关系的类方法也一样好。
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