This project is archived and is in readonly mode.
Add find :unique to ActiveRecord
-
Joris
So, I read the bar at the right :)
So, I didn't test this, I just typed it here, so I'm not sure if my manual diff is ok. anyway.. here's the code:In base.rb from activerecord:
in find(*args):
case args.first when :first then find_initial(options) when :all then find_every(options)-
when :unique then find_unique(options)
add method:
def find_initial(options) options.update(:limit => 1) unless options[:include] find_every(options).first end-
def find_unique(options) -
records = find_every(options) -
if records.size > 0 then -
raise ActiveRecordError, "Too many records found: #{records.size}" -
end -
records.first -
end
Also, some calls to find_initial should be replaced by find_unique, but I can imagine that would break some existing apps. So that might be for later.
-
-
Joris
So, I read the bar at the right :)
So, I didn't test this, I just typed it here, so I'm not sure if my manual diff is ok. anyway.. here's the code:In base.rb from activerecord:
in find(*args):
case args.first
when :first then find_initial(options) when :all then find_every(options)-
when :unique then find_unique(options)</code>
add method:
def find_initial(options)
options.update(:limit => 1) unless options[:include] find_every(options).first end-
def find_unique(options) -
records = find_every(options) -
if records.size > 0 then -
raise ActiveRecordError, "Too many records found: #{records.size}" -
end -
records.first -
end</code>
Also, some calls to find_initial should be replaced by find_unique, but I can imagine that would break some existing apps. So that might be for later. -
-
Pratik
Hey Joris,
I think you should discuss this change in the ML first. Also, your patch should have tests. Check http://guides.rubyonrails.org/contributing_to_rails.html for more details.
Thanks!
-
Pratik
- State changed from new to incomplete
-
MatthewRudy
is this really the proposed implementation?
def find_unique(options) records = find_every(options) if records.size > 0 then
raise ActiveRecordError, "Too many records found: #{records.size}"
Seems a bit crazy,
end records.first end
I'd rather have the two db calls (count, and find_first)Also, I don't get the use-case.
Joris, do you have some examples of how you are using this feature?The only reason I've needed something similar is this case;
class SomeSortOfSettings < ActiveRecord::Base def self.instance self.first || self.new end endnamely a "Singleton" ActiveRecord,
but I think there's a better way to deal with this
(an ActiveRecord::Singleton class, perhaps)User.find(:unique, :conditions => {:username => "ralph"})is silly,
you should just have a unique key on :username -
Joris
Having 2 queries would be a waste of db calls. If you expect 1 row, there's no need to do a count.
All queries for something with a unique index / natural key is where I'd do this. Just because it's contextual more correct, and it has no performance drawbacks except for a single check if there's another row in the resultset.
The implementation was just something I typed. I can imagine that there would be some other things that would need to happen, but basically that's how about what I had in mind.
Hibernate has a similar feature: query.uniqueResult
-
Pratik
- State changed from incomplete to wontfix
While I don't think this is gonna make it to the core, but the best implementation would probably be the one using :limit => 2.
This seem very project specific, hence you should just keep it in /lib or maybe make a plugin and see if many people find it useful or not. We can always reconsider the feature if more people are using it.
Thanks.