Class: Lyra::Projections::CachedRelation

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/lyra/projections/cached_relation.rb

Overview

ActiveRecord::Relation-like wrapper for cached projection results.

Enables method chaining on cached results so that code written for ActiveRecord works transparently in disabled projections mode.

Usage:

relation = CachedRelation.new(User, records)
relation.where(status: "active").order(:name).limit(10)

Defined Under Namespace

Classes: WhereChain

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class, records = []) ⇒ CachedRelation

Returns a new instance of CachedRelation.



19
20
21
22
# File 'lib/lyra/projections/cached_relation.rb', line 19

def initialize(model_class, records = [])
  @model_class = model_class
  @records = records.to_a
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, **kwargs, &block) ⇒ Object



571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
# File 'lib/lyra/projections/cached_relation.rb', line 571

def method_missing(method_name, *args, **kwargs, &block)
  # Try to delegate to model class scopes
  if model_class.respond_to?(method_name)
    # Execute the scope on a bare unscoped relation to get the where conditions
    # This works because scopes add where clauses to the relation
    begin
      # Temporarily bypass Lyra's read overrides so scope calls go through AR
      # Without this, scope lambdas that call `where(...)` would hit our override
      # and return CachedRelation instead of building AR conditions
      Thread.current[:lyra_bypass_read_override] = true
      base_relation = model_class.unscoped
      scope_result = base_relation.public_send(method_name, *args, **kwargs, &block)
    rescue Lyra::StrictDataAccessViolation
      # Don't swallow strict data access violations - these are intentional framework errors
      raise
    rescue => e
      Rails.logger.debug("Lyra::CachedRelation: Could not execute scope #{method_name} - #{e.message}")
      return self
    ensure
      Thread.current[:lyra_bypass_read_override] = nil
    end

    if scope_result.is_a?(ActiveRecord::Relation)
      # Extract where conditions from the scope result
      where_hash = extract_where_conditions(scope_result)
      if where_hash.present?
        return where(where_hash)
      end
    end

    # Fallback: return self to allow chaining
    self
  else
    super
  end
end

Instance Attribute Details

#model_class ⇒ Object (readonly)

Returns the value of attribute model_class.



17
18
19
# File 'lib/lyra/projections/cached_relation.rb', line 17

def model_class
  @model_class
end

#records ⇒ Object (readonly)

Returns the value of attribute records.



17
18
19
# File 'lib/lyra/projections/cached_relation.rb', line 17

def records
  @records
end

Instance Method Details

#[](index) ⇒ Object



40
41
42
# File 'lib/lyra/projections/cached_relation.rb', line 40

def [](index)
  @records[index]
end

#_exec_scope(*args, &block) ⇒ Object

Called by AR when executing scopes Rails passes scope arguments and the scope body block



547
548
549
550
551
552
553
554
# File 'lib/lyra/projections/cached_relation.rb', line 547

def _exec_scope(*args, &block)
  # Execute the scope block in our context
  # The block typically calls methods like `where`, `order`, etc.
  result = instance_exec(*args, &block)

  # Return the result if it's a CachedRelation, otherwise self
  result.is_a?(CachedRelation) ? result : self
end

#_scoping(skip_inherited_scope = false, full = nil, all_queries: nil, &block) ⇒ Object



562
563
564
# File 'lib/lyra/projections/cached_relation.rb', line 562

def _scoping(skip_inherited_scope = false, full = nil, all_queries: nil, &block)
  scoping(skip_inherited_scope, full, all_queries: all_queries, &block)
end

#alias_tracker ⇒ Object

=========================================================================

AR internal methods for association scope building These are needed for belongs_to/has_many association loading



339
340
341
342
343
# File 'lib/lyra/projections/cached_relation.rb', line 339

def alias_tracker
  @alias_tracker ||= ActiveRecord::Associations::AliasTracker.create(
    model_class.connection_pool, table.name, []
  )
end

#all ⇒ Object

=========================================================================

Scoping methods



318
319
320
# File 'lib/lyra/projections/cached_relation.rb', line 318

def all
  self
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/lyra/projections/cached_relation.rb', line 66

