Module: SmartEnum::ActiveRecordCompatibility::QueryMethods
- Defined in:
- lib/smart_enum/active_record_compatibility.rb
Overview
Simulate ActiveRecord Query API
Constant Summary collapse
- STRING =
[String].freeze
- SYMBOL =
[Symbol].freeze
- BOOLEAN =
[TrueClass, FalseClass].freeze
- INTEGER =
[Integer].freeze
- BIG_DECIMAL =
[BigDecimal].freeze
Instance Method Summary collapse
- #all ⇒ Object
-
#cast_primary_key(id_input) ⇒ Object
Given an “id-like” parameter (usually the first argument to find), cast it to the same type used to index the PK lookup hash.
-
#cast_query_attrs(raw_attrs) ⇒ Object
Ensure that the attrs we query by are compatible with the internal types, casting where possible.
- #count ⇒ Object
- #find(id, raise_on_missing: true) ⇒ Object
- #find_by(uncast_attrs) ⇒ Object
- #find_by!(attrs) ⇒ Object
- #first(num = nil) ⇒ Object
- #last(num = nil) ⇒ Object
- #none ⇒ Object
- #where(uncast_attrs) ⇒ Object
Instance Method Details
#all ⇒ Object
104 105 106 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 104 def all values end |
#cast_primary_key(id_input) ⇒ Object
Given an “id-like” parameter (usually the first argument to find), cast it to the same type used to index the PK lookup hash.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 173 def cast_primary_key(id_input) return if id_input == nil id_attribute = attribute_set[:id] fail "no :id attribute defined on #{self}" if !id_attribute types = id_attribute.types # if the type is already compatible, return it. return id_input if types.any? { |t| id_input.instance_of?(t) } case types when INTEGER then Integer(id_input) when STRING then id_input.to_s when SYMBOL then id_input.to_s.to_sym else fail "incompatible type: got #{id_input.class}, need #{types.inspect} or something castable to that" end end |
#cast_query_attrs(raw_attrs) ⇒ Object
Ensure that the attrs we query by are compatible with the internal types, casting where possible. This allows us to e.g.
find_by(id: '1', key: :blah)
even when types differ like we can in ActiveRecord.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 137 def cast_query_attrs(raw_attrs) SmartEnum::Utilities.symbolize_hash_keys(raw_attrs).each_with_object({}) do |(k, v), new_attrs| if v.instance_of?(Array) fail "SmartEnum can't query with array arguments yet. Got #{raw_attrs.inspect}" end if (attr_def = attribute_set[k]) if attr_def.types.any?{|type| v.instance_of?(type) } # No need to cast new_attrs[k] = v elsif (v.nil? && attr_def.types != BOOLEAN) # Querying by nil is a legit case, unless the type is boolean new_attrs[k] = v elsif attr_def.types == STRING new_attrs[k] = String(v) elsif attr_def.types == INTEGER if v.instance_of?(String) && v.empty? # support querying by (id: '') new_attrs[k] = nil else new_attrs[k] = Integer(v) end elsif attr_def.types == BOOLEAN # TODO should we treat "f", 0, etc as false? new_attrs[k] = !!v elsif attr_def.types == BIG_DECIMAL new_attrs[k] = BigDecimal(v) else fail "Passed illegal query arguments for #{k}: #{v} is a #{v.class}, need #{attr_def.types} or a cast rule (got #{raw_attrs.inspect})" end else fail "#{k} is not an attribute of #{self}! (got #{raw_attrs.inspect})" end end end |
#count ⇒ Object
124 125 126 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 124 def count values.count end |
#find(id, raise_on_missing: true) ⇒ Object
74 75 76 77 78 79 80 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 74 def find(id, raise_on_missing: true) self[cast_primary_key(id)].tap do |result| if !result && raise_on_missing fail ActiveRecord::RecordNotFound.new("Couldn't find #{self} with 'id'=#{id}") end end end |
#find_by(uncast_attrs) ⇒ Object
82 83 84 85 86 87 88 89 90 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 82 def find_by(uncast_attrs) attrs = cast_query_attrs(uncast_attrs) if attrs.size == 1 && attrs.has_key?(:id) return find(attrs[:id], raise_on_missing: false) end all.detect do |instance| instance.attributes.slice(*attrs.keys) == attrs end end |
#find_by!(attrs) ⇒ Object
92 93 94 95 96 97 98 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 92 def find_by!(attrs) find_by(attrs).tap do |result| if !result fail ActiveRecord::RecordNotFound.new("Couldn't find #{self} with #{attrs.inspect}") end end end |
#first(num = nil) ⇒ Object
108 109 110 111 112 113 114 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 108 def first(num=nil) if num values.first(num) else values.first end end |
#last(num = nil) ⇒ Object
116 117 118 119 120 121 122 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 116 def last(num=nil) if num values.last(num) else values.last end end |
#none ⇒ Object
100 101 102 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 100 def none [] end |
#where(uncast_attrs) ⇒ Object
67 68 69 70 71 72 |
# File 'lib/smart_enum/active_record_compatibility.rb', line 67 def where(uncast_attrs) attrs = cast_query_attrs(uncast_attrs) all.select do |instance| instance.attributes.slice(*attrs.keys) == attrs end.tap(&:freeze) end |