active_record-framing 0.1.0.pre.9 → 0.1.0.pre.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c45ff57cff6a36c65d09cc5c6e33a8d394c0f35eb6097f64213e458d41d4509
4
- data.tar.gz: 8bd322afcc0c2406367c43354baa15f60291063fce86a91c8bb24dfaeaefd5f2
3
+ metadata.gz: 3470c754f26d19c299b29aed737299fc49be9e8b32ae738b241bf4f857f15aae
4
+ data.tar.gz: 347bc600be62caca146be5062c6244d3d91c6425d12576b6dab0908d7f5e6716
5
5
  SHA512:
6
- metadata.gz: ebfb3761c9c471e80b2b7e77d235f1b74c85dcbb185f470da6f6f8732489802ababfb31ee039680781afdfd5d353d7417e8e0e62e2408bc1010044a1c540cfeb
7
- data.tar.gz: faba924aef8072dc5c98a7bfc6e67decbadab3bc7eaa75b162c9de4a4410716bb89513124c0a27df1d8dc0a55c88507aa3883b5c01207330d4528bf818f55e56
6
+ metadata.gz: 59105768fd8a95a7dc826ca0a8708f05fac62e060a4556703ea6721b4ed8b4dbde6273faafa5e808757499c35f8dcd2825a745e29a768612c408a3bc3760374c
7
+ data.tar.gz: db85b4f5bc35430dfa888402ad5e3a3973efa8f36a2182f3b1781a5f8efa772febb2ea10a26c820c97be477ad4318532f74ede6459c76ad50f2656543b93df55
@@ -0,0 +1,14 @@
1
+ require 'active_record/framing/compat/arel'
2
+
3
+ case ::ActiveRecord.version
4
+ when Gem::Requirement.new('~> 4.2') # 4.2.x
5
+ require 'active_record/framing/compat/active_record_4_2'
6
+ when Gem::Requirement.new('~> 5.0.0') # 5.0.x
7
+ require 'active_record/framing/compat/active_record_5_0'
8
+ when Gem::Requirement.new('~> 5.0') # 5.1+
9
+ require 'active_record/framing/compat/active_record_5_1'
10
+ when Gem::Requirement.new('~> 6.0.0') # 6.0.x
11
+ require 'active_record/framing/compat/active_record_6_0'
12
+ else
13
+ raise NotImplementedError, "ActiveRecord::Framing does not support Rails #{::ActiveRecord.version}" unless ENV['EDGE_TESTING']
14
+ end
@@ -1,13 +1,19 @@
1
- {
2
- frames: {},
3
- reframe: {}
4
- }.each do |value_name, default_value|
5
- define_method("#{value_name}_values") do
6
- @values[value_name] || default_value
7
- end
8
- define_method("#{value_name}_values=") do |values|
9
- raise ImmutableRelation if @loaded
10
- check_cached_relation
11
- @values[value_name] = values
1
+ module ActiveRecord
2
+ module Framing
3
+ module QueryMethods
4
+ {
5
+ frames: {},
6
+ reframe: {}
7
+ }.each do |value_name, default_value|
8
+ define_method("#{value_name}_values") do
9
+ @values[value_name] || default_value
10
+ end
11
+ define_method("#{value_name}_values=") do |values|
12
+ raise ImmutableRelation if @loaded
13
+ check_cached_relation
14
+ @values[value_name] = values
15
+ end
16
+ end
17
+ end
12
18
  end
13
19
  end
@@ -1,12 +1,19 @@
1
- {
2
- frames: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH,
3
- reframe: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH
4
- }.each do |value_name, default_value|
5
- define_method("#{value_name}_values") do
6
- @values[value_name] || default_value
7
- end
8
- define_method("#{value_name}_values=") do |values|
9
- assert_mutability!
10
- @values[value_name] = values
1
+ module ActiveRecord
2
+ module Framing
3
+ module QueryMethods
4
+ {
5
+ frames: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH,
6
+ reframe: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH
7
+ }.each do |value_name, default_value|
8
+ define_method("#{value_name}_values") do
9
+ @values[value_name] || default_value
10
+ end
11
+ define_method("#{value_name}_values=") do |values|
12
+ assert_mutability!
13
+ @values[value_name] = values
14
+ end
15
+ end
16
+ end
11
17
  end
