pat / thinking-sphinx

Sphinx/Manticore plugin for ActiveRecord/Rails
http://freelancing-gods.com/thinking-sphinx
MIT License
1.63k stars 469 forks source link

Rails 4.1 NoMethodError: undefined method 'parent' for #<ActiveRecord::Associations::JoinDependency::JoinAssociation:0x0000010e839af0> #783

Closed Loremaster closed 10 years ago

Loremaster commented 10 years ago

I started to upgrade app to Rails 4.1, it's Rails 4.0 now.

Some data:

$ rake ts:rebuild --trace
** Invoke ts:rebuild (first_time)
** Invoke ts:stop (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute ts:stop
searchd is not currently running.
Stopped searchd daemon (pid: ).
** Invoke ts:index (first_time)
** Invoke environment 
** Execute ts:index
Generating configuration to /Users/serj/Projects/gearup/config/development.sphinx.conf
rake aborted!
NoMethodError: undefined method `parent' for #<ActiveRecord::Associations::JoinDependency::JoinAssociation:0x0000010d869d50>
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/filtered_reflection.rb:40:in `block in scope'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency/join_association.rb:52:in `instance_exec'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency/join_association.rb:52:in `block (2 levels) in join_constraints'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency/join_association.rb:48:in `map'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency/join_association.rb:48:in `block in join_constraints'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency/join_association.rb:33:in `reverse_each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency/join_association.rb:33:in `join_constraints'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:161:in `make_constraints'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:167:in `make_outer_joins'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:169:in `block in make_outer_joins'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:169:in `each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:169:in `flat_map'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:169:in `make_outer_joins'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:205:in `block in walk'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:205:in `each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:205:in `flat_map'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:205:in `walk'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:114:in `block in join_constraints'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:112:in `each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:112:in `flat_map'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/associations/join_dependency.rb:112:in `join_constraints'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/relation/query_methods.rb:985:in `build_joins'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/relation/query_methods.rb:838:in `build_arel'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/relation/query_methods.rb:830:in `arel'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/activerecord-4.1.0/lib/active_record/relation.rb:520:in `to_sql'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/sql_builder.rb:11:in `sql_query'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/sql_source.rb:119:in `build_sql_query'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/sql_source.rb:136:in `prepare_for_render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/sql_source.rb:65:in `render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/riddle-1.5.11/lib/riddle/configuration/index.rb:29:in `block in render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/riddle-1.5.11/lib/riddle/configuration/index.rb:29:in `collect'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/riddle-1.5.11/lib/riddle/configuration/index.rb:29:in `render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/core/index.rb:53:in `render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/riddle-1.5.11/lib/riddle/configuration.rb:43:in `block in render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/riddle-1.5.11/lib/riddle/configuration.rb:43:in `collect'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/riddle-1.5.11/lib/riddle/configuration.rb:43:in `render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:90:in `render'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:96:in `block in render_to_file'
/Users/serj/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/open-uri.rb:36:in `open'
/Users/serj/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/open-uri.rb:36:in `open'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:96:in `render_to_file'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/rake_interface.rb:13:in `configure'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/rake_interface.rb:24:in `index'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/tasks.rb:9:in `block (2 levels) in <top (required)>'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:240:in `call'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:240:in `block in execute'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:235:in `each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:235:in `execute'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:179:in `block in invoke_with_call_chain'
/Users/serj/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:172:in `invoke_with_call_chain'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:201:in `block in invoke_prerequisites'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:199:in `each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:199:in `invoke_prerequisites'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:178:in `block in invoke_with_call_chain'
/Users/serj/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:172:in `invoke_with_call_chain'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/task.rb:165:in `invoke'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:150:in `invoke_task'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:106:in `block (2 levels) in top_level'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:106:in `each'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:106:in `block in top_level'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:115:in `run_with_threads'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:100:in `top_level'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:78:in `block in run'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:176:in `standard_exception_handling'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/lib/rake/application.rb:75:in `run'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/gems/rake-10.3.2/bin/rake:33:in `<top (required)>'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/bin/rake:23:in `load'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/bin/rake:23:in `<main>'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/bin/ruby_executable_hooks:15:in `eval'
/Users/serj/.rvm/gems/ruby-2.0.0-p353@gearup/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => ts:rebuild => ts:index

Here is my Gemfile:

source 'http://rubygems.org'

gem 'rails', '4.1.0'

gem 'devise'
gem 'cancancan'
gem 'rails_admin', '0.6.1'
gem 'rails-i18n', '~> 4.0.1'
gem 'carrierwave'
gem 'fog'
gem 'unf'
gem 'haml-rails'
gem 'less-rails'
gem 'jquery-rails'
gem 'bootstrap-datepicker-rails'
gem 'bootstrap_datepicker_tag', '~> 0.1.3'
gem 'font-awesome-sass'
gem 'simple_form', '~> 3.0.1'
gem 'kaminari'
gem 'thin'
gem 'private_pub'
gem 'mini_magick'
gem 'rmagick'
gem 'simple_captcha2', require: 'simple_captcha' 
gem 'google_currency' 
gem 'monetize', github: 'RubyMoney/monetize'
gem 'draper', '~> 1.3.0'
gem 'auto_html'
gem 'awesome_nested_set', '~> 3.0.0.rc.3'
gem 'default_value_for'
gem 'paper_trail', '~> 3'
gem 'therubyracer'
gem 'thor'
gem 'ffaker'
gem 'pg_search'                       
gem 'acts-as-taggable-on', '~> 2.4.1' 
gem 'pluggable_js', '~> 2.0.0'
gem 'impressionist' 
gem 'gon', '~> 4.1.1'
gem 'jquery-star-rating-rails'
gem 'nested-hstore', github: 'kenjione/nested-hstore', branch: 'rails4_fix'
gem 'bootstrap-sass' 
gem 'carmen-rails'
gem 'i18n-tasks', '~> 0.3.11'
gem 'babosa'
gem 'friendly_id', '5.0.4'

# Sphinx.
gem 'mysql2',          '0.3.13', platform: :ruby
gem 'thinking-sphinx', '~> 3.1.1'

# Assets
gem 'sass-rails',   '~> 4.0.3'
gem 'coffee-rails', '~> 4.0.0'
gem 'uglifier', '>= 1.3.0'
gem 'twitter-bootstrap-rails', "~> 2.2.8"
gem 'compass-rails', github: 'Compass/compass-rails', branch: '2-0-stable'
gem 'oily_png'
gem 'bourbon'
gem 'jquery-fileupload-rails', github: 'demiazz/jquery-fileupload-rails'
gem 'bootstrap-wysihtml5-rails'

gem 'rails-observers'
gem 'actionpack-page_caching'
gem 'actionpack-action_caching'
gem 'activerecord-session_store'

gem 'forem', :github => "radar/forem", :branch => "rails4"
gem 'remotipart' 
gem 'chosen-rails'
gem 'whenever', :require => false

group :development do
  gem 'better_errors' 
  gem 'binding_of_caller' 
  gem 'letter_opener' 
  gem 'quiet_assets' 
  gem 'awesome_print' 
  gem 'bullet', '~> 4.9.0' 
  gem 'rails-erd' 
  gem 'hirb'
  gem 'ruby-prof' 
  gem 'capistrano'
  gem 'rvm-capistrano'
  gem 'capistrano-notifier'
  gem 'capistrano_deploy_lock'
end

group :stage, :development do
  gem 'meta_request' 
end

group :development, :stage, :production, :test do
  gem 'delayed_job_active_record', '~> 4.0.1'
  gem "dj_mon", github: 'akshayrawat/dj_mon'
end

group :stage, :production do
  gem 'unicorn'
  gem 'airbrake'
  gem 'rails_12factor'
  gem 'copycat', github: 'Zorros/copycat', branch: 'rails-4'
  gem 'dalli'
end

group :stage, :production, :development do
  gem 'newrelic_rpm'
end

group :test, :development do
  gem 'spork-rails'
  gem 'rspec-rails', "~> 2.14.0"
  gem 'parallel_tests'
  gem 'sys-proctable'
  gem 'jasmine-rails'
  gem 'mocha'
  gem 'colorize' 
end

group :test do
  gem 'poltergeist', '1.5.1'
  gem 'capybara-webkit'
  gem 'capybara'
  gem 'cucumber-rails', require: false
  gem 'guard-cucumber'
  gem 'guard-spork'
  gem 'email_spec'
  gem 'guard-rails-assets'
  gem 'database_cleaner'
  gem 'shoulda-matchers', '~> 2.4.0', require: false
  gem 'selenium-webdriver', '~> 2.39.0'
  gem 'terminal-notifier-guard' 
  gem 'site_prism', '2.6' 
  gem 'factory_girl_rails'
  gem 'capybara-screenshot'
end

gem 'pg'

thinking_sphinx.yml

development: &defaults
  morphology: stem_enru, Soundex, Metaphone
  enable_star: 1
  expand_keywords: 1
  min_infix_len: 2
  max_matches: 500000

test:
  mysql41: <%= ENV['TEST_ENV_NUMBER'].to_i + 9307 %>
  pid_file: <%= File.join(Rails.root, "tmp", "searchd.#{ENV['TEST_ENV_NUMBER']}.pid") %>
  indices_location: <%= File.join(Rails.root, "db", "sphinx", "#{ENV['TEST_ENV_NUMBER']}") %>
  configuration_file: <%= File.join(Rails.root, "config", "test.#{ENV['TEST_ENV_NUMBER']}.sphinx.conf") %>
  binlog_path: <%= File.join(Rails.root, "db", "sphinx", "#{ENV['TEST_ENV_NUMBER']}", "binlog") %>
  <<: *defaults

Any ideas how to fix that? We can't make the upgrade to Rails 4.1, because our project uses TS very heavy. I'm ready to give any additional information that you may need!

Loremaster commented 10 years ago

I've made the research and I found that this error is caused by an index for polymorphic association:

ThinkingSphinx::Index.define :service, with: :active_record do
  userable_models = %w(LegalEntity Individual)

  polymorphs owner.userable, to: userable_models                                                   

  indexes owner.userable.company_name, as: :le_company_name # This line causes trouble
end

Here I also want to mention that field company_name exists only in LegalEntity model. Is it broken? Or do I need to rewrite it somehow?

pat commented 10 years ago

Hi Serj

Thanks for all of these details. I think this is a bug with Rails 4.1, Thinking Sphinx, and polymorphic associations. I'll try to work on a fix soon.

Associations in Rails 4.1 have changed a lot though, so it may not be a quick thing to fix.

Loremaster commented 10 years ago

Thank you, Pat! Hope to see the fix soon!

Fustrate commented 10 years ago

Just wanted to chime in, I encountered the same issue today with indexing into a polymorphic column. The worst part with trying to get a polymorphic relation indexed was having almost no documentation to work off of - I'd write it myself if I understood more of it, but because of this bug I haven't even actually used this feature yet.

I'd also like to get confirmation on this part:

Here I also want to mention that field company_name exists only in LegalEntity model. Is it broken? Or do I need to rewrite it somehow?

Loremaster commented 10 years ago

Any updates about fixing this issue?

pat commented 10 years ago

I've gotten half way to fixing it... hoping to have some time in the next 24 hours that'll get the last of it figured out. The massive changes under the hood in Rails 4.1, associations and SQL generation are certainly a handful.

Loremaster commented 10 years ago

Wow! I am happy to hear that you are working on that!! :+1:

pat commented 10 years ago

Urgh, took a while, but I got there. Try the following:

gem 'thinking-sphinx', '~> 3.1.1',
  :git    => 'git://github.com/pat/thinking-sphinx.git',
  :branch => 'develop',
  :ref    => 'c8f549f689'

And then run bundle update joiner to ensure you're using 0.3.1 of joiner (as that is part of the relevant fix). This should fix polymorphic associations with Rails 4.1. Sorry it took so long!

Fustrate commented 10 years ago

Looks like it's working for me. Thanks!

pat commented 10 years ago

Great! Closing this, but if anyone has further comments/queries, do let me know.