def any?(&block)
  block_given? ? @records.any?(&block) : @records.any?
end

#average(column_name) ⇒ Object



470
471
472
473
474
# File 'lib/lyra/projections/cached_relation.rb', line 470

def average(column_name)
  values = @records.map { |r| r.send(column_name) }.compact
  return nil if values.empty?
  values.sum.to_f / values.size
end

#bind_attribute(name, value) ⇒ Object



403
404
405
# File 'lib/lyra/projections/cached_relation.rb', line 403

def bind_attribute(name, value)
  self
end

#blank? ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/lyra/projections/cached_relation.rb', line 86

def blank?
  @records.blank?
end

#connection ⇒ Object



349
350
351
# File 'lib/lyra/projections/cached_relation.rb', line 349

def connection
  model_class.connection
end

#count(column_name = nil, &block) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/lyra/projections/cached_relation.rb', line 52

def count(column_name = nil, &block)
  if block_given?
    @records.count(&block)
  elsif column_name
    @records.count { |r| r.send(column_name).present? }
  else
    @records.size
  end
end

#current_page ⇒ Object



238
239
240
# File 'lib/lyra/projections/cached_relation.rb', line 238

def current_page
  @current_page || 1
end

#distinct ⇒ Object



268
269
270
# File 'lib/lyra/projections/cached_relation.rb', line 268

def distinct
  self.class.new(model_class, @records.uniq)
end

#each(&block) ⇒ Object

=========================================================================

Enumerable / Array-like interface



28
29
30
# File 'lib/lyra/projections/cached_relation.rb', line 28

def each(&block)
  @records.each(&block)
end

#eager_load(*args) ⇒ Object



291
292
293
294
# File 'lib/lyra/projections/cached_relation.rb', line 291

def eager_load(*args)
  # Same as preload - no-op for cached records
  self
end

#empty? ⇒ Boolean

Returns:

  • (Boolean)


62
63
64
# File 'lib/lyra/projections/cached_relation.rb', line 62

def empty?
  @records.empty?
end

#except(*skips) ⇒ Object



411
412
413
# File 'lib/lyra/projections/cached_relation.rb', line 411

def except(*skips)
  self
end

#exists?(conditions = nil) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/lyra/projections/cached_relation.rb', line 146

def exists?(conditions = nil)
  case conditions
  when nil, false
    @records.any?
  when Integer, String
    @records.any? { |r| r.id.to_s == conditions.to_s }
  when Hash
    find_by(conditions).present?
  else
    @records.any?
  end
end

#extending(*modules, &block) ⇒ Object



386
387
388
# File 'lib/lyra/projections/cached_relation.rb', line 386

def extending(*modules, &block)
  self
end

#extending!(*modules, &block) ⇒ Object



381
382
383
384
# File 'lib/lyra/projections/cached_relation.rb', line 381

def extending!(*modules, &block)
  # No-op for cached relation - extensions are for AR scopes
  self
end

#extract_predicate_value(node) ⇒ Object



643
644
645
646
647
648
649
650
651
652
653
654
655
# File 'lib/lyra/projections/cached_relation.rb', line 643

def extract_predicate_value(node)
  case node
  when Arel::Nodes::Casted
    node.value
  when Arel::Nodes::BindParam
    # Rails 7+ bind params
    node.value.value_before_type_cast
  when NilClass
    nil
  else
    node.respond_to?(:value) ? node.value : node
  end
end

#extract_where_conditions(relation) ⇒ Object



608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
# File 'lib/lyra/projections/cached_relation.rb', line 608

def extract_where_conditions(relation)
  # Try to extract hash conditions from the relation's where clause
  return {} unless relation.respond_to?(:where_clause)

  where_clause = relation.where_clause
  return {} if where_clause.empty?

  # Rails 7+ stores conditions in predicates
  # Try to convert Arel predicates to a hash
  conditions = {}
  where_clause.send(:predicates).each do |predicate|
    case predicate
    when Arel::Nodes::Equality
      # Simple equality: column = value
      if predicate.left.respond_to?(:name)
        column = predicate.left.name.to_sym
        value = extract_predicate_value(predicate.right)
        conditions[column] = value
      end
    when Arel::Nodes::In
      # IN clause: column IN (values)
      if predicate.left.respond_to?(:name)
        column = predicate.left.name.to_sym
        values = predicate.right.map { |v| extract_predicate_value(v) }
        conditions[column] = values
      end
    end
  end

  conditions
