# How about find(:exactly\_one, ...)?

**URL:** <https://www.ruby-forum.com/t/how-about-find-exactly-one/135192>\
**Category:** Rails\
**Created:** [April 19, 2008, 12:37am UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192 "2008-04-19T00:37:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 19, 2008, 12:37am UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/1 "2008-04-19T00:37:09Z")

</div>

All,

Is there a safe, one-line way of finding a record that:

1. Must be present
2. Must be unique (according to the conditions)

Bootstrapping data (often stored as a constant) often spurs this need,  
e.g.

class Status \< ActiveRecord::Base  
APPROVED = Status.find(:first, :conditions =\> [“name = ‘approved’”])  
…  
end

class AccountType \< ActiveRecord::Base  
AccountType.find(:first, :conditions =\> [“type = ‘commercial’”])  
end

or

us\_state = UsState.find(:first, :conditions =\> [“abbrev = ?”,  
abbreviation])

I don’t want the burden of error-checking the results, e.g. ‘x.nil?’ or  
‘x.size == 1’, every time I issue a query of this type.

I haven’t seen any good solution so far, and I’m considering overriding  
‘find’ to take an ‘:exactly\_one’ option in addition to :first and :all,  
raising RecordNotFoundException or TooManyRecordsException. Before I go  
down that road I wanted to ask the mailing list if I’m missing  
something.

Thanks!

Brian H.

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 19, 2008, 12:45am UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/2 "2008-04-19T00:45:10Z")

</div>

Brian H. wrote:

> All,
> 
> Is there a safe, one-line way of finding a record that:
> 
> 1. Must be present
> 2. Must be unique (according to the conditions)
> 
> Bootstrapping data (often stored as a constant) often spurs this need,  
> e.g.
> 
> class Status \< ActiveRecord::Base  
> APPROVED = Status.find(:first, :conditions =\> [“name = ‘approved’”])  
> …  
> end
> 
> class AccountType \< ActiveRecord::Base  
> AccountType.find(:first, :conditions =\> [“type = ‘commercial’”])  
> end
> 
> or
> 
> us\_state = UsState.find(:first, :conditions =\> [“abbrev = ?”,  
> abbreviation])
> 
> I don’t want the burden of error-checking the results, e.g. ‘x.nil?’ or  
> ‘x.size == 1’, every time I issue a query of this type.
> 
> I haven’t seen any good solution so far, and I’m considering overriding  
> ‘find’ to take an ‘:exactly\_one’ option in addition to :first and :all,  
> raising RecordNotFoundException or TooManyRecordsException. Before I go  
> down that road I wanted to ask the mailing list if I’m missing  
> something.
> 
> Thanks!
> 
> Brian H.

The access you are asking for would be given by

class ActiveRecord::Base  
def self.find\_exactly\_one(conditions)  
return nil unless self.count(:conditions =\> conditions) == 1  
self.find(:first, :conditions =\> conditions)  
end  
end

(or something close to this)

I don’t know if you want to bother into one sql-statement.

Can you not put a uniqueness constraint on the column?

Stephan

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 19, 2008, 1:50am UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/3 "2008-04-19T01:50:42Z")

</div>

Stephan W. wrote:

> Brian H. wrote:
> 
> > All,
> > 
> > Is there a safe, one-line way of finding a record that:
> > 
> > 1. Must be present
> > 2. Must be unique (according to the conditions)
> > 
> > Bootstrapping data (often stored as a constant) often spurs this need,  
> > e.g.
> > 
> > class Status \< ActiveRecord::Base  
> > APPROVED = Status.find(:first, :conditions =\> [“name = ‘approved’”])  
> > …  
> > end
> > 
> > class AccountType \< ActiveRecord::Base  
> > AccountType.find(:first, :conditions =\> [“type = ‘commercial’”])  
> > end
> > 
> > or
> > 
> > us\_state = UsState.find(:first, :conditions =\> [“abbrev = ?”,  
> > abbreviation])
> > 
> > I don’t want the burden of error-checking the results, e.g. ‘x.nil?’ or  
> > ‘x.size == 1’, every time I issue a query of this type.
> > 
> > I haven’t seen any good solution so far, and I’m considering overriding  
> > ‘find’ to take an ‘:exactly\_one’ option in addition to :first and :all,  
> > raising RecordNotFoundException or TooManyRecordsException. Before I go  
> > down that road I wanted to ask the mailing list if I’m missing  
> > something.
> > 
> > Thanks!
> > 
> > Brian H.
> 
> The access you are asking for would be given by
> 
> class ActiveRecord::Base  
> def self.find\_exactly\_one(conditions)  
> return nil unless self.count(:conditions =\> conditions) == 1  
> self.find(:first, :conditions =\> conditions)  
> end  
> end
> 
> (or something close to this)
> 
> I don’t know if you want to bother into one sql-statement.
> 
> Can you not put a uniqueness constraint on the column?
> 
> Stephan

