Module: Switchman::ActiveRecord::SpawnMethods

Defined in:
lib/switchman/active_record/spawn_methods.rb

Instance Method Summary collapse

Instance Method Details

#merge(r) ⇒ Object



46
47
48
49
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
80
81
82
# File 'lib/switchman/active_record/spawn_methods.rb', line 46

def merge(r)
  return self unless r
  return super unless r.is_a?(Relation)

  # have to figure out shard stuff *before* conditions are merged
  final_shard_value, final_primary_shard, final_shard_source_value = shard_values_for_merge(r)

  return super unless final_shard_source_value

  if !final_shard_value
    result = super
    result.shard_source_value = final_shard_source_value
    return result
  end

  return none if final_shard_value == []

  # change the primary shard if necessary before merging
  result = if primary_shard != final_primary_shard && r.primary_shard != final_primary_shard
             lhs = shard(final_primary_shard)
             r = r.shard(final_primary_shard)
             lhs.merge(r)
           elsif primary_shard != final_primary_shard
             lhs = shard(final_primary_shard)
             lhs.merge(r)
           elsif r.primary_shard != final_primary_shard
             r = r.shard(final_primary_shard)
             super(r)
           else
             super
           end

  result.shard_value = final_shard_value
  result.shard_source_value = final_shard_source_value

  result
end

#merge!(r) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/switchman/active_record/spawn_methods.rb', line 84

def merge!(r)
  return super unless r.is_a?(::ActiveRecord::Relation)

  # have to figure out shard stuff *before* conditions are merged
  final_shard_value, final_primary_shard, final_shard_source_value = shard_values_for_merge(r)

  return super unless final_shard_source_value

  if !final_shard_value
    super
    self.shard_source_value = final_shard_source_value
    return self
  end

  return none! if final_shard_value == []

  # change the primary shard if necessary before merging
  if primary_shard != final_primary_shard && r.primary_shard != final_primary_shard
    shard!(final_primary_shard)
    r = r.shard(final_primary_shard)
    super(r)
  elsif primary_shard != final_primary_shard
    shard!(final_primary_shard)
    super(r)
  elsif r.primary_shard != final_primary_shard
    r = r.shard(final_primary_shard)
    super(r)
  else
    super
  end

  self.shard_value = final_shard_value
  self.shard_source_value = final_shard_source_value

  self
end

#shard_values_for_merge(r) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/switchman/active_record/spawn_methods.rb', line 4

def shard_values_for_merge(r)
  if shard_value != r.shard_value
    if r.shard_source_value == :implicit
      final_shard_value = shard_value
      final_primary_shard = primary_shard
      final_shard_source_value = shard_source_value
    elsif shard_source_value == :implicit
      final_shard_value = r.shard_value
      final_primary_shard = r.primary_shard
      final_shard_source_value = r.shard_source_value
    else
      final_shard_source_value = [:explicit, :association].detect do |source_value|
        shard_source_value == source_value || r.shard_source_value == source_value
      end
      raise "unknown shard_source_value" unless final_shard_source_value

      # have to merge shard_value
      lhs_shard_value = all_shards
      rhs_shard_value = r.all_shards
      if (::ActiveRecord::Relation === lhs_shard_value &&
          ::ActiveRecord::Relation === rhs_shard_value)
        final_shard_value = lhs_shard_value.merge(rhs_shard_value)
        final_primary_shard = Shard.default
      else
        final_shard_value = lhs_shard_value.to_a & rhs_shard_value.to_a
        final_primary_shard = final_shard_value.first
        final_shard_value = final_shard_value.first if final_shard_value.length == 1
      end
    end
  elsif shard_source_value != r.shard_source_value
    final_shard_source_value = [:explicit, :association, :implicit].detect do |source_value|
      shard_source_value == source_value || r.shard_source_value == source_value
    end
    raise "unknown shard_source_value" unless final_shard_source_value
  else
    # nothing fancy
  end

  [final_shard_value, final_primary_shard, final_shard_source_value]
end