rescue => e
  Rails.logger.debug("Lyra::CachedRelation: Could not extract where conditions - #{e.message}")
  {}
end

#find(id) ⇒ Object



126
127
128
129
130
131
132
# File 'lib/lyra/projections/cached_relation.rb', line 126

def find(id)
  record = @records.find { |r| r.id.to_s == id.to_s }
  record || raise(ActiveRecord::RecordNotFound.new(
    "Couldn't find #{model_class.name} with '#{model_class.primary_key}'=#{id}",
    model_class, model_class.primary_key, id
  ))
end

#find_by(attributes) ⇒ Object



134
135
136
137
138
# File 'lib/lyra/projections/cached_relation.rb', line 134

def find_by(attributes)
  @records.find do |record|
    attributes.all? { |key, value| matches_value?(record, key, value) }
  end
end

#find_by!(attributes) ⇒ Object



140
141
142
143
144
# File 'lib/lyra/projections/cached_relation.rb', line 140

def find_by!(attributes)
  find_by(attributes) || raise(ActiveRecord::RecordNotFound.new(
    "Couldn't find #{model_class.name}", model_class
  ))
end

#find_each(batch_size: 1000, &block) ⇒ Object

=========================================================================

Batching (simplified - all records are in memory)



513
514
515
# File 'lib/lyra/projections/cached_relation.rb', line 513

def find_each(batch_size: 1000, &block)
  each(&block)
end

#find_in_batches(batch_size: 1000) ⇒ Object



517
518
519
520
521
# File 'lib/lyra/projections/cached_relation.rb', line 517

def find_in_batches(batch_size: 1000)
  @records.each_slice(batch_size) do |batch|
    yield batch
  end
end

#first(limit = nil) ⇒ Object

=========================================================================

Finder methods



94
95
96
# File 'lib/lyra/projections/cached_relation.rb', line 94

def first(limit = nil)
  limit ? @records.first(limit) : @records.first
end

#first! ⇒ Object



118
119
120
# File 'lib/lyra/projections/cached_relation.rb', line 118

def first!
  first || raise(ActiveRecord::RecordNotFound.new("Couldn't find #{model_class.name}", model_class))
end

#ids ⇒ Object



494
495
496
# File 'lib/lyra/projections/cached_relation.rb', line 494

def ids
  pluck(:id)
end

#in_batches(of: 1000) ⇒ Object



523
524
525
526
527
# File 'lib/lyra/projections/cached_relation.rb', line 523

def in_batches(of: 1000)
  @records.each_slice(of) do |batch|
    yield self.class.new(model_class, batch)
  end
end

#includes(*args) ⇒ Object



286
287
288
289
# File 'lib/lyra/projections/cached_relation.rb', line 286

def includes(*args)
  # Same as preload - no-op for cached records
  self
end

#inspect ⇒ Object

=========================================================================

Inspection



533
534
535
# File 'lib/lyra/projections/cached_relation.rb', line 533

def inspect
  "#<#{self.class.name} [#{@records.map(&:inspect).join(', ')}]>"
end

#joins(*args) ⇒ Object



300
301
302
303
304
# File 'lib/lyra/projections/cached_relation.rb', line 300

def joins(*args)
  # Can't actually join - return self to allow chain to continue
  # Note: This may produce incorrect results for complex queries
  self
end

#joins_values ⇒ Object



353
354
355
# File 'lib/lyra/projections/cached_relation.rb', line 353

def joins_values
  []
end

#klass ⇒ Object



365
366
367
# File 'lib/lyra/projections/cached_relation.rb', line 365

def klass
  model_class
end

#last(limit = nil) ⇒ Object



