This project is archived and is in readonly mode.

#358 ✓resolved
nerdrew

find with a has_many condition fails

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

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

Comments and changes to this ticket

  • nerdrew
  • nerdrew

    nerdrew June 7th, 2008 @ 01:11 AM

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

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

  • Greg Campbell

    Greg Campbell June 7th, 2008 @ 01:52 AM

    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))

  • josh

    josh September 18th, 2008 @ 03:49 PM

    • State changed from “new” to “stale”
    • Tag cleared.
  • nerdrew

    nerdrew September 18th, 2008 @ 08:03 PM

    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.

  • Tarmo Tänav

    Tarmo Tänav September 18th, 2008 @ 09:24 PM

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

  • nerdrew

    nerdrew September 19th, 2008 @ 03:21 AM

    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

    
    
  • nerdrew

    nerdrew September 19th, 2008 @ 03:22 AM

    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
    
    
  • Vladimir Meremyanin

    Vladimir Meremyanin March 21st, 2009 @ 04:39 PM

    • 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.

  • Vladimir Meremyanin

    Vladimir Meremyanin March 21st, 2009 @ 05:58 PM

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

  • CancelProfileIsBroken

    CancelProfileIsBroken August 5th, 2009 @ 03:42 PM

    • Tag changed from active_record, bug, patch to active_record, bug, bugmash, patch
  • Arthur Zapparoli

    Arthur Zapparoli August 9th, 2009 @ 07:58 AM

    +1 for this patch

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

  • CancelProfileIsBroken

    CancelProfileIsBroken August 9th, 2009 @ 11:02 PM

    • State changed from “stale” to “open”
  • Repository

    Repository August 9th, 2009 @ 11:12 PM

    • 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...

  • Repository

    Repository August 9th, 2009 @ 11:12 PM

    (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...

  • Elad Meidar

    Elad Meidar August 9th, 2009 @ 11:18 PM

    +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.

  • CancelProfileIsBroken

    CancelProfileIsBroken August 10th, 2009 @ 02:15 AM

    • Tag changed from active_record, bug, bugmash, patch to active_record, bug, patch

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Referenced by

Pages