2014-11-23 55 views
6

我對Ruby的項目on Rails的4.1.4,使用activeadmin 1.0.0.pre from git://github.com/activeadmin/activeadminpg 0.17.1,PostgreSQL的9.3的Rails + ActiveAdmin - 與ransacker過濾拋出Error PG ::語法錯誤:錯誤:語法錯誤或接近 「」

在項目中,我有這些模型:

  1. class User has_one :account

  2. class Account belongs_to :user has_many :project_accounts has_many :projects, :through => :project_accounts

  3. class Project # the project has a boolean attribute 'archive' has_many :project_accounts

  4. class ProjectAccount belongs_to :account belongs_to :project

我已經得到落實的索引頁,名爲「by_active_projects」上ActiveAdmin過濾器的任務,所以它必須證明已定義的活躍號碼的用戶項目,這意味着這樣的項目有archive == false。 例如如果我在篩選器中鍵入'2',則必須找到具有2個活動項目的帳戶。

對於ActiveAdmin現在我已經註冊了「戶口」的資源,並在admin/account.rb我添加filter :by_active_projects_eq

後,我已經定義了一個範圍having_active_projects的帳戶模型(模型/ account.rb):

scope :having_active_projects, ->(number) { joins(:projects).where("projects.archive = ?", false).having("count(projects) = ?", number).group("accounts.id") } 

下一步,我定義爲帳戶模型ransacker這樣的:

ransacker :by_active_projects, formatter: proc{ |v| 
    data = Account.having_active_projects(v).map(&:id) 
    data ||= nil 
    } do |parent| 
    parent.table[:id] 
    end 

在發展DB有一個帳戶,該帳戶恰好有8個活動項目,過濾對此非常有用。但是當我試圖通過2個活動項目篩選帳戶時,我遇到了一個錯誤。在DB有三個這樣的賬戶,並錯誤頁面報道我,查詢語法錯誤:不是

"accounts"."id" IN ('e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114') 

正在生成這個東西

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 

正如你所看到的,:

"accounts"."id" = 'e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114' 

我試圖深入研究源代碼,在ActiveRecord,ActiveAdmin和Ransack庫中的代碼塊上移動斷點,並發現關係正在構建中在的幫助下Arel :: Nodes :: Equality。我不確定這是爲什麼,但我可以肯定地說:

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這裏是一個賬戶活動記錄關係;

在列#565調用build_where之前,self.to_sql等於

SELECT "accounts".* FROM "accounts" WHERE "accounts"."deleted_at" IS NULL ORDER BY "accounts"."created_at" desc 

調用它,並將結果分配給self.where_values後,

self.to_sql等於

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 

任何幫助或有關這個問題的信息表示讚賞!謝謝!

回答

4

所以我找到了解決辦法:

首先,我改變了我的過濾器admin/account.rb

filter :by_active_projects_eq 

filter :by_active_projects_in, 
     :as => :string 

這種做法導致了正確的SQL生成,

"accounts"."id" IN ('e4d247ec-e64d-4e8a-996a-4d73ccb11257', 'bcb8fa61-4a53-4b45-8954-8fb6ae328365', '93d670b6-7b8f-4c27-91cc-e0f44c137114') 

之後,我也有我的ransacker從

ransacker :by_active_projects, formatter: proc{ |v| 
    data = Account.having_active_projects(v).map(&:id) 
    data ||= nil 
    } do |parent| 
    parent.table[:id] 
    end 

改變

ransacker :by_active_projects, formatter: proc{ |v| 
    data = Account.having_active_projects(v).pluck(:id) 
    data.present? ? data : nil 
    } do |parent| 
    parent.table[:id] 
    end 

,因爲它也被實施的方式造成不正確的查詢:比如有一些具有完全相同5個活動項目,沒有這樣的賬戶。在這種情況下

data = Account.having_active_projects(v).pluck(:id) 

返回「空陣」,以及處理該陣列與data ||= nil實際上從未返回nil,而導致這樣的SQL:

SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "accounts" WHERE "accounts"."deleted_at" IS NULL AND "accounts"."id" IN() LIMIT 30 OFFSET 0) subquery_for_count 

通知"accounts"."id" IN()的一部分,這是製造麻煩。 "accounts"."id" IN (NULL)

data.present? ? data : nil替換data ||= nil,如果data不存在它被分配一個nil,並被corectly生成SQL那部分之後

相關問題