ROR + Ransack:根据数字范围(年龄类别)筛选结果

ROR + Ransack:根据数字范围(年龄类别)筛选结果

问题描述:

我试图按照使用Ransack的年龄类别来允许筛选条件。但是,我没有将年龄段作为文章表的一部分,而是作为文章模型中的一种方法。我已经参考了这个ROR + Ransack:根据数字范围(年龄类别)筛选结果

我希望用户能够过滤具有属于年龄段的created_at日期的文章,但是,我似乎无法理解为什么选择年龄段的options_for_select列表根本没有被呈现。当我检查轨道控制台时,div标记之间没有内容。

但是,呈现了options_from_collection_for_select的下拉列表。

模式:

create_table "articles", force: :cascade do |t| 
    t.string "title" 
    t.text "description" 
    t.bigint "user_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 

browse.html.erb

<div class="form-group"> 
    <div class ="row"> 
    <div class="col-md-6 col-sm-6 col-xs-6"> 
     <%= f.select :categories_name_cont, options_from_collection_for_select(Category.all, "id", "name", @q.categories_name_eq), 
                      { :prompt => "Any Category" }, 
                      { class: "form-control" } %> 
    </div> 
    <div class="col-md-6 col-sm-6 col-xs-6"> 
     <% f.select :age_group_in, options_for_select([["more than 1 year ago", "more than 1 year ago"], 
                ["less than 1 year ago", "less than 1 year ago"], 
                ["less than 3 months ago", "less than 3 months ago"], 
                ["less than 1 month ago", "less than 1 month ago"]]), 
                { :prompt => "Any Age Group" }, 
                { class: "form-control" } %> 
    </div> 
    </div> 
</div> 

文章控制器

def browse 
    @q = Article.ransack(params[:q]) 
    @articles_morefilter = @q.result.includes(:categories, :users) 
end 

模型:article.rb

def age_group 
    months_between = Date.today.month - self.created_at.month 
    if months_between > 12 
     "more than 1 year ago" 
    elsif months_between <= 12 
     "less than 1 year ago" 
    elsif months_between <= 3 
     "less than 3 months ago" 
    elsif months_between <= 1 
     "less than 1 month ago" 
    end 
    end 

ransacker :age_group, :formatter => proc {|v| Date.today.month - v.created_at.month} do |parent| 
    parent.table[:created_at] 
end 

编辑:我固定它通过添加=之后<%呈现字段。我现在正在得到一个新的错误,似乎Ransacker语法存在问题。

PG::InvalidDatetimeFormat: ERROR: invalid input syntax for type timestamp: "less than 1 month ago" 
LINE 1: ...name" ILIKE '%1%' AND "articles"."created_at" IN ('less than... 

当我测试改变parent.table[:created_at]parent.table[:age_group],我得到这个错误,而不是:

PG::UndefinedColumn: ERROR: column articles.age_group does not exist 
LINE 1: ...ry_id" WHERE ("categories"."name" ILIKE '%3%' AND "articles"... 
+0

你忘了'='(等号)''应该是' '。 ''ransacker'可能还有其他问题,但这就是为什么下拉不能渲染。 – engineersmnky

+0

@engineersmnky,这是粗心的我。是的,我的ransacker语法存在问题,因为我现在在单击提交后出现上述错误。 – doyz

+0

是的,我认为,但我认为你应该考虑一下你的逻辑。例如,您希望“months_between”大于12的时间点以及您如何期望第三个和第四个条件适用?现在'months_between'的最大范围是0-11(因为DateTime#month将返回1-12),第二个条件是始终为真的 engineersmnky

您可以创建一个ransacker像这样

class Article < ApplicationRecord 

    ransacker :age_group do |parent| 
    query= <<-SQL 
     CASE ((DATE_PART('year', CURRENT_DATE) - DATE_PART('year', #{parent.table[:created_at].to_sql})) * 12 + 
      (DATE_PART('month', CURRENT_DATE) - DATE_PART('month', #{parent.table[:created_at].to_sql}))) 
     WHEN 0,1 THEN "less than 1 month ago" 
     WHEN 2,3 THEN "less than 3 months ago" 
     WHEN 4,5,6,7,8,9,10,11,12 THEN "less than 1 year ago" 
     ELSE "more than 1 year ago" 
     END 
    SQL 
    Arel.sql(query) 
    end 

,然后在视图中更改:age_group_in:age_group_eq。如果您使用类似MSSQL之类的东西,则此答案假定为postgres,那么CASE药水简化为DATEDIFF(m,#{parent.table[:created_at]},GETDATE())

这种缺乏日常的准确性,但我认为这是为您的使用足够接近

+0

我得到2错误:1)语法错误:意外的输入结束,2(在编辑器本身的EOF之前的任何地方都找不到字符串“SQL” – doyz

+0

@diana是否确实使用了我发布的内容,包括'Arel.sql(query)'之前的SQL'?在[这个Gist](https://repl.it/MZUM/1) – engineersmnky

+0

是的,它可以正常工作。现在,我复制并粘贴后,但奇怪的是,正在发生...... https://screenshots.firefox。 com/qYIxobvqy3jy49D8/ide.c9.io,我现在得到一个ActiveRecord :: StatementInvalid错误 - > PG :: SyntaxError:ERROR:语法错误处于或接近“Arel” LINE 1:... year',CURRENT_DATE) - DATE_PART('year',# doyz