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
-

-

-

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) #=> errorThe 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))
-
Joshua Peek September 18th, 2008 @ 03:49 PM
- → Tag cleared.
- → State changed from new to stale
-

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 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 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 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
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
Source available from github
The Git repository resides at http://github.com/rails
Check out the current development trunk (Edge Rails) with:
git clone git://github.com/rails/rails.git
Creating or reviewing a patch
See the contributor guide.
Creating a feature request
Please don't. If you want a new feature in Rails, you'll have to pull up your sleeves and get busy yourself. Or convince someone else to do it. See the contributor guide on how to get going. But posting them here is just going to lead to ticket root.
Creating a bug report
When creating a bug report, be sure to include as much relevant information as possible. Post the code sample that causes the problem. Preferably, alter the unit tests and show through either changed or added tests how the expected behavior is not occuring.
Security vulnerabilities should be reported via an email to security@rubyonrails.org, do not use trac for reporting security vulnerabilities. All content in trac is publicly available as soon as it is posted.
Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kinda bug, you're creating this ticket in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the ticket automatically will see any activity or that others will jump to fix it. Creating a ticket like this is mostly to help yourself start on the path of fixing the problem and for others to sign on to with a "I'm having this problem too".
