Thinking Sphinx indexer condition - ruby-on-rails

My models:
class Item < ActiveRecord::Base
belongs_to :group
scope :able, ->{joins(:group).where(:groups => {:disabled => [nil,false]}).order("position")}
end
class Group < ActiveRecord::Base
has_many :items
scope :able, ->{ where(disabled: [false,nil]).order('position') }
end
My item_index.rb
ThinkingSphinx::Index.define :item, :with => :active_record do
indexes title
# attributes
has created_at, updated_at, group_id, position
end
How i can index only Item where group.disabled is false or nil.
Example with where:
ThinkingSphinx::Index.define :item, :with => :active_record do
where "id = 1"
indexes title
# attributes
has created_at, updated_at, group_id, position
end
This will index only Item with id = 1

In your index definition:
# force join on groups table:
join group
# PostgreSQL
where "disabled = 'f' OR disabled IS NULL"
# MySQL
where "disabled = 0 OR disabled IS NULL"
I'd highly recommend on having a default value of true or false for your disabled column, thus avoiding null values.

Related

Filter rails record by 2 instances of child record model

I'm trying to filter a list of Products based on 2 tags,
class Product < ActiveRecord::Base
has_many :tags
end
class Tag < ActiveRecord::Base {
:id => :integer,
:created_at => :datetime,
:updated_at => :datetime,
:key => :string
}
How can I format a query statement that allows me to find a product which has 2 tags, one with key 'fragile', and one with key 'perishable'?
Product.joins(:tags).where("tags.key IN (?)", ['fragile', 'perishable']).group('products.id').having('COUNT(tags.id) = ?', 2)

Sortable custom column in ActiveAdmin index view : joins, group and count hell

