簡體   English   中英

如何在無循環依賴的情況下使用Think Sphinx在Rails 5中索引多態(STI)模型?

[英]How do I index polymorphic (STI) models in Rails 5 with Thinking Sphinx without a circular dependency?

我正在使用Sphinx 2.2.11-id64-release (95ae9a6)Sphinx 2.2.11-id64-release (95ae9a6) thinking_sphinx v 4.0.0集成對rails 5.1.4應用程序的簡單索引搜索

預期行為:

提交新搜索時,我希望看到一個空數組[]或一組搜索結果。

實際行為:

當我從視圖層提交帶有空參數的新搜索並嘗試通過控制器動作中的binding.pry訪問ThinkingSphinx :: Search對象時,rails會拋出ActionView::Template::Error (Circular dependency detected while autoloading constant StudentLesson)

[1] pry(main)> ThinkingSphinx.search ''
=> [#<ThinkingSphinx::Search:0x2b0925399e10>
[2] pry(main)> _.inspect
RuntimeError: Circular dependency detected while autoloading constant StudentLesson
from /home/kf/.rvm/gems/ruby-2.4.3@crm/gems/activesupport-5.1.6/lib/active_support/dependencies.rb:509:in `load_missing_constant'
[3] pry(main)>

代碼段:

class Lesson < ApplicationRecord
  LESSON_TYPES = {
    'StudentLesson': StudentLesson,
    'ProfessionalLesson': ProfessionalLesson
  }.freeze
end

class StudentLesson < Lesson
  after_save ThinkingSphinx::RealTime.callback_for(:student_lesson)
end

class ProfessionalLesson < Lesson
  after_save ThinkingSphinx::RealTime.callback_for(:professional_lesson)
end
# app/indices/student_lesson_index.rb
ThinkingSphinx::Index.define :student_lesson, with: :real_time do
  indexes name, sortable: true
end

# app/indices/professional_lesson_index.rb
ThinkingSphinx::Index.define :professional_lesson, with: :real_time do
  indexes name, sortable: true
end
class SearchesController < ApplicationController
  def index
    @results = []
  end

  def create
    @results = ThinkingSphinx.search(params[:search])
    render :index
  end
end
<div class="collapse navbar-collapse" id="header-navbar">
   <%= render 'layouts/nav_links' %>
   <%= form_for searches_path do %>
     <%= search_field_tag :search, params[:search] %>
     <%= submit_tag 'Search', name: nil, method: :get %>
   <% end %>
 </div>

這是dev.sphinx.conf

indexer
{
}

searchd
{
  listen = 127.0.0.1:9306:mysql41
  log = /home/myapp/log/development.searchd.log
  query_log = /home/myapp/log/development.searchd.query.log
  pid_file = /home/myapp/log/development.sphinx.pid
  workers = threads
  binlog_path = /home/myapp/tmp/binlog/development
}

index game_core
{
  type = rt
  path = /home/myapp/db/sphinx/development/game_core
  docinfo = extern
  rt_field = sphinx_internal_class_name
  rt_field = name
  rt_field = summary
  rt_attr_uint = sphinx_deleted
  rt_attr_bigint = sphinx_internal_id
  rt_attr_timestamp = created_at
  rt_attr_timestamp = updated_at
  rt_attr_string = sphinx_internal_class
  rt_attr_string = name_sort
}

index lesson_core
{
  type = rt
  path = /home/myapp/db/sphinx/development/lesson_core
  docinfo = extern
  rt_field = sphinx_internal_class_name
  rt_field = name
  rt_field = purpose
  rt_field = meta
  rt_field = supplies
  rt_field = activity
  rt_attr_uint = sphinx_deleted
  rt_attr_bigint = sphinx_internal_id
  rt_attr_timestamp = created_at
  rt_attr_timestamp = updated_at
  rt_attr_string = sphinx_internal_class
  rt_attr_string = name_sort
}

index protocol_core
{
  type = rt
  path = /home/myapp/db/sphinx/development/protocol_core
  docinfo = extern
  rt_field = sphinx_internal_class_name
  rt_field = name
  rt_field = description
  rt_attr_uint = sphinx_deleted
  rt_attr_bigint = sphinx_internal_id
  rt_attr_timestamp = created_at
  rt_attr_timestamp = updated_at
  rt_attr_string = sphinx_internal_class
  rt_attr_string = name_sort
}

index resource_page_core
{
  type = rt
  path = /home/myapp/db/sphinx/development/resource_page_core
  docinfo = extern
  rt_field = sphinx_internal_class_name
  rt_field = header
  rt_field = content
  rt_attr_uint = sphinx_deleted
  rt_attr_bigint = sphinx_internal_id
  rt_attr_timestamp = created_at
  rt_attr_timestamp = updated_at
  rt_attr_string = sphinx_internal_class
  rt_attr_string = header_sort
}

index game
{
  type = distributed
  local = game_core
}

index lesson
{
  type = distributed
  local = lesson_core
}

index protocol
{
  type = distributed
  local = protocol_core
}

index resource_page
{
  type = distributed
  local = resource_page_core
}

我認為這里的問題與Think Sphinx沒有直接關系-只是錯誤,因為由於模型中的循環依賴關系,它無法加載搜索結果-特別是LESSON_TYPES常量:

  • Thinking Sphinx進行了搜索調用,並且在其結果集中它至少具有一個StudentLesson實例,因此需要加載該模型。
  • 加載StudentLesson發現其對Lesson依賴關系(作為子類)。
  • 正在加載Lesson可以找到其對StudentLessonProfessionalLesson依賴關系(作為對常量的引用)。
  • 因此,試圖再次加載StudentLesson ,從而導致無限循環的依賴關系。

(FWIW我只是使用您提供的模型代碼在測試Rails應用程序中確認了此行為,而沒有涉及TS:我需要在控制台中運行的只是StudentLesson.first 。)

您有2個類都繼承一個常量定義,這看起來很麻煩。

嘗試將此常量定義移至初始化程序:

LESSON_TYPES = {
    'StudentLesson': StudentLesson,
    'ProfessionalLesson': ProfessionalLesson
  }.freeze

解決方案實際上是在注釋線程中找到的spring仍然未解決的問題,可通過初始化require_dependency 'lesson' ->來解決,該問題我實際上已經在初始化程序中有了,但將其移至已解決的Rails.application.config.to_prepare塊中重新加載問題以及與獅身人面像相關的症狀。

暫無
暫無

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

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