There is a uniqueness constraint, but that doesn’t cover the case in  
which the record doesn’t exist. The behavior I’m shooting for is:

1. One and only one query is issued (your example issues two)
2. The conditions will usually reference a column(s) with a unique  
index, but not necessarily (some dev shops don’t use them - sigh)
3. It must raise a NoRecordFound if no record is found
4. It must raise a TooManyRecordsFound if more than one record is found
5. It must not interfere with other, expected find behavior

So far, I’ve got:

def self.find\_exactly\_one(conditions)  
results = self.find(:all, :conditions =\> conditions)  
raise RecordNotFound if results.size == 0  
raise TooManyRecordsFound, “#{results.size} found.” if results.size \>  
1  
results[0] # Found just one  
end

But this is only because I’m not yet ready to tackle replacing ‘find’  
itself. Ideally, I could do:

find(:exactly\_one, :conditions =\> …)

Thanks for the response!

Brian

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 19, 2008, 2:05am UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/4 "2008-04-19T02:05:04Z")

</div>

> > Brian H. wrote:
> > 
> > > …but that doesn’t cover the case in  
> > > which the record doesn’t exist. The behavior I’m shooting for is:
> 
> 1. One and only one query is issued (your example issues two)
> 2. The conditions will usually reference a column(s) with a unique  
> index, but not necessarily (some dev shops don’t use them - sigh)
> 3. It must raise a NoRecordFound if no record is found
> 4. It must raise a TooManyRecordsFound if more than one record is found
> 5. It must not interfere with other, expected find behavior

How something like this one:

class ActiveRecord::Base  
def self.find\_exactly\_one(conditions)  
results = self.find(:all, :condition =\> conditions)  
raise ‘None found’ if results.blank? # might also be results==[]  
raise ‘Too many’ if results.length \> 1  
results.first  
end  
end

Stephan

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 19, 2008, 2:04am UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/5 "2008-04-19T02:04:30Z")

</div>

Patching it into find should be easy. Something like below (which is  
aircoded and probably not correct) should get you started:

class ActionView::Base

# this method will become “find”

def find\_with\_exactly\_one(\*args)  
options = args.extract\_options!  
case args.first  
when :exactly\_one then find\_exactly\_one(options)  
else find\_without\_exactly\_one(args, options)  
end  
end

# this makes “find\_with\_exactly\_one” into “find”

# and turn the original “find” method into “find\_without\_exactly\_one”

alias\_method\_chain :find, :exactly\_one

def self.find\_exactly\_one(conditions)  
results = self.find(:all, :conditions =\> conditions)  
raise RecordNotFound if results.size == 0  
raise TooManyRecordsFound, “#{results.size} found.” if results.size

> 

1  
results[0] # Found just one  
end  
end

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 21, 2008, 4:14pm UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/6 "2008-04-21T16:14:20Z")

</div>

I think that typically you use alias\_method\_chain when you want to  
inject something into the call chain (ie., before/after processing,  
adding callbacks) rather than simply extending the method. If you  
only need to extend it, you’re probably better adding an extension in  
lib (often lib/core\_ext when extending a core object) and then  
including the functionality where you need it.

The find\_exactly\_on code is good (should probably be protected),  
though you could simply:

