Class: Predicates::Unique
Overview
Describes an attribute as being unique, possibly within a certain scope.
Options
-
:scope [array] - a list of other fields that define the context for uniqueness. it’s like defining a multi-column uniqueness constraint.
-
:case_sensitive [boolean, default false] - whether case matters for uniqueness.
Examples
field_is_unique :case_sensitive => true
field_is_unique :scope => [:other_field, :another_other_field]
Instance Attribute Summary collapse
-
#case_sensitive ⇒ Object
Returns the value of attribute case_sensitive.
-
#scope ⇒ Object
Returns the value of attribute scope.
Attributes inherited from Base
#full_message, #or_empty, #validate_if, #validate_on
Instance Method Summary collapse
- #error_message ⇒ Object
-
#initialize(attribute, options = {}) ⇒ Unique
constructor
A new instance of Unique.
- #validate(value, record) ⇒ Object
Methods inherited from Base
#allow_empty?, #error, #error_binds, #normalize, #to_human
Constructor Details
#initialize(attribute, options = {}) ⇒ Unique
Returns a new instance of Unique.
14 15 16 17 18 19 20 |
# File 'lib/predicates/unique.rb', line 14 def initialize(attribute, = {}) defaults = { :scope => [], :case_sensitive => false } super attribute, defaults.merge() end |
Instance Attribute Details
#case_sensitive ⇒ Object
Returns the value of attribute case_sensitive.
11 12 13 |
# File 'lib/predicates/unique.rb', line 11 def case_sensitive @case_sensitive end |
#scope ⇒ Object
Returns the value of attribute scope.
12 13 14 |
# File 'lib/predicates/unique.rb', line 12 def scope @scope end |
Instance Method Details
#error_message ⇒ Object
22 23 24 |
# File 'lib/predicates/unique.rb', line 22 def @error_message || :taken end |
#validate(value, record) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/predicates/unique.rb', line 26 def validate(value, record) klass = record.class # merge all the scope fields with this one. they must all be unique together. # no special treatment -- case sensitivity applies to all or none. values = [scope].flatten.collect{ |attr| [attr, record.send(attr)] } values << [@attribute, value] sql = values.map do |(attr, attr_value)| comparison_for(attr, attr_value, klass) end unless record.new_record? sql << klass.send(:sanitize_sql, ["#{klass.quoted_table_name}.#{klass.primary_key} <> ?", record.id]) end !klass.where(sql.join(" AND ")).exists? end |