В моей настройке я хочу отфильтровать 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, тогда он возьмет значение из меню выбора времени starts_at
и ends_at
, используя сегодняшнюю дату (1 октября 2015 г.), и автоматически вычтет из него 8 часов перед выполнением запроса. Как запретить Ransack вычитать смещенные часы?