12
18
  end
19
+
@@ -1,12 +1,18 @@
1
- {
2
- frames: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH,
3
- reframe: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH
4
- }.each do |value_name, default_value|
5
- define_method("#{value_name}_values") do
6
- get_value(value_name)
1
+ module ActiveRecord
2
+ module Framing
3
+ module QueryMethods
4
+ {
5
+ frames: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH,
6
+ reframe: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH
7
+ }.each do |value_name, default_value|
8
+ define_method("#{value_name}_values") do
9
+ get_value(value_name)
10
+ end
11
+ define_method("#{value_name}_values=") do |value|
12
+ set_value(value_name, value)
13
+ end
14
+ ::ActiveRecord::QueryMethods::DEFAULT_VALUES[value_name] = default_value
15
+ end
16
+ end
7
17
  end
8
- define_method("#{value_name}_values=") do |value|
9
- set_value(value_name, value)
10
- end
11
- ::ActiveRecord::QueryMethods::DEFAULT_VALUES[value_name] = default_value
12
18
  end
@@ -0,0 +1,23 @@
1
+ module ActiveRecord
2
+ module Framing
3
+ module QueryMethods
4
+ {
5
+ frames: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH,
6
+ reframe: ::ActiveRecord::QueryMethods::FROZEN_EMPTY_HASH
7
+ }.each do |value_name, default_value|
8
+ ::ActiveRecord::QueryMethods::DEFAULT_VALUES[value_name] = default_value
9
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
10
+ def #{value_name}_values # def frames_values
11
+ default = ::ActiveRecord::QueryMethods::DEFAULT_VALUES[:#{value_name}] # default = DEFAULT_VALUES[:frames]
12
+ @values.fetch(:#{value_name}, default) # @values.fetch(:frames, default)
13
+ end # end
14
+
15
+ def #{value_name}_values=(value) # def frames_values=(value)
16
+ assert_mutability! # assert_mutability!
17
+ @values[:#{value_name}] = value # @values[:frames] = value
18
+ end # end
19
+ CODE
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ case Gem::Version.new(Arel::VERSION)
2
+ when Gem::Requirement.new('>= 7.0')
3
+ Arel::Table.class_eval do
4
+ def engine
5
+ type_caster.send(:types)
6
+ end
7
+
8
+ def engine=(value)
9
+ @type_caster = value.type_caster
10
+ end
11
+ end
12
+
13
+ Arel::Nodes::TableAlias.class_eval do
14
+ def engine
15
+ left.send(:type_caster)
16
+ end
17
+ end
18
+ else
19
+ Arel::Table.class_eval do
20
+ def engine=(value)
21
+ @engine = value
22
+ end
23
+ end
24
+ end
@@ -10,6 +10,8 @@ module ActiveRecord
10
10
  def self.prepended(subclass)
11
11
  subclass.singleton_class.class_eval do
12
12
  alias_method :unframed_all, :all
13
+ # NOTE: not for 4.2
14
+ alias_method :unframed_scope_for_association, :scope_for_association if subclass.respond_to?(:scope_for_association)
13
15
 
14
16
  # Subclasses need to be able to call its parent's
15
17
  protected :relation
@@ -32,6 +34,13 @@ module ActiveRecord
32
34
  @disabled == true
33
35
  end
34
36
 
37
+ class Foo
38
+
39
+ def self.whatever
40
+ @whatever
41
+ end
42
+ end
43
+
35
44
  module ClassMethods # :nodoc:
36
45
  def current_frame
37
46
  FrameRegistry.value_for(:current_frame, self)
@@ -40,6 +49,16 @@ module ActiveRecord
40
49
  def current_frame=(frame)
41
50
  FrameRegistry.set_value_for(:current_frame, self, frame)
42
51
  end
52
+
53
+ def const_missing(const_name)
54
+ case const_name
55
+ when *frames.keys
56
+ columns
57
+ frames[const_name].call
58
+ else
59
+ super
60
+ end
61
+ end
43
62
  end
44
63
 
45
64
  # This class stores the +:current_frame+ and +:ignore_default_frame+ values
@@ -49,7 +49,7 @@ module ActiveRecord
49
49
  # The ignore_default_frame flag is used to prevent an infinite recursion
50
50
  # situation where a default frame references a frame which has a default
51
51
  # frame which references a frame...
52
- def ignore_default_frame
52
+ def evaluate_default_frame
53
53
  return if ignore_default_frame?
54
54
  self.ignore_default_frame = true
55
55
  yield
@@ -57,6 +57,13 @@ module ActiveRecord
57
57
  self.ignore_default_frame = false
58
58
  end
59
59
 
60
+ def default_arel_table
61
+ @default_arel_table ||= arel_table.dup.tap do |at|
62
+ at.name = sovereign_table_name
63
+ end
64
+ # @default_arel_table ||= arel_table.alias(sovereign_table_name)
65
+ end
66
+
60
67
  protected
61
68
 
62
69
  def build_frame(frames, arel_table, base_rel = nil, &block)
@@ -68,6 +75,7 @@ module ActiveRecord
68
75
  end
69
76
 
70
77
  relation.frame!(Arel::Nodes::As.new(arel_table, cte_relation.arel)).tap do |rel|
78
+ rel.table = arel_table
71
79
  extension = Module.new(&block) if block_given?
72
80
  rel.extending!(extension) if extension
73
81
  end
@@ -120,7 +128,7 @@ module ActiveRecord
120
128
  # # Should return a frame, you can call 'super' here etc.
121
129
  # end
122
130
  # end
123
- def default_frame(frame = nil) # :doc:
131
+ def default_frame(frame_name = nil, frame: nil) # :doc:
124
132
  frame = Proc.new if block_given?
125
133
 
126
134
  if frame.is_a?(Relation) || !frame.respond_to?(:call)
@@ -131,9 +139,31 @@ module ActiveRecord
131
139
  "self.default_frame.)"
132
140
  end
133
141
 
142
+ # TODO: Include default_scopes?
143
+ # frame(:unframed)
144
+
145
+ # default_arel_table.tap do |at|
146
+ # at.name = frame_name
147
+ # end if frame_name
148
+
134
149
  self.default_frames += [frame]
135
150
  end
136
151
 
152
+ def sovereign_table_name
153
+ # TODO: Use compute_table_name to disambiguate between users and admins
154
+ if superclass < ::ActiveRecord::Base && table_name == superclass.table_name
155
+ begin
156
+ orig, superclass.abstract_class = superclass.abstract_class, true
157
+ # return compute_table_name
158
+ return table_name
159
+ ensure
160
+ superclass.abstract_class = orig
161
+ end
162
+ end
163
+ # compute_table_name
164
+ table_name
165
+ end
166
+
137
167
  def build_default_frame(base_rel = nil)
138
168
  return if abstract_class?
139
169
 
@@ -143,14 +173,15 @@ module ActiveRecord
143
173
 
144
174
  if default_frame_override
145
175
  # The user has defined their own default frame method, so call that
146
- ignore_default_frame do
176
+ evaluate_default_frame do
147
177
  if (frame = default_frame)
148
178
  (base_rel ||= relation).frame!(frame)
149
179
  end
150
180
  end
151
181
  elsif default_frames.any?
152
- ignore_default_frame do
153
- cte_table = Arel::Table.new(table_name)
182
+ evaluate_default_frame do
183
+ # cte_table = Arel::Table.new(table_name)
184
+ cte_table = default_arel_table
154
185
  build_frame(default_frames, cte_table, base_rel || relation)
155
186
  end
156
187
  end
@@ -0,0 +1,26 @@
1
+ module ActiveRecord
2
+ module Framing
3
+ module JoinDependency
4
+ def table_aliases_for(parent, node)
5
+ super.tap do |list|
6
+ list.zip(node.reflection.chain).each do |aliaz, reflection|
7
+ engine = @join_root.base_klass.reframe_values.fetch(reflection.name) { reflection }.klass
8
+ fix_table_engine(aliaz, engine)
9
+ end
10
+ end
11
+ end
12
+
13
+ def fix_table_engine(table, engine)
14
+ case table
15
+ when ::Arel::Nodes::TableAlias
16
+ table.left.engine = engine # if table.left.engine == ::ActiveRecord::Base
17
+ table.left.name = engine.table_name
18
+ else
19
+ table.engine = engine # if table.engine == ::ActiveRecord::Base
20
+ table.name = engine.table_name
21
+ end
22
+ # binding.pry if table.name == "users"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ module ActiveRecord
2
+ module Framing
3
+ class ModelProxy < SimpleDelegator
4
+
5
+ def initialize(klass, table)
6
+ @table = table
7
+ super(klass)
8
+ end
9
+
10
+ def unscoped
11
+ __getobj__.unscoped.tap do |rel|
12
+ rel.instance_variable_set(:@table, @table)
13
+ end
14
+ end
15
+
16
+ # NOTE: Arel 8.x / Rails 5.1 compatibility
17
+ # Method exists on AR::Model, but default value for table
18
+ # is scoped incorrectly without this proxy override
19
+ def arel_attribute(column_name, table = arel_table)
20
+ super
21
+ end
22
+
23
+ def table=(value)
24
+ @table = value
25
+ end
26
+
27
+ def table_name
28
+ @table.name
29
+ end
30
+
31
+ def reframe_values
32
+ @reframe_values ||= {}
33
+ end
34
+
35
+ def reframe_values=(value)
36
+ @reframe_values = value
37
+ end
38
+
39
+ def send(*args)
40
+ __getobj__.send(*args)
41
+ end
42
+
43
+ def arel_table
44
+ @table
45
+ end
46
+
47
+ # Might not need this
48
+ def is_a?(obj)
49
+ __getobj__.is_a?(obj)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -18,23 +18,34 @@ module ActiveRecord
18
18
  # You can define a frame that applies to all finders using
19
19
  # {default_frame}[rdoc-ref:Framing::Default::ClassMethods#default_frame].
20
20
  def all
21
- if (current_frame = self.current_frame)
22
- if self == current_frame.klass
23
- current_frame.clone
24
- else
25
- unframed_all.merge!(current_frame)
26
- end
27
- else
28
- # default_framed.merge!(unframed_all)
29
- unframed_all.merge!(default_framed)
30
- end
21
+ unframed_all.merge(current_frame || default_framed)
22
+ end
23
+
24
+ # def all
25
+ # current_frame = self.current_frame
26
+
27
+ # if current_frame
28
+ # if self == current_frame.klass
29
+ # current_frame.clone
30
+ # else
31
+ # unframed_all.merge!(current_frame)
32
+ # end
33
+ # else
34
+ # default_framed
35
+ # end
36
+ # end
37
+
38
+ def scope_for_association(scope = relation) # :nodoc:
39
+ unframed_scope_for_association(scope).merge(current_frame || default_framed)
31
40
  end
32
41
 
33
- # def default_framed(frame = relation) # :nodoc:
34
- def default_framed(frame = relation) # :nodoc:
35
- !ignore_default_frame? && !ActiveRecord::Framing.disabled? && build_default_frame(frame) || frame
42
+ def default_framed(my_frame = relation)
43
+ build_default_frame(my_frame) || my_frame
36
44
  end
37
45
 
46
+ def frames
47
+ @frames ||= {}
48
+ end
38
49
  # Adds a class method for retrieving and querying objects.
39
50
  # The method is intended to return an ActiveRecord::Relation
40
51
  # object, which is composable with other frames.
@@ -136,50 +147,39 @@ module ActiveRecord
136
147
  #
137
148
  # Article.published.featured.latest_article
138
149
  # Article.featured.titles
139
- def frame(frame_name, body, &block)
140
- unless body.respond_to?(:call)
141
- raise ArgumentError, "The frame body needs to be callable."
150
+ def frame(frame_name, body = nil, &block)
151
+ constant = frame_name.to_s.classify.to_sym
152
+
153
+ if !body.respond_to?(:call)
154
+ # raise ArgumentError, "The frame body needs to be callable."
155
+ warn "You've assigned a frame (#{frame_name}) with no callable block." unless
156
+ AttributeMethods::BLACKLISTED_CLASS_CONSTS.include?(frame_name)
157
+ elsif dangerous_class_const?(constant)
158
+ raise ArgumentError, "You tried to define a frame named \"#{constant}\" " \
159
+ "on the model \"#{self.constant}\", but Active Record already defined " \
160
+ "a class method with the same name."
142
161
  end
143
162
 
144
- constant = frame_name.to_s.classify.to_sym
145
163
  valid_frame_name?(constant)
146
164
 
147
165
  arel_tn = "#{frame_name}/#{self.table_name}"
148
166
 
149
- new_class = self.const_set constant, (Class.new(self) do |klass|
150
- klass.abstract_class = true
151
- klass.table_name = superclass.table_name
152
-
153
- def klass.discriminate_class_for_record(record)
154
- superclass.send(:discriminate_class_for_record, record)
155
- end
156
-
157
- klass.default_frames = [body]
158
-
159
- @current_frame_extension = block
160
-
161
- def klass.current_frame
162
- build_frame(default_frames, arel_table, superclass.relation, &@current_frame_extension)
163
- end
164
-
165
- @arel_table = superclass.arel_table.dup.tap do |at|
166
- at.name = arel_tn
167
- end
168
-
169
- end)
170
-
171
- if dangerous_class_const?(constant)
172
- raise ArgumentError, "You tried to define a frame named \"#{constant}\" " \
173
- "on the model \"#{self.constant}\", but Active Record already defined " \
174
- "a class method with the same name."
167
+ at = arel_table.clone.tap do |a_t|
168
+ a_t.name = arel_tn
175
169
  end
170
+ # at = Arel::Table.new(arel_tn, arel_table.engine)
171
+ # at = Arel::Table.new(arel_tn, self)
176
172
 
173
+ frames[constant] = Proc.new do
174
+ build_frame([body].compact, at, relation, &block)
175
+ end
177
176
  end
178
177
 
179
178
  private
180
179
 
181
180
  def valid_frame_name?(name)
182
- if const_defined?(name) && logger
181
+ # if const_defined?(name) && logger
182
+ if frames.key?(name) && logger
183
183
  logger.warn "Creating frame :#{name}. " \
184
184
  "Overwriting existing const #{self.name}::#{name}."
185
185
  end
@@ -4,29 +4,10 @@ module ActiveRecord
4
4
  module Framing
5
5
  module QueryMethods
6
6
 
7
- if ::ActiveRecord.version >= Gem::Version.new("5.1") # 5.1+
8
- require 'active_record/framing/compat/active_record_5_1'
9
- elsif ::ActiveRecord.version >= Gem::Version.new("5.0") # 5.0+
10
- require 'active_record/framing/compat/active_record_5_0'
11
- elsif ::ActiveRecord.version >= Gem::Version.new("4.2") # 4.2+
12
- require 'active_record/framing/compat/active_record_4_2'
13
- else
14
- raise NotImplementedError, "ActiveRecord::Framing does not support Rails #{::ActiveRecord.version}"
7
+ def frame(value)
8
+ spawn.frame!(value)
15
9
  end
16
10
 
17
- # def from!(value, subquery_name = nil) # :nodoc:
18
- # super.tap do |rel|
19
- # if value.is_a?(::ActiveRecord::Relation) && value.frames_values.any?
20
- # self.frames_values = self.frames_values.merge(value.frames_values)
21
- # value.frames_values.clear
22
- # end
23
- # end
24
- # end
25
-
26
- # def frame(value)
27
- # spawn.frame!(value)
28
- # end
29
-
30
11
  def frame!(value)
31
12
  value = value.all if (value.is_a?(Class) && value < ::ActiveRecord::Base)
32
13
 
@@ -39,6 +20,8 @@ module ActiveRecord
39
20
  {value.left.name => value}
40
21
  when String
41
22
  {arel_table.name => value}
23
+ when Hash
24
+ value
42
25
  else
43
26
  {}
44
27
  end
@@ -4,15 +4,21 @@ require 'active_record/framing/query_methods'
4
4
  require 'active_record/framing/spawn_methods'
5
5
  require 'active_record/framing/attribute_methods'
6
6
  require 'active_record/framing/relation'
7
+ require 'active_record/framing/join_dependency'
8
+ require 'active_record/framing/reflection'
9
+ require 'active_record/framing/compat'
7
10
 
8
11
  module ActiveRecord::Framing
9
12
  class Railtie < Rails::Railtie
10
13
  initializer 'active_record-framing.load' do |_app|
11
14
  ActiveSupport.on_load(:active_record) do
12
15
  ::ActiveRecord::Base.prepend(ActiveRecord::Framing)
16
+
13
17
  ::ActiveRecord::Relation.prepend(ActiveRecord::Framing::Relation)
14
18
  ::ActiveRecord::Relation.prepend(ActiveRecord::Framing::QueryMethods)
15
19
  ::ActiveRecord::Relation.prepend(ActiveRecord::Framing::SpawnMethods)
20
+ ::ActiveRecord::Associations::JoinDependency.prepend(ActiveRecord::Framing::JoinDependency)
21
+
16
22
  end
17
23
  end
18
24
  end
@@ -0,0 +1,36 @@
1
+ module ActiveRecord
2
+ module Framing
3
+ module Reflection
4
+
5
+ def self.prepended(subclass)
6
+ class << subclass
7
+ prepend ClassMethods
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def add_reflection(ar, name, reflection)
14
+ super.tap do |reflections|
15
+ #
16
+ # puts "foo"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ module ActiveRecord
25
+ module Framing
26
+ module MacroReflection
27
+
28
+ def self.prepended(subclass)
29
+ class << subclass
30
+ attr_reader :frame
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -1,9 +1,18 @@
1
+ require 'active_record/framing/model_proxy'
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Relation
3
5
  module Framing
4
6
  module Relation
5
7
 
8
+ def initialize(*args)
9
+ super.tap do |something|
10
+ @klass = ModelProxy.new(@klass, arel_table) unless @klass.class == ModelProxy
11
+ end
12
+ end
13
+
6
14
  def build_arel(*)
15
+ @klass.reframe_values = reframe_values
7
16
  super.tap do |ar|
8
17
  unless ignore_default_frame?
9
18
  build_frames(ar)
@@ -12,8 +21,30 @@ module ActiveRecord
12
21
  end
13
22
  end
14
23
 
24
+ # Prevents a scope from re-including the default_scope
25
+ # e.g. User::All.all.to_sql yielding
26
+ # WITH "all/users" AS (SELECT "users".* FROM "users"), "users" AS (SELECT "users".* FROM "users" WHERE "users"."kind" = 1) SELECT "all/users".* FROM "all/users"
27
+ # vs.
28
+ # WITH "all/users" AS (SELECT "users".* FROM "users") SELECT "all/users".* FROM "all/users"
29
+ def all
30
+ spawn
31
+ end
32
+
33
+ def table=(value)
34
+ @table = value
35
+ @klass.table = value
36
+ end
37
+
38
+ def aggregate_column(column_name)
39
+ framing { super }
40
+ end
41
+
42
+ def build_joins(*)
43
+ framing { super }
44
+ end
45
+
15
46
  # This is all very unfortunate (rails 4.2):
16
- # ActiveRecord, in it's infinite wisdom, has decided
47
+ # ActiveRecordin it's infinite wisdomhas decided
17
48
  # to create JoinDependency objects with arel_tables using a
18
49
  # generic engine (ActiveRecord::Base) as opposed to that of
19
50
  # the driving class. For example:
@@ -33,7 +64,7 @@ module ActiveRecord
33
64
  # TODO: cache known associations, (renable warning)
34
65
  assocs = klass.reflect_on_all_associations.inject(Hash.new) do |assocs, assoc|
35
66
  begin
36
- assocs[assoc.table_name] = assoc
67
+ assocs[assoc.name] = assoc
37
68
  rescue NameError => e
38
69
  # warn <<~WARN.chomp
39
70
  # ActiveRecord::Framing was trying to inspect the association #{assoc.name}
@@ -47,19 +78,28 @@ module ActiveRecord
47
78
 
48
79
  manager.join_sources.each do |join_source|
49
80
  next unless join_source&.left&.respond_to?(:name)
50
- if (assoc = assocs[join_source.left.name])
51
- source = reframe_values.fetch(assoc.name) { assoc.klass }
81
+ table = join_source.left
82
+ if (join_class = derive_engine(table, assocs))
83
+ frame!(join_class)
84
+ end
85
+ end
52
86
 
53
- join_source.left.name = source.arel_table.name
54
- if source < ::ActiveRecord::Base
55
- merge!(source.all)
56
- elsif source < ::ActiveRecord::Relation
57
- merge!(source)
58
- end
87
+ reframe_values.each do |assoc_name, relation|
88
+ relation.frames_values.values.each do |value|
89
+ original = frames_values.delete(value.left.engine.table_name)
90
+ frame!(value)
59
91
  end
60
92
  end
61
93
  end
62
94
 
95
+ def derive_engine(table, associations)
96
+ if table.engine == ::ActiveRecord::Base
97
+ associations[table.name]
98
+ else
99
+ table.engine
100
+ end
101
+ end
102
+
63
103
  # Frame all queries to the current frame.
64
104
  #
65
105
  # Comment.where(post_id: 1).framing do
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Framing
3
- VERSION = "0.1.0-9"
3
+ VERSION = "0.1.0-10"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record-framing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.9
4
+ version: 0.1.0.pre.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Stevens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-13 00:00:00.000000000 Z
11
+ date: 2019-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6.1'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '4.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6.1'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: pg
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +142,20 @@ dependencies:
136
142
  - - ">="
137
143
  - !ruby/object:Gem::Version
138
144
  version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: colorize
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
139
159
  description: Allows for larger level scoping (framing) that affect complicated queries
140
160
  more holistically
141
161
  email:
@@ -148,16 +168,21 @@ files:
148
168
  - LICENSE
149
169
  - README.md
150
170
  - lib/active_record-framing.rb
151
- - lib/active_record/framing.rb
152
171
  - lib/active_record/framing/attribute_methods.rb
172
+ - lib/active_record/framing/compat.rb
153
173
  - lib/active_record/framing/compat/active_record_4_2.rb
154
174
  - lib/active_record/framing/compat/active_record_5_0.rb
155
175
  - lib/active_record/framing/compat/active_record_5_1.rb
176
+ - lib/active_record/framing/compat/active_record_6_0.rb
177
+ - lib/active_record/framing/compat/arel.rb
156
178
  - lib/active_record/framing/core_extension.rb
157
179
  - lib/active_record/framing/default.rb
180
+ - lib/active_record/framing/join_dependency.rb
181
+ - lib/active_record/framing/model_proxy.rb
158
182
  - lib/active_record/framing/named.rb
159
183
  - lib/active_record/framing/query_methods.rb
160
184
  - lib/active_record/framing/railtie.rb
185
+ - lib/active_record/framing/reflection.rb
161
186
  - lib/active_record/framing/relation.rb
162
187
  - lib/active_record/framing/spawn_methods.rb
163
188
  - lib/active_record/framing/version.rb
@@ -181,7 +206,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
206
  - !ruby/object:Gem::Version
182
207
  version: 1.3.1
183
208
  requirements: []
184
- rubygems_version: 3.0.3
209
+ rubyforge_project:
210
+ rubygems_version: 2.7.6.2
185
211
  signing_key:
186
212
  specification_version: 4
187
213
  summary: Provides larger level scopes (frames) through the use of common table expressions.
@@ -1,3 +0,0 @@
1
- require 'active_record/framing/default'
2
- require 'active_record/framing/named'
3
- require 'active_record/framing/railtie' if defined?(Rails::Railtie)