Module: CompositePrimaryKeys::ActiveRecord::FinderMethods
- Included in:
- CompositeRelation
- Defined in:
- lib/composite_primary_keys/relation/finder_methods.rb
Instance Method Summary collapse
- #apply_join_dependency(eager_loading: group_values.empty?) ⇒ Object
- #construct_relation_for_exists(conditions) ⇒ Object
-
#find_one(id) ⇒ Object
def last(limit = nil) return find_last(limit) if loaded? || has_limit_or_offset?.
- #find_some(ids) ⇒ Object
- #find_some_ordered(ids) ⇒ Object
- #find_with_ids(*ids) ⇒ Object
- #limited_ids_for(relation) ⇒ Object
- #ordered_relation ⇒ Object
Instance Method Details
#apply_join_dependency(eager_loading: group_values.empty?) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 4 def apply_join_dependency(eager_loading: group_values.empty?) join_dependency = construct_join_dependency(eager_load_values + includes_values, Arel::Nodes::OuterJoin) relation = except(:includes, :eager_load, :preload).joins!(join_dependency) if eager_loading && !using_limitable_reflections?(join_dependency.reflections) if has_limit_or_offset? limited_ids = limited_ids_for(relation) # CPK # limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids) limited_ids.empty? ? relation.none! : relation.where!(cpk_in_predicate(table, self.primary_keys, limited_ids)) end relation.limit_value = relation.offset_value = nil end if block_given? yield relation, join_dependency else relation end end |
#construct_relation_for_exists(conditions) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 50 def construct_relation_for_exists(conditions) conditions = sanitize_forbidden_attributes(conditions) if distinct_value && offset_value relation = except(:order).limit!(1) else relation = except(:select, :distinct, :order)._select!(::ActiveRecord::FinderMethods::ONE_AS_ONE).limit!(1) end case conditions # CPK when CompositePrimaryKeys::CompositeKeys relation = relation.where(cpk_id_predicate(table, primary_key, conditions)) # CPK when Array pk_length = @klass.primary_keys.length if conditions.length == pk_length # E.g. conditions = ['France', 'Paris'] return self.construct_relation_for_exists(conditions.to_composite_keys) else # Assume that conditions contains where relation relation = relation.where(conditions) end when Array, Hash relation.where!(conditions) unless conditions.empty? else relation.where!(primary_key => conditions) unless conditions == :none end relation end |
#find_one(id) ⇒ Object
def last(limit = nil)
return find_last(limit) if loaded? || has_limit_or_offset?
result = limit(limit || 1)
# CPK
# result.order!(table[primary_key]) if order_values.empty? && primary_key
if order_values.empty? && primary_key
if composite?
result.order!(primary_keys.map { |pk| table[pk].asc })
elsif
result.order!(table[primary_key])
end
end
result = result.reverse_order!
limit ? result.reverse : result.first
rescue ::ActiveRecord::IrreversibleOrderError
ActiveSupport::Deprecation.warn(<<-WARNING.squish)
Finding a last element by loading the relation when SQL ORDER
can not be reversed is deprecated.
Rails 5.1 will raise ActiveRecord::IrreversibleOrderError in this case.
Please call `to_a.last` if you still want to load the relation.
WARNING
find_last(limit)
end
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 135 def find_one(id) if ::ActiveRecord::Base === id raise ArgumentError, <<-MSG.squish You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`. MSG end # CPK #relation = where(primary_key => id) relation = where(cpk_id_predicate(table, primary_keys, id)) record = relation.take raise_record_not_found_exception!(id, 0, 1) unless record record end |
#find_some(ids) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 153 def find_some(ids) # CPK if composite? ids = if ids.length == 1 CompositePrimaryKeys::CompositeKeys.parse(ids.first) else ids.to_composite_keys end end return find_some_ordered(ids) unless order_values.present? # CPK # result = where(primary_key => ids).to_a result = if composite? result = where(cpk_in_predicate(table, primary_keys, ids)).to_a else result = where(primary_key => ids).to_a end expected_size = if limit_value && ids.size > limit_value limit_value else ids.size end # 11 ids with limit 3, offset 9 should give 2 results. if offset_value && (ids.size - offset_value < expected_size) expected_size = ids.size - offset_value end if result.size == expected_size result else raise_record_not_found_exception!(ids, result.size, expected_size) end end |
#find_some_ordered(ids) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 192 def find_some_ordered(ids) ids = ids.slice(offset_value || 0, limit_value || ids.size) || [] # CPK # result = except(:limit, :offset).where(primary_key => ids).records result = if composite? except(:limit, :offset).where(cpk_in_predicate(table, primary_keys, ids)).records else except(:limit, :offset).where(primary_key => ids).records end if result.size == ids.size pk_type = @klass.type_for_attribute(primary_key) records_by_id = result.index_by(&:id) # CPK # ids.map { |id| records_by_id.fetch(pk_type.cast(id)) } if composite? ids.map do |id| typecasted_id = primary_keys.zip(id).map do |col, val| @klass.type_for_attribute(col).cast(val) end records_by_id.fetch(typecasted_id) end else ids.map { |id| records_by_id.fetch(pk_type.cast(id)) } end else raise_record_not_found_exception!(ids, result.size, ids.size) end end |
#find_with_ids(*ids) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 81 def find_with_ids(*ids) raise UnknownPrimaryKey.new(@klass) if primary_key.nil? # CPK # expects_array = ids.first.kind_of?(Array) ids = CompositePrimaryKeys.normalize(ids, @klass.primary_keys.length) expects_array = ids.flatten != ids.flatten(1) return ids.first if expects_array && ids.first.empty? # CPK # ids = ids.flatten.compact.uniq ids = expects_array ? ids.first : ids model_name = @klass.name case ids.size when 0 = "Couldn't find #{model_name} without an ID" raise ::ActiveRecord::RecordNotFound.new(, model_name, primary_key) when 1 result = find_one(ids.first) expects_array ? [ result ] : result else find_some(ids) end end |
#limited_ids_for(relation) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 26 def limited_ids_for(relation) # CPK # values = @klass.connection.columns_for_distinct( # connection.column_name_from_arel_node(table[primary_key]), # relation.order_values # ) columns = @klass.primary_keys.map do |key| connection.visitor.compile(table[key]) end values = @klass.connection.columns_for_distinct(columns, relation.order_values) relation = relation.except(:select).select(values).distinct! id_rows = skip_query_cache_if_necessary { @klass.connection.select_all(relation.arel, "SQL") } # CPK #id_rows.map { |row| row[primary_key] } id_rows.map do |row| @klass.primary_keys.map do |key| row[key] end end end |
#ordered_relation ⇒ Object
224 225 226 227 228 229 230 231 232 |
# File 'lib/composite_primary_keys/relation/finder_methods.rb', line 224 def ordered_relation if order_values.empty? && (implicit_order_column || primary_key) # CPK # order(table[implicit_order_column || primary_key].asc) order(Array(implicit_order_column || primary_key).map {|key| table[key].asc}) else self end end |