98
99
100
# File 'lib/lyra/projections/cached_relation.rb', line 98

def last(limit = nil)
  limit ? @records.last(limit) : @records.last
end

#last! ⇒ Object



122
123
124
# File 'lib/lyra/projections/cached_relation.rb', line 122

def last!
  last || raise(ActiveRecord::RecordNotFound.new("Couldn't find #{model_class.name}", model_class))
end

#left_joins(*args) ⇒ Object



306
307
308
# File 'lib/lyra/projections/cached_relation.rb', line 306

def left_joins(*args)
  self
end

#left_outer_joins(*args) ⇒ Object



310
311
312
# File 'lib/lyra/projections/cached_relation.rb', line 310

def left_outer_joins(*args)
  self
end

#left_outer_joins_values ⇒ Object



357
358
359
# File 'lib/lyra/projections/cached_relation.rb', line 357

def left_outer_joins_values
  []
end

#length ⇒ Object



48
49
50
# File 'lib/lyra/projections/cached_relation.rb', line 48

def length
  size
end

#limit(count) ⇒ Object



210
211
212
# File 'lib/lyra/projections/cached_relation.rb', line 210

def limit(count)
  self.class.new(model_class, @records.first(count))
end

#limit!(value) ⇒ Object



373
374
375
# File 'lib/lyra/projections/cached_relation.rb', line 373

def limit!(value)
  self.class.new(model_class, @records.first(value))
end

#limit_value ⇒ Object



246
247
248
# File 'lib/lyra/projections/cached_relation.rb', line 246

def limit_value
  @per_page
end

#many? ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/lyra/projections/cached_relation.rb', line 78

def many?
  @records.size > 1
end

#maximum(column_name) ⇒ Object



480
481
482
# File 'lib/lyra/projections/cached_relation.rb', line 480

def maximum(column_name)
  @records.map { |r| r.send(column_name) }.compact.max
end

#merge(other, *rest) ⇒ Object



394
395
396
397
# File 'lib/lyra/projections/cached_relation.rb', line 394

def merge(other, *rest)
  # For association scopes, just return self since we already have filtered records
  self
end

#merge!(other, *rest) ⇒ Object



399
400
401
# File 'lib/lyra/projections/cached_relation.rb', line 399

def merge!(other, *rest)
  self
end

#minimum(column_name) ⇒ Object



476
477
478
# File 'lib/lyra/projections/cached_relation.rb', line 476

def minimum(column_name)
  @records.map { |r| r.send(column_name) }.compact.min
end

#none ⇒ Object



322
323
324
# File 'lib/lyra/projections/cached_relation.rb', line 322

def none
  self.class.new(model_class, [])
end

#none?(&block) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/lyra/projections/cached_relation.rb', line 70

def none?(&block)
  block_given? ? @records.none?(&block) : @records.none?
end

#not(conditions) ⇒ Object



185
186
187
188
189
190
# File 'lib/lyra/projections/cached_relation.rb', line 185

def not(conditions)
  filtered = @records.reject do |record|
    conditions.all? { |key, value| matches_value?(record, key, value) }
  end
  self.class.new(model_class, filtered)
end

#offset(count) ⇒ Object



214
215
216
# File 'lib/lyra/projections/cached_relation.rb', line 214

def offset(count)
  self.class.new(model_class, @records.drop(count))
end

#offset_value ⇒ Object



250
251
252
253
# File 'lib/lyra/projections/cached_relation.rb', line 250

def offset_value
  return 0 unless @current_page && @per_page
  (@current_page - 1) * @per_page
end

#one?(&block) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/lyra/projections/cached_relation.rb', line 74

def one?(&block)
  block_given? ? @records.one?(&block) : @records.one?
end

#only(*keeps) ⇒ Object



415
416
417
# File 'lib/lyra/projections/cached_relation.rb', line 415

def only(*keeps)
  self
end

#order(*args) ⇒ Object



192
193
194
195
196
197
198
199
200
# File 'lib/lyra/projections/cached_relation.rb', line 192

def order(*args)
  return self if args.empty?

  sorted = @records.sort do |a, b|
    compare_for_order(a, b, args)
  end

  self.class.new(model_class, sorted)
