ROR + Ransack:根据数字范围(年龄类别)得出的结果

时间:2017-10-10 08:26:15

标签: ruby-on-rails ruby ruby-on-rails-5 ransack

我尝试使用Ransack按年龄类别允许过滤条件。但是,我没有年龄类别作为文章表的一部分,而是作为文章模型中的方法。我引用了其他的

我希望用户能够过滤属于年龄类别的created_at日期的文章,但是,我似乎无法理解为什么根本没有呈现用于选择年龄类别的options_for_select列表。当我在rails控制台中检查时,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

编辑:我通过在&lt;%之后添加=来修复它来修复字段。我现在收到一个新错误,似乎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"...

1 个答案:

答案 0 :(得分:0)

您可以像这样创建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。如果您使用postgres之类的内容,则此答案会假设为MSSQL,然后CASE药水会简化为DATEDIFF(m,#{parent.table[:created_at]},GETDATE())

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