I have a project on Ruby on Rails 4.1.4, using activeadmin 1.0.0.pre from git://github.com/activeadmin/activeadmin
, pg 0.17.1
, PostgreSQL 9.3
In the project I have these models:
class User has_one :account
class Account belongs_to :user has_many :project_accounts has_many :projects, :through => :project_accounts
class Project # the project has a boolean attribute 'archive' has_many :project_accounts
class ProjectAccount belongs_to :account belongs_to :project
I've got a task to implement an ActiveAdmin filter on the index page, called "by_active_projects", so it has to show the users that have defined number of active projects, that means such projects that have archive == false
.
E.g. if I type '2' in the filter, it has to find such accounts that have exactly 2 active projects.
For now I have registered "Account" resource in ActiveAdmin, and within admin/account.rb
i've added filter :by_active_projects_eq
After that I've defined a scope having_active_projects
for Account model (models/account.rb):
scope :having_active_projects, ->(number) { joins(:projects).where("projects.archive = ?", false).having("count(projects) = ?", number).group("accounts.id") }
Next step, I've defined a ransacker for Account model like this:
ransacker :by_active_projects, formatter: proc{ |v|
data = Account.having_active_projects(v).map(&:id)
data ||= nil
} do |parent|
parent.table[:id]
end
In the development DB there is one account, that has exactly 8 active projects, and filtering works great for it. But when I've tried to filter accounts by 2 active projects, I faced an error. In the DB there are three such accounts, and the error page reported me that the query syntax is wrong:
SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "accounts" WHERE "accounts"."deleted_at" IS NULL AND "accounts"."id" = 'e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114' LIMIT 30 OFFSET 0) subquery_for_count
As you can see, instead of
"accounts"."id" IN ('e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114')
this thing is being generated:
"accounts"."id" = 'e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114'
I tried to dig down into the source code, moving with breakpoints on the pieces of code within the ActiveRecord, ActiveAdmin and Ransack lib's and figured out that the relation is being constructed with the help of Arel::Nodes::Equality. I'm not sure this is the reason but one I can say for sure:
lib/active_record/relation/query_methods.rb `
560 def where!(opts = :chain, *rest)
561 if opts == :chain
562 WhereChain.new(self)
563 else
564 references!(PredicateBuilder.references(opts)) if Hash === opts
565 self.where_values += build_where(opts, rest)
566 self
567 end
568 end`
self
here is an Active Record relation for Account;
before calling build_where
on the row #565, self.to_sql
equals to
SELECT "accounts".* FROM "accounts" WHERE "accounts"."deleted_at" IS NULL ORDER BY "accounts"."created_at" desc
after calling it and assigning the result to self.where_values
,
self.to_sql
equals to
SELECT "accounts".* FROM "accounts" WHERE "accounts"."deleted_at" IS NULL AND "accounts"."id" = 'e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114' ORDER BY "accounts"."created_at" desc
Any help or information on the matter is appreciated! Thanks!