Ruby on Rails:使用Ransack实现按周日期范围筛选列表
实现按日期复选框筛选整周活动列表
看起来你已经搭好了Ransack搜索的基础框架,接下来我们一步步把按日期复选框筛选整周活动的功能补全:
1. 完善控制器逻辑(events_controller.rb)
我们需要在index方法里处理复选框提交的日期参数,把选中的日期转换成对应周的日期范围,再传给Ransack做筛选:
# events_controller.rb def index @q = Event.ransack(params[:q]) # 处理选中的周日期筛选逻辑 if params[:selected_weeks].present? # 将选中的日期字符串转为Date对象,再计算对应周的起止日期 week_ranges = params[:selected_weeks].map do |date_str| target_date = Date.parse(date_str) # 按照学期设置的周起始日(比如周一/周日)计算整周范围 week_start = target_date - target_date.wday + Semester.current.start_dt.wday week_end = week_start + 6 week_start..week_end end # 筛选活动日期落在任意选中周范围内的记录 @q = Event.ransack(event_date_in: week_ranges.flatten) end @events = @q.result(distinct: true) # 加上distinct避免重复数据 # 生成可选的周起始日期列表(保留你原来的逻辑) @weeks = Semester.current.range.select {|w| w.wday == Semester.current.start_dt.wday}.map(&:to_s) end
2. 完善视图的复选框表单(index.html.erb)
在搜索表单里添加日期复选框组,确保选中的日期能正确传递给控制器:
<div class="col-10"> <div class="dates"> <%= search_form_for @q, id: "filters_click", remote: true do |f| %> <!-- 周日期复选框组 --> <div class="week-checkboxes d-flex flex-wrap gap-3"> <% @weeks.each do |week_date| %> <div class="form-check"> <%= check_box_tag 'selected_weeks[]', week_date, params[:selected_weeks]&.include?(week_date), class: 'form-check-input' %> <%= label_tag "selected_weeks_#{week_date}", "周起始:#{week_date}", class: 'form-check-label' %> </div> <% end %> </div> <!-- 可选:添加提交按钮,或者设置点击复选框自动提交 --> <%= f.submit '筛选', class: 'btn btn-primary mt-3' %> <% end %> </div> <!-- 活动列表展示区 --> <div class="events-list mt-4"> <% @events.each do |event| %> <div class="card mb-2"> <div class="card-body"> <h5 class="card-title"><%= event.title %></h5> <p class="card-text">日期:<%= event.event_date.strftime('%Y-%m-%d') %></p> <!-- 其他活动信息按需添加 --> </div> </div> <% end %> </div> </div>
3. 复选框点击自动提交(可选优化)
如果不想每次选完都点提交按钮,可以加一段JS实现点击复选框自动提交表单:
// 可以放在index.html.erb末尾,或者单独的JS文件中 document.addEventListener('DOMContentLoaded', function() { const checkboxes = document.querySelectorAll('.week-checkboxes .form-check-input'); const filterForm = document.getElementById('filters_click'); checkboxes.forEach(box => { box.addEventListener('change', () => filterForm.submit()); }); });
关键细节说明
- 用
selected_weeks[]作为复选框的name,这样多个选中的日期会以数组形式提交到控制器 - 控制器里把每个选中日期转换成对应周的起止范围,再用Ransack的
event_date_in条件筛选匹配的活动 - 确保
Semester.current.range返回的是有效的日期数组,这样@weeks才能正确生成周起始日期选项
内容的提问来源于stack exchange,提问作者degenPenguin
相关产品推荐
相关产品推荐

