Вопрос

I have a Product & Price models, where:

class Product < AR::Base
  has_many :prices # there are several types of prices, e.g. for guests, users et.c.

I want to index and sort products by price values, belonging to this product and exact price_type.

ThinkingSphinx::Index.define :product, with: :active_record do
  indexes name
  indexes k1c
  indexes catalogue_code
  indexes created_at, sortable: true
  indexes prices(:value), as: :price, sortable: true # TODO

  has :category_id
  has :brand_id
  has :kind_cd
  has :price_id
end

After rake ts:rebuild I get that

rake aborted!
NoMethodError: undefined method `type' for nil:NilClass
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/attribute/type.rb:64:in `type_from_database'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/attribute/type.rb:17:in `type'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/attribute.rb:4:in `type'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb:30:in `sphinx_type'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb:18:in `collection_type'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/sql_source.rb:96:in `block in append_presenter_to_attribute_array'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/sql_source.rb:93:in `each'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/sql_source.rb:93:in `append_presenter_to_attribute_array'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/sql_source.rb:132:in `prepare_for_render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/active_record/sql_source.rb:65:in `render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/riddle-1.5.10/lib/riddle/configuration/index.rb:29:in `block in render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/riddle-1.5.10/lib/riddle/configuration/index.rb:29:in `collect'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/riddle-1.5.10/lib/riddle/configuration/index.rb:29:in `render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/core/index.rb:53:in `render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/riddle-1.5.10/lib/riddle/configuration.rb:41:in `block in render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/riddle-1.5.10/lib/riddle/configuration.rb:41:in `collect'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/riddle-1.5.10/lib/riddle/configuration.rb:41:in `render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/configuration.rb:88:in `render'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/configuration.rb:94:in `block in render_to_file'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/configuration.rb:94:in `render_to_file'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/rake_interface.rb:13:in `configure'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/rake_interface.rb:24:in `index'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/gems/thinking-sphinx-3.1.0/lib/thinking_sphinx/tasks.rb:9:in `block (2 levels) in <top (required)>'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/bin/ruby_executable_hooks:15:in `eval'
/home/asiniy/.rvm/gems/ruby-2.1.0@zhivojoffice/bin/ruby_executable_hooks:15:in `<main>'
Tasks: TOP => ts:rebuild => ts:index

Need I write a raw SQL query or there is another method?

UPD

Analogue sql query for get a one price (after that I want to order by price):

SELECT "prices".* FROM "prices" WHERE "prices"."product_id" = $1 AND "prices"."price_type_id" = 1 LIMIT 1

My prices model. Quantity of price_types are about 5 and changes very seldom.

class Price < ActiveRecord::Base
  validates :price_type, :value, :product, presence: true
  validates :price_type, uniqueness: { scope: :product }
  validates :value, numericality: { greater_than: 0.0 }

  belongs_to :price_type
  belongs_to :product
end
Это было полезно?

Решение

There's a couple of things to note here.

Firstly: attributes are a better fit for sorting (they're sortable by their very nature)... but yes, if you want to sort by the minimum price, then you're going to need a SQL snippet for that:

has 'MIN(prices.value)', as: :price, type: :float

You will also need to ensure you're referring to the prices association either in a separate field or attribute, or explicitly in a call to join, to ensure the table is actually part of the joins in the generated SQL query:

join prices

However, the error you're seeing is unrelated to this - it's complaining that it can't determine the type of an attribute because the specified column doesn't exist. I'm pretty certain this is from your price_id attribute, which should probably go through the prices association:

has prices.id, as: :price_ids

Making this change has the added bonus of ensuring the SQL join exists for the prices table, and so you don't need the join prices line in your index definition.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top