1

I can disable STI for a complete model but I'd like to just disable it when doing certain queries. Things were working swell in Rails 3.2, but I've upgraded to Rails 4.1.13 and a new thing is happening that's breaking the query.

I have a base class called Person with a fairly complex scope.

class Person < ActiveRecord::Base
  include ActiveRecord::Sanitization
  has_many :approvals, :dependent => :destroy
  has_many :years, through: :approvals

  scope :for_current_or_last_year, lambda {
      joins(:approvals).merge(Approval.for_current_or_last_year) }

  scope :for_current_or_last_year_latest_only, ->{
      approvals_sql = for_current_or_last_year.select('person_id AS ap_person_id, MAX(year_id) AS max_year, year_id AS ap_year_id, status_name AS ap_status_name, active AS ap_active, approved AS ap_approved').group(:id).to_sql
      approvals_sql = select("*").from("(#{approvals_sql}) AS ap, approvals AS ap2").where('ap2.person_id = ap.ap_person_id AND ap2.year_id = ap.max_year').to_sql

    select("people.id, ap_approved, ap_year_id, ap_status_name, ap_active").
    joins("JOIN (#{approvals_sql}) filtered_people ON people.id =    
      filtered_people.person_id").uniq
  }
end

And inheriting classes called Member and Staff. The only thing related to this I had to comment out to get my tests to pass with Rails 4. It may be the problem, but uncommenting it hasn't helped in this case.

class Member < Person
    #has_many :approvals, :foreign_key => 'person_id', :dependent => :destroy, :class_name => "MemberApproval"
end

The problem happens when I do the query Member.for_current_or_last_year_latest_only

I get the error unknown column 'people.type'

When I look at the SQL, I can see the problem line but I don't know how to remove it or make it work.

Member.for_current_or_last_year_latest_only.to_sql results in.

SELECT DISTINCT people.id, ap_approved, ap_year_id, ap_status_name, ap_active 
FROM `people` 
JOIN (SELECT * FROM (SELECT person_id AS ap_person_id, MAX(year_id) AS max_year, year_id AS ap_year_id, status_name AS ap_status_name, active AS ap_active, approved AS ap_approved 
  FROM `people` INNER JOIN `approvals` ON `approvals`.`person_id` = `people`.`id` 
WHERE `people`.`type` IN ('Member') AND ((`approvals`.`year_id` = 9 OR `approvals`.`year_id` = 8)) 
GROUP BY `people`.`id`) AS ap, approvals AS ap2

WHERE `people`.`type` IN ('Member') AND (ap2.person_id = ap.ap_person_id AND ap2.year_id = ap.max_year)) filtered_people ON people.id = filtered_people.person_id

WHERE `people`.`type` IN ('Member')

If I remove people.type IN ('Member') AND from the beginning of the second to last WHERE clause the query runs successfully. And btw, that part isn't in the query generated from the old Rails 3.2 code, neither is the one above it (only the last one matches the Rails 3.2 query). The problem is, that part is being generated from rails Single Table Inheritance I assume, so I can't just delete it from my query. It's not the only place that is getting added into the original query, but that's the only one that is causing it to break.

Does anybody have any idea how I can either disable STI for only certain queries or add something to my query that will make it work? I've tried putting people.type in every one of the SELECT queries to try and make it available but to no avail.

Thanks for taking the time to look at this.

andyrue
  • 903
  • 10
  • 24
  • You can try to use this tutorial http://stackoverflow.com/questions/7134559/rails-use-type-column-without-sti#answer-29663933 – akbarbin Nov 10 '15 at 03:29
  • I'm not sure I want to completely disable Single Table Inheritance, but perhaps I'll give it a try and see what adverse affects it has. – andyrue Nov 10 '15 at 15:25
  • I might be able to work with this. At least with this specific query, I can now manually add `WHERE people.type IN('Member')` at the end and it works. To really solve the problem I think I would need a way to disable it for just those subqueries that are used to build the overall query. I've updated the title to reflect this new insight. – andyrue Nov 10 '15 at 15:31

1 Answers1

0

I was apparently making this harder than it really was...I just needed to add unscoped to the front of the two approval_sql sub-queries. Thanks for helping my brain change gears.

andyrue
  • 903
  • 10
  • 24