簡體   English   中英

Rails Ransack搜索PG hstore

[英]Rails Ransack search PG hstore

我在Rails4應用中使用Ransack。 我最近在表中添加了PG hstore字段。 在此應用中,用戶可以定義hstore字段的內容(鍵和值)。

如果知道密鑰名稱,我找到了一種使用Ransack搜索hstore字段的方法。 這是一個示例-關鍵是color

ransacker :color do |parent|
  Arel::Nodes::InfixOperation.new('->', parent.table[:data], 'color')
end

然后在視圖中,我使用:

    <td><%= f.label :color_cont, "Color:" %></td>
    <td><%= f.text_field :color_cont %></td>

但是,我不知道用戶將使用什么key

有沒有人想辦法讓Ransack在不知道密鑰的情況下搜索hstore字段?

謝謝您的幫助!

您也許可以直接使用Arel :: Nodes執行此操作,但是您也可以使用在更高版本的Ransack中添加的ransackable_scopes方法。

首先創建一個方法來返回您的hstore_col_name。

然后在hstore列上創建一些使用postgres運算符的作用域。 第一個作用域可用於查找具有key_value_pair的行。 第二個作用域可用於查找具有給定鍵和任何值的行,這也可能會有所幫助。

scope :with_key_value_pair, ->(key,value){where("#{table_name}.#{hstore_col_name} @> '#{key}=>#{value}'")}
scope :with_key, ->(key){where("#{table_name}.#{hstore_col_name} ? :key", :key=>key)}

然后創建一個類方法,該方法將動態返回該hstore列中正在使用的所有當前唯一鍵的數組:

def self.hstore_keys_to_a
  self.connection.execute("SELECT DISTINCT UNNEST(AKEYS(#{hstore_col_name})) from #{table_name}").map(&:values).flatten.uniq
end

由於我沒有找到在一個作用域上使用帶有兩個參數的ransack的任何示例,因此我創建了另一個類方法來動態添加供ransack調用的作用域,以匹配hstore列中當前使用的每個鍵。 也許有一種比通過在作用域名稱中放入一個參數更直接的方法來傳遞兩個參數:

def self.add_hstore_key_scopes do
  hstore_keys_to_a.each do |key|
    define_singleton_method "with_#{key}" do |val|
      with_key_value_pair(key,val)
    end
  end
end

def self.ransackable_scopes(auth_obj=nil)
  hstore_keys_to_a.map{|key| "with_#{key}"} << "with_key"
end

我將靜態“ with_key”作用域附加到ransackable_scopes,以允許選擇搜索具有給定鍵和任何值的行。

然后在搜索表單的rails控制器方法中,在呈現之前調用Model.add_hstore_key_scopes。 這將確保所有最近添加的鍵也為其添加了with _#{key}范圍。

現在,在視圖中,您可以為每個當前使用的鍵渲染部分圖像:

<% Model.hstore_keys_to_a.each do |key| %>
  <%= f.label "with_#{key}" %>
  <%= f.text_field "with_#{key}" %>
<% end %>

如果願意,可以使用另一個字段來搜索具有給定鍵的任意值的行:

<%= f.label "with_key" %>
<%= f.text_field "with_key" %>

我最終在Vehicle模型中這樣做:

if ActsAsTenant.current_tenant.data.present?
  ActsAsTenant.current_tenant.data.each do |key, value|
    ransacker key do |parent|
      Arel::Nodes::InfixOperation.new('->', parent.table[:data], key)
    end
  end
end

在視圖中:

      <% if current_tenant.data.present? %>
          <% current_tenant.data.each do |key, value| %>
              <td><%= f.label key + '_cont', key.capitalize + ":" %></td>
              <td><%= f.text_field key + '_cont' %></td>
          <% end %>
      <% end %>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM