在我的设置中,我想使用选择菜单按Schedule
,Activity
,City
,Date
和Starting Time
过滤End Time
。
我已经与Ransack合作了:
# db
create_table "schedules", force: :cascade do |t|
t.integer "city_id"
t.integer "activity_id"
t.datetime "starts_at"
t.datetime "ends_at"
...
end
# Schedule model
scope :six_hours_from_now, -> { where('starts_at >= ?', Time.zone.now + 6.hours) }
ransacker :start_date, type: :date do
Arel.sql('starts_at::date') # filter only the date from starts_at attribute
end
ransacker :start_time, type: :time do
Arel.sql('starts_at::time') # filter only the time from starts_at attribute
end
ransacker :end_time, type: :time do
Arel.sql('ends_at::time') # filter only the time from ends_at attribute
end
# Schedule controller
def index
@q = Schedule.ransack(params[:q])
@q.sorts = ['starts_at asc', 'ends_at asc'] if @q.sorts.empty?
@schedules = @q.result.six_hours_from_now
end
# view
<%= search_form_for @q do |f| %>
<%= f.collection_select :activity_id_eq, @activities, :id, :name, { include_blank: 'All' } %>
<%= f.collection_select :city_id_eq, @cities, :id, :name, { include_blank: 'All' } %>
<%= f.select :start_date_eq, options_for_select([
['Today', Time.zone.today],
['Tomorrow', Time.zone.tomorrow],
[(Time.zone.today + 2).strftime("%d %b"), Time.zone.today + 2],
[(Time.zone.today + 3).strftime("%d %b"), Time.zone.today + 3],
[(Time.zone.today + 4).strftime("%d %b"), Time.zone.today + 4],
[(Time.zone.today + 5).strftime("%d %b"), Time.zone.today + 5],
[(Time.zone.today + 6).strftime("%d %b"), Time.zone.today + 6]
], @q.start_date_eq), { include_blank: true } %>
<%= f.time_select :start_time_gteq, ampm: true, default: { hour: '07' } %>
<%= f.time_select :end_time_lteq, ampm: true, default: { hour: '23', minute: '45' } %>
<%= f.submit "Filter" %>
<% end %>
不幸的是,当我输入一些代码来处理时区时,过滤器不再起作用了:
# application.rb
default settings, no changes
# application_controller.rb
before_filter :set_time_zone
def set_time_zone
if current_user
Time.zone = current_user.time_zone
elsif current_admin
Time.zone = current_admin.time_zone
end
end
如果我只过滤城市,我收到了这个问题:
SELECT "schedules".*
FROM "schedules"
WHERE (
"schedules"."city_id" = 6 AND
starts_at::time >= '2015-09-30 23:00:00.000000' AND
ends_at::time <= '2015-10-01 15:45:00.000000'
) AND (
starts_at >= '2015-10-01 20:52:39.866880'
) ORDER BY "schedules"."starts_at" ASC, "schedules"."ends_at" ASC`
基本上,如果用户的时区为GMT + 8,那么它将使用今天日期(2015年10月1日)的starts_at
和ends_at
时间选择菜单中的值,并自动减去8小时在运行查询之前。如何防止Ransack减去偏移小时数?
答案 0 :(得分:0)
显然,根据我的时区自动减去8小时的sql查询是预期的行为和正确的事情。
我没有在没有任何日期的情况下过滤数据,而是从日期选择中删除了空白选项,并确保显示的默认计划被过滤到明天的日期,而不是显示所有日程表。这样,用户必须在过滤日程表之前先选择日期。
我必须从时间选择中修改传入的参数,因此在将所有参数传递给Ransack之前,它使用日期选择中的参数。
日程安排模型:
# Delete the custom Ransack methods as we don't need them anymore:
ransacker :start_date, type: :date ...
ransacker :start_time, type: :time ...
ransacker :end_time, type: :time ...
# ...and add these scopes:
scope :sort_by_datetime_asc, -> { order(:starts_at, :ends_at) }
def self.only_tomorrow
where('starts_at BETWEEN ? AND ?', Time.zone.tomorrow.beginning_of_day, Time.zone.tomorrow.end_of_day)
end
日程管理员:
params[:q] = {} unless params[:q]
# Copies the date params from date select to replace the date params from the time select menu.
if params["start_date"].present?
date = Time.zone.parse(params["start_date"])
year = date.strftime("%Y")
month = date.strftime("%m")
day = date.strftime("%e")
params[:q]["starts_at_gteq(1i)"] = year
params[:q]["starts_at_gteq(2i)"] = month
params[:q]["starts_at_gteq(3i)"] = day
params[:q]["ends_at_lteq(1i)"] = year
params[:q]["ends_at_lteq(2i)"] = month
params[:q]["ends_at_lteq(3i)"] = day
end
@q = Schedule.ransack(params[:q])
if params[:q].present?
@schedules = @q.result
else
@schedules = Schedule.only_tomorrow
end
@schedules = @schedules.six_hours_from_now.sort_by_datetime_asc
Schedule #index view:
<%= select_tag "start_date", options_for_select([...], selected: default_date_select) %>
<%= f.time_select :starts_at_gteq ...
<%= f.time_select :ends_at_lteq ...
计划助手:
# Show selected date for Schedule's date filter.
def default_date_select
if params["start_date"].present?
params["start_date"]
else
['Tomorrow', Time.zone.tomorrow]
end
end