在Ruby中组合块

时间:2015-01-07 18:27:17

标签: ruby

我正在配置Algolia搜索Rails。 algoliasearch方法接受包含索引配置设置的块。我们的每个可搜索模型都有公共和私人索引。这些索引的配置是相同的,除了公共索引中的数据仅在公共索引时被索引?方法返回true。我试图找到一种方法,我不能重复为公共索引中的安全索引指定的配置,以便代码更干。我正在考虑将配置提取到Proc并在安全索引和公共索引块中使用该Proc。我无法完成这项工作。有没有人对如何实现这个有任何建议?

algoliasearch index_name: SECURED_INDEX_NAME do
  # Index configuration. I want to extract this so I can reuse it.
  attribute :name

  add_index PUBLIC_INDEX_NAME, if: :public? do
    # Repeat index configuration here.  
  end
end

https://github.com/algolia/algoliasearch-rails#target-multiple-indexes

这是我到目前为止所拥有的。它不起作用。

module Algolia::UserIndexConcern
  extend ActiveSupport::Concern

  included do
    PUBLIC_INDEX_NAME  = "User_Public_#{Rails.env}"
    PRIVATE_INDEX_NAME = "User_Private_#{Rails.env}"

    index_config = build_index_config(index_name: PRIVATE_INDEX_NAME) # Obviously can't call method here but need to?
    algoliasearch index_name: PRIVATE_INDEX_NAME, sanitize: true, force_utf8_encoding: true, &index_config

    private def build_index_config(index_name:)
      Proc.new do
        # =====================
        # Attributes
        # =====================

        # Searchable.

        attribute :name do
          full_name
        end

        attribute :primary_employer do
          primary_employer.try(:name)
        end

        attributesToIndex ['unordered(name)', 'unordered(primary_employer)']

        attributesToHighlight [:name, :primary_employer]

        if index_name == PRIVATE_INDEX_NAME
          index_config = build_index_config(index_name: PUBLIC_INDEX_NAME)
          add_index PUBLIC_INDEX_NAME, &index_config
        end
      end
    end

    private def public?
      !exclude_from_search? && !admin_exclude_from_search?
    end
  end
end

1 个答案:

答案 0 :(得分:3)

Instance_eval是解决这个问题的关键。

  

在接收器(obj)的上下文中计算包含Ruby源代码或给定块的字符串。为了设置上下文,在代码执行时将变量self设置为obj,使代码可以访问obj的实例变量。

PUBLIC_INDEX_NAME  = "User_Public_#{Rails.env}"
PRIVATE_INDEX_NAME = "User_Private_#{Rails.env}"

common_index_attributes = Proc.new do

  # Define search attributes.

end

algoliasearch index_name: PRIVATE_INDEX_NAME, sanitize: true, force_utf8_encoding: true do
  self.instance_eval &common_index_attributes

  add_index PUBLIC_INDEX_NAME, if: :public? do
    self.instance_eval &common_index_attributes
  end
end

private def public?
  # Excluded for brevity
end