2

如何将 Sunspotsearch do块中的通用代码重构为可以从多个位置调用的方法?我怀疑这可能更像是一个 Ruby 元编程问题,而不是特定于 Sunspot 的问题,但这里有。

我有一个使用太阳黑子的模型,如下所示:

class Book
  def self.basic_search(params)    
    search do
      # boilerplate...
      facet :category
      paginate page: params[:p], per_page: APP_CONFIG[:results_per_page]

      # bespoke basic_search search code goes here
    end    
  end

  def self.curated_search(params)    
    search do
      # boilerplate...
      facet :category
      paginate page: params[:p], per_page: APP_CONFIG[:results_per_page]

      # bespoke curated_search code goes here
    end    
  end

end

然后我尝试像这样重构代码:

class Book
  def self.basic_search(params)    
    search do
      boilerplate params
      # bespoke basic_search search code goes here
    end    
  end

  def self.curated_search(params)    
    search do
      boilerplate params
      # bespoke curated_search code goes here
    end    
  end

  def self.boilerplate(params)
    facet :category
    paginate page: params[:p], per_page: APP_CONFIG[:results_per_page]
  end

end

由于样板方法被定义为 Book 上的类方法,因此不出所料,这会导致:

undefined method 'boilerplate' for #<Sunspot::DSL::Search:0x007f92b4177a98

我怀疑需要一些使用 of instance_eval,但是对于 Ruby 来说是新手,我不太确定如何应用它。

4

2 回答 2

2

这就是我想出的。

def self.basic_search(params)    
  search do
    boilerplate(self, params)  # here, self is a sunspot search instance

    # bespoke basic_search search code goes here
  end    
end

def self.curated_search(params)    
  search do
    boilerplate(self, params)  # here, self is a sunspot search instance

    # bespoke curated_search code goes here
  end    
end

def self.boilerplate(sunspot, params)
  sunspot.instance_eval do 
    facet :category
    paginate page: params[:p], per_page: APP_CONFIG[:results_per_page]
  end
end
于 2012-10-09T17:19:36.400 回答
0

要解决特定问题,请尝试将其范围限定为调用Book.boilerplate。正如错误消息所暗示的那样,search'do...end块内的内容是在内部Sunspot::DSL::Search而不是内部评估的Book

请参阅以下示例。为可读性而简化Foo->BookBar->Search

带复制的原始方式

class Foo
  def self.bar()
    p 1
  end

  def self.baz()
    p 1
  end
end

去重。请注意,在太阳黑子示例中,最有可能的方法定义挂钩或类似的东西用于定义方法,Book而不是在此处使用硬编码传递。关键是Bar可以调用quuxwhich in Foo

class Foo
  # Following two methods inserted via DSL magic. #Simplified for readability.
  def self.bar
    Bar.bar
  end

  def self.baz
    Bar.baz
  end

  def self.quux()
    p 1
  end
end

class Bar
  def self.bar
    Foo.quux
  end

  def self.baz
    Foo.quux
  end
end

但是,在您的特定情况下,这可能仍然没有达到您想要的效果,因为被评估的参数可能应该在Search而不是Book. 根据search参数缓存的方式,您应该考虑尝试这样的事情。

def self.boilerplate(params)
  search do
    facet :category
    paginate page: params[:p], per_page: APP_CONFIG[:results_per_page]
  end
end
于 2012-10-09T17:12:44.660 回答