end

#order!(*args) ⇒ Object



435
436
437
438
439
440
# File 'lib/lyra/projections/cached_relation.rb', line 435

def order!(*args)
  # In-place order modification
  return self if args.empty?
  @records = @records.sort { |a, b| compare_for_order(a, b, args) }
  self
end

#page(num) ⇒ Object

=========================================================================

Pagination support (Kaminari/WillPaginate compatibility)



222
223
224
225
226
# File 'lib/lyra/projections/cached_relation.rb', line 222

def page(num)
  @current_page = [num.to_i, 1].max
  @per_page ||= 25
  self
end

#per(num) ⇒ Object



228
229
230
231
# File 'lib/lyra/projections/cached_relation.rb', line 228

def per(num)
  @per_page = num.to_i
  paginated_records
end

#pick(*column_names) ⇒ Object



498
499
500
501
502
503
504
505
506
507
# File 'lib/lyra/projections/cached_relation.rb', line 498

def pick(*column_names)
  record = first
  return nil unless record

  if column_names.size == 1
    record.send(column_names.first)
  else
    column_names.map { |col| record.send(col) }
  end
end

#pluck(*column_names) ⇒ Object



484
485
486
487
488
489
490
491
492
# File 'lib/lyra/projections/cached_relation.rb', line 484

def pluck(*column_names)
  @records.map do |record|
    if column_names.size == 1
      record.send(column_names.first)
    else
      column_names.map { |col| record.send(col) }
    end
  end
end

#preload(*args) ⇒ Object

=========================================================================

Eager loading (no-ops for cached records - data is already in memory)



280
281
282
283
284
# File 'lib/lyra/projections/cached_relation.rb', line 280

def preload(*args)
  # Associations are already loaded or don't exist in cache
  # This is a no-op but allows the chain to continue
  self
end

#present? ⇒ Boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/lyra/projections/cached_relation.rb', line 82

def present?
  @records.present?
end

#readonly(value = true) ⇒ Object



330
331
332
# File 'lib/lyra/projections/cached_relation.rb', line 330

def readonly(value = true)
  self
end

#references(*args) ⇒ Object



296
297
298
# File 'lib/lyra/projections/cached_relation.rb', line 296

def references(*args)
  self
end

#reorder(*args) ⇒ Object



202
203
204
# File 'lib/lyra/projections/cached_relation.rb', line 202

def reorder(*args)
  order(*args)
end

#reselect(*args) ⇒ Object



442
443
444
# File 'lib/lyra/projections/cached_relation.rb', line 442

def reselect(*args)
  self
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Allow method_missing for scope delegation

Returns:

  • (Boolean)


567
568
569
# File 'lib/lyra/projections/cached_relation.rb', line 567

def respond_to_missing?(method_name, include_private = false)
  model_class.respond_to?(method_name) || super
end

#reverse_order ⇒ Object



206
207
208
# File 'lib/lyra/projections/cached_relation.rb', line 206

def reverse_order
  self.class.new(model_class, @records.reverse)
end

#rewhere(conditions) ⇒ Object



407
408
409
# File 'lib/lyra/projections/cached_relation.rb', line 407

def rewhere(conditions)
  where(conditions)
end

#scope_for_create ⇒ Object



369
370
371
# File 'lib/lyra/projections/cached_relation.rb', line 369

def scope_for_create
  {}
end

#scoping(skip_inherited_scope = false, full = nil, all_queries: nil) {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:



556
557
558
559
560
# File 'lib/lyra/projections/cached_relation.rb', line 556

def scoping(skip_inherited_scope = false, full = nil, all_queries: nil, &block)
  # Yield self for scoping blocks
  yield self if block_given?
  self
end

#second ⇒ Object



102
103
104
# File 'lib/lyra/projections/cached_relation.rb', line 102

def second
  @records[1]
end

#select(*args, &block) ⇒ Object



446
447
448
449
450
451
452
453
454
# File 'lib/lyra/projections/cached_relation.rb', line 446

