2015-10-06 66 views
1

我正在更新具有ActiveAdmin组件(ActiveAdmin 0.6,Ruby 1.9.3和Rails 3.2)的旧ruby \ rails应用程序。用户已经请求过滤器来搜索给定模型中的所有字段。我不认为这是实际的,因为你不能搜索日期或数字值“a”,所以我已经妥协了只用过滤器搜索文本。ActiveAdmin从动态模型属性中自定义过滤器

查看了ActiveAdmin文档后,您可以使用属性之间的“”创建多个属性的过滤器。所以,如果我想搜索“情况”或“accident_type”属性,我会使用下面的过滤:如果我用这个语法过滤器工作正常

filter :circumstances_or_accident_type, :as => :string, label: "Search All Text Fields" 

我现在想找到所有的字符串\文本属性由我使用此代码(也有这样做的可能是整洁的方式,但它的工作原理)过滤器的属性创建:

xfilter_text = "" 
Notification.columns.each do |xfield| 
    if xfield.type == :string or xfield.type == :text 
    if xfilter_text.length == 0 
     xfilter_text = xfield.name 
    else 
     xfilter_text << "_or_" 
     xfilter_text << xfield.name 
    end 
    end 
end 

我用导致硬编码的值到这给了我下面的过滤器(是的,在该模式中的一些属性):

filter :circumstances_or_accident_type_or_author_type_or_location_or_immediate_action_or_injury_details_or_outcome_type_or_investigation_findings_or_action_to_prevent_recurrence_or_building_or_classification_or_manager_email_or_manager_name_or_current_stage_or_injured_last_name_or_injured_first_name_or_injured_gender_or_injured_address_or_injured_home_telephone_or_injured_work_status_or_injured_job_title_or_injured_working_pattern_or_injured_email_or_riddor_document_or_body_part_or_kind_of_accident_or_injury_type_or_service_or_team_or_defects_or_witness_details_or_location_details_or_hse_reference_number_or_riddor_category_or_address_or_details_of_treatment_or_processor_actions_or_business_unit_or_other_author_type_or_lost_time_details_or_changed_by_or_details_of_hospital_treatment, :as => :string, label: "Search All Text Fields" 

我测试了这一点,它的工作。迄今为止都很好。我可以将它留在这里,但我想确保代码是自我维护的,因此模型中的任何更改都不需要更改自定义过滤器。这是我遇到的问题。我想改变硬编码的属性来使用以某种方式创建过滤器属性的代码的结果。这样的事情:

filter :get_filter, :as => :string, label: "Search All Text Fields" 

def get_filter 
    xfilter_text = "" 
    Notification.columns.each do |xfield| 
    if xfield.type == :string or xfield.type == :text 
     if xfilter_text.length == 0 
     xfilter_text = xfield.name 
     else 
     xfilter_text << "_or_" 
     xfilter_text << xfield.name 
     end 
    end 
    return xfilter 
    end 
end 

我希望我会需要的东西,检查属性返回,否则过滤器将失败。我可以补充说,一旦我得到的代码工作。

感谢任何帮助或建议。

+0

您是否将ActiveAdmin更新至0.6以上?也就是说,您是否在寻找一种搜索或元搜索解决方案? – ahmacleod

+0

不,我不想更新ActiveAdmin。我正在寻找一种解决方案,可以让我随时构建垃圾过滤器。 –

回答

2

我倾向于采用生成查询的混乱业务并将其委托给模型,使用它自己的作用域/类方法。然后,您只需告知MetaSearch/Ransack(取决于您的ActiveAdmin版本)它可以搜索该范围,并且可以将其添加为过滤器。

对于奖励积分,您可以将搜索方法放到您可以纳入任何模型的关注点中。

应用程序/管理/ notifications.rb

filter :containing_text, as: :string, label: 'Text Search:' 

应用程序/模型/ notification.rb里

# for MetaSearch 
# search_methods :containing_text 

# for Ransack 
def self.ransackable_scopes(_opts) 
    [:containing_text] 
end 

# this could be dropped into a concern as-is 
def self.containing_text(query) 
    # select text-type columns 
    cols = columns.select { |c| [:string, :text].include?(c.type) } 

    # generate query fragment 
    fragment = cols.map { |c| "#{ table_name }.#{ c.name } LIKE ?" } 
       .join(' OR ') 

    # execute sanitized query 
    where(fragment, *Array.new(cols.size, "%#{ query }%")) 
end 

###编辑由OP ###

我以前从未用过担心,所以最终找出了如何得到它工作会有:

1)关注路径添加到您的application.rb中

配置/应用。RB

class Application < Rails::Application 
    config.autoload_paths += %W(#{config.root}/app/models/concerns) 
end 

2)添加包括所创建的关注检索的关心和方法调用到notifcation模型

应用程序/模型/ notification.rb里

include Searchable 
search_methods :containing_text 

3) :

/app/models/concerns/searchable.rb

module Searchable 
    extend ActiveSupport::Concern 
    module ClassMethods 
    def self.containing_text(query) 
     # select text-type columns (string and text) 
     cols = columns.select { |c| [:string, :text].include?(c.type) } 
     # generate query fragment 
     fragment = cols.map { |c| "#{ table_name }.#{ c.name } LIKE ?" } 

        .join(' OR ') 
     # execute sanitized query 
     where(fragment, *Array.new(cols.size, "%#{ query }%")) 
    end 
    end 
end 

然后,这似乎工作。我可能应该将可搜索的内容重新命名为更好的内容,但它可行。

+0

我会看看这个,当我有时更新帖子。谢谢。 –

+0

是的,这是一种享受,非常感谢ahmacleod。我不能在一个问题上工作,但我不关心这个问题; o) –

+0

发挥了担忧,并最终得到它的工作。更新该帖子以向其他人显示未使用过的人。 –