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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)