We're using ActiveAdmin for our admin view, here's the current index code. The Book model retrieves data from a single "books" postgres table :
class Book < ActiveRecord::Base
has_many :stories, class_name: "BookStory"
...
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
default_actions
end
...
I would like to add a "stories" column in our index view. A "story" is an action from an user, associated with a book. The stories are stored in a "book_stories" table.
class BookStory < ActiveRecord::Base
belongs_to :user,
belongs_to :book,
From a SQL point of view, this is how I would like to implement the query into ActiveAdmin. This query gives me the wanted result into pgAdmin3 :
SELECT books.id,books.title,books.subtitle,books.isbn_13,COUNT(book_stories.book_id) AS count
FROM books
INNER JOIN book_stories ON books.id = book_stories.book_id
GROUP BY books.id
ORDER BY count DESC
LIMIT 30;
And I really don't know how to implement a sortable "Stories" column into our admin view. By sortable, I mean, being able to sort the book like by their stories count. I managed to show the stories count per book with this code, but the column isn't sortable :
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
column :stories do |book|
BookStory.joins(:book).group.where("books.id = #{book.id}").count
default_actions
end
...
Any ideas ?
Take a look on the belongs_to counter_cache option. http://guides.rubyonrails.org/association_basics.html#counter-cache
class BookStory < ActiveRecord::Base
belongs_to :book, counter_cache: true
end
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
column :book_stories_count # will be sortable by default
default_actions
end
end
Okay, it's working. Thank you very much ! Here's my code :
Book model :
class Book < ActiveRecord::Base
has_many :stories, class_name: "BookStory"
Book stories model :
class BookStory < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :book, :counter_cache => true
Migration file :
class AddBookStoriesCountColumn < ActiveRecord::Migration
def self.up
add_column :books, :book_stories_count, :integer, :null => false, :default => 0
Book.reset_column_information
Book.find_each do |b|
Book.reset_counters b.id, :stories
end
end
def self.down
remove_column :books, :book_stories_count
end
end
Index view :
ActiveAdmin.register Book do
index do
column :id
column :title
column :subtitle
column :isbn_13
column :book_stories_count
default_actions
end
I also created a rake task to manually update the counter if needed :
task :update_counters => [:environment] do
Book.reset_column_information
Book.find_each do |b|
Book.reset_counters b.id, :stories
end
Now, I would like to implement a stories counter for the users. And I believed I'll just have to use the same code up here, just changing "Book" with "User", but I have another problem.
User model :
class User < ActiveRecord::Base
has_many :book_actions
has_many :book_stories
has_many :books, through: :book_stories
but I encouter an error when I try to update / reset the counter
NoMethodError: undefined method `options' for nil:NilClass
Still investigating...

Showing index to current user, only their information

I have a model Order. In the index, I want the current_user to see the index with only their orders. Order belongs_to :admin_user. AdminUser has_many :orders. I am using activeadmin in my app, if that makes a difference. I am getting this error:
Couldn't find Order without an ID
The line giving the error is the second line in my order controller.(redacted unnecessary info)
index do
#order = Order.where(admin_user_id: current_admin_user.id, order_id: resource.id)
column "ID" do |order|
link_to order.id, admin_order_path(order)
end
column "Proof" do |order|
image_tag order.proof_url(:proof).to_s
end
column "Name" do |order|
link_to order.name, admin_order_path(order)
end
column(:customer, :sortable => :customer_id)
column "Category", :order_category
column "Status", :order_status
column "Priority", :order_priority
column "Due Date", :end_date
default_actions
end
here is my order model requested by #jamesw
class Order < ActiveRecord::Base
attr_accessible :color_back, :color_front, :color_sleeve, :end_date, :name, :start_date, :whiteboard, :customer_id, :order_category_id, :order_type_id, :order_status_id, :order_priority_id, :print_location_id, :artwork, :proof, :line_items_attributes, :assignee_id, :admin_user_id
mount_uploader :artwork, ArtworkUploader
mount_uploader :proof, ProofUploader
has_many :line_items
belongs_to :assignee, :class_name => "AdminUser"
belongs_to :customer
belongs_to :order_category
belongs_to :order_type
belongs_to :order_status
belongs_to :order_priority
belongs_to :print_location
belongs_to :admin_user
accepts_nested_attributes_for :line_items, :allow_destroy => true
scope :owned_by, lambda { |user| includes(:assignee).where("admin_users.id = ?", user.id) }
def default_values
if new_record?
self.start_date ||= Date.today
self.number ||= (Order.maximum(:number) + 1 rescue 1)
end
end
end
It looks like you're trying to filter the Orders table by order_id. Unless you've built your DB in a non-standard manner, the ID field of the orders table would typically be id (not order_id).
That issue aside, I doubt you want to be passing in an order id for the index action since that would only return a single record, and by it's nature the index action should list many records (in your case, all records for the current_admin_user).
If neither of those issues solve your problem, try commenting out the lines 1 by 1.
Try to add this controller method
ActiveAdmin.register Order do
controller do
def scoped_collection
Order.where(:admin_user => current_admin_user.id)
end
end
end
see more here:
Two pages for the same resource - ActiveAdmin
I fixed the issue by taking the line in question out and using scope_to :current_user. I am wondering though, how to add a conditional statement to still allow the admin to view this? here is a look at the controller now.
scope_to current_user
index do
column "ID" do |order|
link_to order.id, admin_order_path(order)
end
column "Proof" do |order|
image_tag order.proof_url(:proof).to_s
end
column "Name" do |order|
link_to order.name, admin_order_path(order)
end
column(:customer, :sortable => :customer_id)
column "Category", :order_category
column "Status", :order_status
column "Priority", :order_priority
column "Due Date", :end_date
default_actions
end

How to filter with a foreign key count in rails 3?

I have a country with many hotels, how can i get all countries which have hotels? I mean a filter using count on my foreign key model?
Thank you
# migration
class AddCounterCacheToCountries < ActiveRecord::Migration
add_column :countries, :hotel_count, :integer, :default => 0
end
# models
class Country
has_many :hotels
scope :with_hotels, where('hotel_count > 0')
end
class Hotel
belongs_to :country, :counter_cache => true
end
# controller
def index
#countries = Country.with_hotels.all
end
And that's about all there is to it.

Thinking Sphinx, associations are not working

I have a model:
class Topic < ActiveRecord::Base
define_index do
indexes title, :sortable => true
indexes body
indexes tags(:name), :as => :tag_name
end
has_and_belongs_to_many :tags, :join_table => 'topic_tags', :order => 'tags.name asc'
end
When I run:
rake ts:rebuild
I get:
sql_range_query: Unknown column 'topics.name' in 'field list'
And my 'config/development.sphinx.conf' has this oddness:
sql_query = SELECT `topics`.`id` * 1 + 0 AS `id` , CAST(`topics`.`title` AS CHAR) AS
`title`, CAST(`topics`.`body` AS CHAR) AS `body`, CAST(`topics`.`name` AS CHAR) AS
`tag_name`, `topics`.`id` AS `sphinx_internal_id`, 1552019743 AS `class_crc`, '1552019743'
AS `subclass_crcs`, 0 AS `sphinx_deleted`, IFNULL(`topics`.`title`, '') AS `title_sort`
FROM `topics` WHERE `topics`.`id` >= $start AND `topics`.`id` <= $end GROUP BY
`topics`.`id` ORDER BY NULL
sql_query_range = SELECT IFNULL(MIN(`id`), 1), IFNULL(MAX(`id`), 1) FROM `topics`
So for some reason associations look bust, where have I gone wrong and how do I fix this?
(running rails 2.3.4 and latest thinking sphinx 1.2.11)
Trivial trap:
This works:
class Topic < ActiveRecord::Base
has_and_belongs_to_many :tags, :join_table => 'topic_tags', :order => 'tags.name asc'
define_index do
indexes title, :sortable => true
indexes body
indexes tags(:name), :as => :tag_name
end
end
associations must be defined prior to the index.

Resources