Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

find with a has_many condition fails

#358

Given a model with a has_many that has a condition, a find with this has_many association included will fail.

class Company < ActiveRecord::Base
  has_many(
      :employments, 
      :class_name => 'Employment', 
      :conditions => {
        :end_date => nil
      },
      :include => :person
    )
end

class Employment < ActiveRecord::Base
  belongs_to :person
  belongs_to :company
end

class Person < ActiveRecord::Base
end

Company.find(:all, :include => {:employments => :person})
Company.find(:all, :include => :employments)

The last two statements both fail. I've attached a sample that fails for me.

The problem is that the condition for the has_many tries to use companies.end_date for the condition instead of employments.end_date

The error:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: companies.end_date

Reported by nerdrew · June 7th, 2008 @ 01:06 AM

State: resolved
Milestone: none
Assigned to: nobody
Importance: none

Activity

  1. nerdrew
  2. nerdrew
    nerdrew

    I can't attach files without an error, so I've uploaded it here:

    http://www.nerdputer.com/test_ra...

    June 7th, 2008 @ 01:11 AM

  3. Greg Campbell
    Greg Campbell

    The same is true for a has_one association with a condition.

    I have:

    class Contact < ActiveRecord::Base
      has_one :primary_email, :class_name => 'ContactEmail', :conditions => {:primary_email => true}
    end
    
    Contact.find(:first).primary_email #=> #<ContactEmail ... >
    Contact.find(:first, :include => :primary_email) #=> error
    

    The error in question is ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'contacts.primary_email' in 'where clause': SELECT `contact_emails`.* FROM `contact_emails` WHERE (`contact_emails`.contact_id IN (1) AND (`contacts`.`primary_email` = 1))

    June 7th, 2008 @ 01:52 AM

  4. josh
    josh
    • State changed from new to stale
    • Tag cleared.

    September 18th, 2008 @ 03:49 PM

  5. nerdrew
    nerdrew

    Why is this stale now? I'm still seeing the same bug (I think) in edge. It could be that I'm using the conditions hash wrong, but I don't know how else I'd do it. My understanding is that the conditions hash of a has_many should be properties on the associated model. So, in the example above, the {:end_date => nil} should apply to the employment model, not the company model.

    September 18th, 2008 @ 08:03 PM

  6. Tarmo Tänav
    Tarmo Tänav

    stale only means that the bug is not moving anywhere, either no patch for a long time or the patch no longer applies.

    September 18th, 2008 @ 09:24 PM

  7. nerdrew
    nerdrew

    Can someone test this for me? I have some custom ActiveRecord improvements (nested condition hashes and includes), but it seems to work for me.

    @@@ruby

    class <<ActiveRecord::Base

    private

    def find_associated_records(ids, reflection, preload_options)

    options = reflection.options
    table_name = reflection.klass.quoted_table_name
    
    if !options[:conditions].is_a?(Hash) && !preload_options[:conditions].is_a?(Hash)
      if interface = reflection.options[:as]
        conditions = "#{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_id"} #{in_or_equals_for_ids(ids)} and #{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_type"} = '#{self.base_class.sti_name}'"
      else
        foreign_key = reflection.primary_key_name
        conditions = "#{reflection.klass.quoted_table_name}.#{foreign_key} #{in_or_equals_for_ids(ids)}"
      end
    
      conditions << append_conditions(options, preload_options)
      conditions = [conditions, ids]
    else
      conditions = if interface = reflection.options[:as]
        {"#{interface}_id" => ids, "#{interface}_type" => self.base_class.sti_name}
      else
        {reflection.primary_key_name => ids}
      end
    
      conditions.merge!(options[:conditions]) if options[:conditions]
      conditions.merge!(preload_options[:conditions]) if preload_options[:conditions]
    end
    
    reflection.klass.find(:all,
                          :select => (preload_options[:select] || options[:select] || "#{table_name}.*"),
                          :include => preload_options[:include] || options[:include],
                          :conditions => conditions,
                          :joins => options[:joins],
                          :group => preload_options[:group] || options[:group],
                          :order => preload_options[:order] || options[:order])
    
    

    end

    end #adding to ActiveRecord::Base

    
    

    September 19th, 2008 @ 03:21 AM

  8. nerdrew
    nerdrew

    I wish there was a way to edit comments...

    Here it is again.

    
    
    class <<ActiveRecord::Base
    
      private
    
      def find_associated_records(ids, reflection, preload_options)
        options = reflection.options
        table_name = reflection.klass.quoted_table_name
    
        if !options[:conditions].is_a?(Hash) && !preload_options[:conditions].is_a?(Hash)
          if interface = reflection.options[:as]
            conditions = "#{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_id"} #{in_or_equals_for_ids(ids)} and #{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_type"} = '#{self.base_class.sti_name}'"
          else
            foreign_key = reflection.primary_key_name
            conditions = "#{reflection.klass.quoted_table_name}.#{foreign_key} #{in_or_equals_for_ids(ids)}"
          end
    
          conditions << append_conditions(options, preload_options)
          conditions = [conditions, ids]
        else
          conditions = if interface = reflection.options[:as]
            {"#{interface}_id" => ids, "#{interface}_type" => self.base_class.sti_name}
          else
            {reflection.primary_key_name => ids}
          end
    
          conditions.merge!(options[:conditions]) if options[:conditions]
          conditions.merge!(preload_options[:conditions]) if preload_options[:conditions]
        end
    
        reflection.klass.find(:all,
                              :select => (preload_options[:select] || options[:select] || "#{table_name}.*"),
                              :include => preload_options[:include] || options[:include],
                              :conditions => conditions,
                              :joins => options[:joins],
                              :group => preload_options[:group] || options[:group],
                              :order => preload_options[:order] || options[:order])
      end
    
    end #adding to ActiveRecord::Base
    
    

    September 19th, 2008 @ 03:22 AM

  9. Vladimir Meremyanin
    Vladimir Meremyanin
    • Tag set to active_record, bug, patch

    I've fixed this error. It was caused by accidental assignment to a parameter.

    Please, see the patch with test.

    March 21st, 2009 @ 04:39 PM

  10. Vladimir Meremyanin
    Vladimir Meremyanin

    I've forked rails, and applied this patch to 2-3-stable branch: http://github.com/stiff/rails/tr...

    March 21st, 2009 @ 05:58 PM

  11. CancelProfileIsBroken
    CancelProfileIsBroken
    • Tag changed from active_record, bug, patch to active_record, bug, bugmash, patch

    August 5th, 2009 @ 03:42 PM

  12. Arthur Zapparoli
    Arthur Zapparoli

    +1 for this patch

    Vladimir's patch solve the issue and applies cleanly to 2-3-stable

    August 9th, 2009 @ 07:58 AM

  13. CancelProfileIsBroken
    CancelProfileIsBroken
    • State changed from stale to open

    August 9th, 2009 @ 11:02 PM

  14. Repository
    Repository
    • State changed from open to resolved

    (from [93f5d9d5f0417c552701996760cc5de2d2d4be10]) Make sure association conditions work with :include and :joins [#358 state:resolved]

    Signed-off-by: Pratik Naik pratiknaik@gmail.com
    http://github.com/rails/rails/commit/93f5d9d5f0417c552701996760cc5d...

    August 9th, 2009 @ 11:12 PM

  15. Repository
    Repository

    (from [08ec22054f56442b10f67e41c3b7593da6adcabd]) Make sure association conditions work with :include and :joins [#358 state:resolved]

    Signed-off-by: Pratik Naik pratiknaik@gmail.com
    http://github.com/rails/rails/commit/08ec22054f56442b10f67e41c3b759...

    August 9th, 2009 @ 11:12 PM

  16. Elad Meidar
    Elad Meidar

    +1 Verified +1 patch applies on 2-3-stable cleanly and tests pass.

    patch fails on master, attached a working patch and tests for master.

    August 9th, 2009 @ 11:18 PM

  17. CancelProfileIsBroken
    CancelProfileIsBroken
    • Tag changed from active_record, bug, bugmash, patch to active_record, bug, patch

    August 10th, 2009 @ 02:15 AM