def select(*args, &block)
  if block_given?
    # Enumerable select
    self.class.new(model_class, @records.select(&block))
  else
    # AR select (column selection) - return self since we have full records
    self
  end
end

#size ⇒ Object



44
45
46
# File 'lib/lyra/projections/cached_relation.rb', line 44

def size
  @records.size
end

#spawn ⇒ Object



390
391
392
# File 'lib/lyra/projections/cached_relation.rb', line 390

def spawn
  self.class.new(model_class, @records.dup)
end

#sum(column_name = nil, &block) ⇒ Object

=========================================================================

Aggregations



460
461
462
463
464
465
466
467
468
# File 'lib/lyra/projections/cached_relation.rb', line 460

def sum(column_name = nil, &block)
  if block_given?
    @records.sum(&block)
  elsif column_name
    @records.sum { |r| r.send(column_name).to_f }
  else
    0
  end
end

#table ⇒ Object



345
346
347
# File 'lib/lyra/projections/cached_relation.rb', line 345

def table
  model_class.arel_table
end

#take(limit = nil) ⇒ Object



110
111
112
# File 'lib/lyra/projections/cached_relation.rb', line 110

def take(limit = nil)
  limit ? @records.first(limit) : @records.first
end

#take! ⇒ Object



114
115
116
# File 'lib/lyra/projections/cached_relation.rb', line 114

def take!
  take || raise(ActiveRecord::RecordNotFound.new("Couldn't find #{model_class.name}", model_class))
end

#third ⇒ Object



106
107
108
# File 'lib/lyra/projections/cached_relation.rb', line 106

def third
  @records[2]
end

#to_a ⇒ Object



32
33
34
# File 'lib/lyra/projections/cached_relation.rb', line 32

def to_a
  @records.dup
end

#to_ary ⇒ Object



36
37
38
# File 'lib/lyra/projections/cached_relation.rb', line 36

def to_ary
  to_a
end

#to_s ⇒ Object



537
538
539
# File 'lib/lyra/projections/cached_relation.rb', line 537

def to_s
  inspect
end

#total_count ⇒ Object



242
243
244
# File 'lib/lyra/projections/cached_relation.rb', line 242

def total_count
  @records.size
end

#total_pages ⇒ Object



233
234
235
236
# File 'lib/lyra/projections/cached_relation.rb', line 233

def total_pages
  return 1 if @per_page.nil? || @per_page <= 0
  (@records.size.to_f / @per_page).ceil
end

#uniq ⇒ Object



272
273
274
# File 'lib/lyra/projections/cached_relation.rb', line 272

def uniq
  distinct
end

#unscoped ⇒ Object



326
327
328
# File 'lib/lyra/projections/cached_relation.rb', line 326

def unscoped
  self
end

#values ⇒ Object



377
378
379
# File 'lib/lyra/projections/cached_relation.rb', line 377

def values
  {}
end

#where(conditions = nil, *args) ⇒ Object

=========================================================================

Query methods (return new CachedRelation for chaining)



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/lyra/projections/cached_relation.rb', line 163

def where(conditions = nil, *args)
  return self if conditions.nil?

  # Handle where.not(...) chain
  return WhereChain.new(self) if conditions == :chain

  filtered = @records.select do |record|
    case conditions
    when Hash
      conditions.all? { |key, value| matches_value?(record, key, value) }
    when String
      # SQL string conditions - can't evaluate, return all
      # This is a limitation of the cached approach
      true
    else
      true
    end
  end

  self.class.new(model_class, filtered)
end

#where!(conditions) ⇒ Object



419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/lyra/projections/cached_relation.rb', line 419

def where!(conditions)
  # In-place where modification (for AR internal use)
  # Filter records and update @records directly
  return self if conditions.nil?

  @records = @records.select do |record|
    case conditions
    when Hash
      conditions.all? { |key, value| matches_value?(record, key, value) }
    else
      true
    end
  end
  self
end

#where_clause ⇒ Object



361
362
363
# File 'lib/lyra/projections/cached_relation.rb', line 361

def where_clause
  ActiveRecord::Relation::WhereClause.empty
end