def self.find  
options = args.extract\_options!  
return find\_exactly\_one if args.first==:exactly\_one # add your new  
method when the conditions are right  
super # give way to default if not  
end

On Apr 18, 8:04 pm, Nathan E. \<rails-mailing-l…@andreas-

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 22, 2008, 8:02pm UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/7 "2008-04-22T20:02:01Z")

</div>

Brian H. wrote:

> AndyV wrote:
> 
> > I think that typically you use alias\_method\_chain when you want to  
> > inject something into the call chain (ie., before/after processing,  
> > adding callbacks) rather than simply extending the method. If you  
> > only need to extend it, you’re probably better adding an extension in  
> > lib (often lib/core\_ext when extending a core object) and then  
> > including the functionality where you need it.
> > 
> > The find\_exactly\_on code is good (should probably be protected),  
> > though you could simply:
> > 
> > def self.find  
> > options = args.extract\_options!  
> > return find\_exactly\_one if args.first==:exactly\_one # add your new  
> > method when the conditions are right  
> > super # give way to default if not  
> > end
> > 
> > On Apr 18, 8:04 pm, Nathan E. \<rails-mailing-l…@andreas-
> 
> That implies that we either do this in a particular model or use a  
> common base class for all our models, no? For a monkeypatch, I’d have  
> to use alias\_method\_chain, right?
> 
> I prefer the common base-class approach. I’ll give that a shot.
> 
> Thanks!
> 
> Brian

I’ve done this as a monkeypatch for now. Here’s what I have:

# Add common behaviors to models

module ActiveRecord  
class TooManyRecordsFound \< ActiveRecordError  
end

class Base  
class \<\< self  
# Adds support for the new :exactly\_one option  
def find\_with\_exactly\_one(\*args)  
options = args.last.is\_a?(Hash) ? args.last : {}  
if args.first == :exactly\_one  
find\_exactly\_one(options)  
else  
find\_without\_exactly\_one(\*args)  
end  
end

```
  alias_method_chain :find, :exactly_one

  protected
      # Raises either TooManyRecordsFound or
      # RecordNotFound if we don't find exactly
      # one record.
      def find_exactly_one(options)
        results = find(:all, options)
        raise RecordNotFound if results.size == 0
        raise TooManyRecordsFound, "#{results.size} found." if 

```

results.size \> 1  
results[0] # Found just one  
end  
end  
end  
end

Thanks for all your responses,

Brian H.

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 21, 2008, 8:54pm UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/8 "2008-04-21T20:54:53Z")

</div>

AndyV wrote:

> I think that typically you use alias\_method\_chain when you want to  
> inject something into the call chain (ie., before/after processing,  
> adding callbacks) rather than simply extending the method. If you  
> only need to extend it, you’re probably better adding an extension in  
> lib (often lib/core\_ext when extending a core object) and then  
> including the functionality where you need it.
> 
> The find\_exactly\_on code is good (should probably be protected),  
> though you could simply:
> 
> def self.find  
> options = args.extract\_options!  
> return find\_exactly\_one if args.first==:exactly\_one # add your new  
> method when the conditions are right  
> super # give way to default if not  
> end
> 
> On Apr 18, 8:04 pm, Nathan E. \<rails-mailing-l…@andreas-

That implies that we either do this in a particular model or use a  
common base class for all our models, no? For a monkeypatch, I’d have  
to use alias\_method\_chain, right?

I prefer the common base-class approach. I’ll give that a shot.

Thanks!

Brian

---

<div class="post-metadata">

**Author:** ![kuma](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/a587f6/32.png) [@kuma](https://www.ruby-forum.com/u/kuma)\
**Post date:** [April 22, 2008, 11:46pm UTC](https://www.ruby-forum.com/t/how-about-find-exactly-one/135192/9 "2008-04-22T23:46:45Z")

</div>

I am not sure but I actually think Andy was right. I am not sure  
alias\_method\_chain is the best method to use here BUT it works so I am  
happy you at least got that worked up. Although I think Andy might have  
been pointing you to a better solution (i.e included module extension)
