Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Don't internally rely on Model#[] being available since it may confli…

…ct with other plugins

Add Model#find_all_by_enumerator
  • Loading branch information...
commit 3db8cb015ece9727a1a72bd4d8bb18a6c353b28d 1 parent 34fa878
@obrie obrie authored
View
2  CHANGELOG.rdoc
@@ -1,5 +1,7 @@
== master
+* Add Model#find_all_by_enumerator
+* Don't internally rely on Model#[] being available since it may conflict with other plugins
* Enable caching by default for all enumerations
* Allow caching to be turned off on an application-wide basis
* Allow cache store to be configurable
View
45 lib/enumerate_by.rb
@@ -117,6 +117,18 @@ def enumeration?
true
end
+ # Finds the record that is associated with the given enumerator. The
+ # attribute that defines the enumerator is based on what was specified
+ # when calling +enumerate_by+.
+ #
+ # For example,
+ #
+ # Color.find_by_enumerator('red') # => #<Color id: 1, name: "red">
+ # Color.find_by_enumerator('invalid') # => nil
+ def find_by_enumerator(enumerator)
+ first(:conditions => {enumerator_attribute => enumerator})
+ end
+
# Finds the record that is associated with the given enumerator. If no
# record is found, then an ActiveRecord::RecordNotFound exception is
# raised.
@@ -127,20 +139,35 @@ def enumeration?
# Color['invalid'] # => ActiveRecord::RecordNotFound: Couldn't find Color with name "red"
#
# To avoid raising an exception on invalid enumerators, use +find_by_enumerator+.
- def [](enumerator)
+ def find_by_enumerator!(enumerator)
find_by_enumerator(enumerator) || raise(ActiveRecord::RecordNotFound, "Couldn't find #{name} with #{enumerator_attribute} #{enumerator.inspect}")
end
+ alias_method :[], :find_by_enumerator!
- # Finds the record that is associated with the given enumerator. The
- # attribute that defines the enumerator is based on what was specified
- # when calling +enumerate_by+.
+ # Finds records with the given enumerators.
#
# For example,
#
- # Color.find_by_enumerator('red') # => #<Color id: 1, name: "red">
- # Color.find_by_enumerator('invalid') # => nil
- def find_by_enumerator(enumerator)
- first(:conditions => {enumerator_attribute => enumerator})
+ # Color.find_all_by_enumerator('red', 'green') # => [#<Color id: 1, name: "red">, #<Color id: 1, name: "green">]
+ # Color.find_all_by_enumerator('invalid') # => []
+ def find_all_by_enumerator(enumerators)
+ all(:conditions => {enumerator_attribute => enumerators})
+ end
+
+ # Finds records with the given enumerators. If no record is found for a
+ # particular enumerator, then an ActiveRecord::RecordNotFound exception
+ # is raised.
+ #
+ # For Example,
+ #
+ # Color.find_all_by_enumerator!('red', 'green') # => [#<Color id: 1, name: "red">, #<Color id: 1, name: "green">]
+ # Color.find_all_by_enumerator!('invalid') # => ActiveRecord::RecordNotFound: Couldn't find Color with name(s) "invalid"
+ #
+ # To avoid raising an exception on invalid enumerators, use +find_all_by_enumerator+.
+ def find_all_by_enumerator!(enumerators)
+ records = find_all_by_enumerator(enumerators)
+ missing = [enumerators].flatten.select {|enumerator| !records.any? {|record| record.enumerator == enumerator}}
+ missing.empty? ? records : raise(ActiveRecord::RecordNotFound, "Couldn't find #{name} with #{enumerator_attribute}(s) #{missing.map(&:inspect).to_sentence}")
end
# Adds support for looking up records from the enumeration cache for
@@ -242,7 +269,7 @@ module InstanceMethods
# a String, then it is compared against the enumerator. Otherwise,
# ActiveRecord's default equality comparator is used.
def ==(arg)
- arg.is_a?(String) ? self == self.class[arg] : super
+ arg.is_a?(String) ? self == self.class.find_by_enumerator!(arg) : super
end
# Determines whether this enumeration is in the given list.
View
4 lib/enumerate_by/extensions/associations.rb
@@ -79,14 +79,14 @@ def belongs_to_with_enumerations(association_id, options = {})
# Inclusion scopes
%W(with_#{name} with_#{name.to_s.pluralize}).each do |scope_name|
named_scope scope_name.to_sym, lambda {|*enumerators| {
- :conditions => {primary_key_name => enumerators.flatten.collect {|enumerator| klass[enumerator].id}}
+ :conditions => {primary_key_name => klass.find_all_by_enumerator!(enumerators).map(&:id)}
}}
end
# Exclusion scopes
%W(without_#{name} without_#{name.to_s.pluralize}).each do |scope_name|
named_scope scope_name.to_sym, lambda {|*enumerators| {
- :conditions => ["#{primary_key_name} NOT IN (?)", enumerators.flatten.collect {|enumerator| klass[enumerator].id}]
+ :conditions => ["#{primary_key_name} NOT IN (?)", klass.find_all_by_enumerator!(enumerators).map(&:id)]
}}
end
View
6 lib/enumerate_by/extensions/base_conditions.rb
@@ -105,7 +105,11 @@ def enumerator_options_for(name, enumerator, allow_multiple = true)
if reflection = reflect_on_enumeration(name)
klass = reflection.klass
attribute = reflection.primary_key_name
- id = allow_multiple && enumerator.is_a?(Array) ? enumerator.map {|enumerator| klass[enumerator].id} : klass[enumerator].id
+ id = if allow_multiple && enumerator.is_a?(Array)
+ enumerator.map {|enumerator| klass.find_by_enumerator!(enumerator).id}
+ else
+ klass.find_by_enumerator!(enumerator).id
+ end
{attribute => id}
end
View
29 test/unit/enumerate_by_test.rb
@@ -65,16 +65,13 @@ def test_should_require_a_unique_name
class EnumerationWithRecordsTest < ActiveRecord::TestCase
def setup
@red = create_color(:name => 'red')
+ @green = create_color(:name => 'green')
end
def test_should_index_by_enumerator
assert_equal @red, Color['red']
end
- def test_should_raise_exception_for_invalid_index
- assert_raise(ActiveRecord::RecordNotFound) {Color['white']}
- end
-
def test_should_allow_finding_by_enumerator
assert_equal @red, Color.find_by_enumerator('red')
end
@@ -86,6 +83,30 @@ def test_should_allow_finding_by_enumerator_with_nil
def test_should_find_nothing_if_finding_by_unknown_enumerator
assert_nil Color.find_by_enumerator('invalid')
end
+
+ def test_should_raise_exception_for_invalid_index
+ assert_raise(ActiveRecord::RecordNotFound) {Color['white']}
+ end
+
+ def test_should_allow_finding_all_by_enumerator
+ assert_equal [@red, @green], Color.find_all_by_enumerator(['red', 'green'])
+ end
+
+ def test_should_allow_finding_all_by_enumerator_with_nil
+ assert_equal [], Color.find_all_by_enumerator(nil)
+ end
+
+ def test_should_find_nothing_if_finding_all_by_unknown_enumerator
+ assert_equal [], Color.find_all_by_enumerator('invalid')
+ end
+
+ def test_should_raise_exception_find_finding_all_by_unknown_enumerator!
+ assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!('invalid') }
+ end
+
+ def test_should_raise_exception_if_only_some_found_when_finding_all_by_enumerator!
+ assert_raise(ActiveRecord::RecordNotFound) { Color.find_all_by_enumerator!(['red', 'invalid']) }
+ end
end
class EnumerationAfterBeingCreatedTest < ActiveRecord::TestCase
Please sign in to comment.
Something went wrong with that request. Please try again.