edge 0.4.3 → 0.6.1

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
- SHA1:
3
- metadata.gz: de6a7e89e268d6a04bcb12ea49f331c0492a12c0
4
- data.tar.gz: d3223c0995b78bc3c9de539948b225ee2c0a148a
2
+ SHA256:
3
+ metadata.gz: 9ee55cbc8cd29fcd367b1423df3ecef782eb3ab3f6cc054f86373e35518fbbea
4
+ data.tar.gz: a8565592a8020190a13a04291252508b459c63deb270f220a91f54333a244779
5
5
  SHA512:
6
- metadata.gz: e906301864501743b6848b67a40b33d60e5447c7a34c39023327d577e03e43b0ad926834435c31dbaa5b924f16a1b4dcf3bf095565d18779d8cd180b9b4e3776
7
- data.tar.gz: 85d2f8ea8e2e95dd163f17a2e436cec52b50bb80cc8bda6afc012cedba282548cd23991ea0bb4917b91847832ea9a7fb51734ff9a34bfc1b4a5df9011cd1f115
6
+ metadata.gz: cb8afdfdadae80f8e073a3ce094d2361dc5f47de9ed540b3ff309d40a8b9a9c12cc60c6beb2946a752a7938c7246e4841b66374d111b910ffa8f2e523c7b4cde
7
+ data.tar.gz: c540a358d7cb3c4424472a4b1c80354855673d262622cc3813c3cde9fab12c1c685638fa2083cfefed51658f2ec7917de0e993b0587a7797f57bb8f6fa397333
data/.travis.yml CHANGED
@@ -1,12 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.0
4
- - 2.1.5
5
- - 2.0.0
3
+ - 2.5.3
4
+ - 2.4.5
5
+ - 2.3.8
6
6
  gemfile:
7
- - gemfiles/4.0.gemfile
8
- - gemfiles/4.1.gemfile
9
- - gemfiles/4.2.gemfile
7
+ - gemfiles/5.0.gemfile
10
8
 
11
9
  addons:
12
10
  postgresql: "9.2"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ # 0.6.1 (February 20, 2021)
2
+
3
+ * Add Ruby 3 compatibility (Martins Polakovs)
4
+
5
+ # 0.6.0 (December 13, 2018)
6
+
7
+ * Fix usage when table name includes schema
8
+ * Drop Rails 4.x support
9
+
10
+ # 0.5.1 (August 4, 2017)
11
+
12
+ * Allow use of 'optional' option for belongs_to (Yuji Yaginuma)
13
+
14
+ # 0.5.0 (May 14, 2016)
15
+
16
+ * Add Rails 5.0 support
17
+ * Drop Rails 4.0 support
18
+ * Replace using internal arel with SQL string building
19
+
20
+ # 0.4.4 (January 29, 2016)
21
+
22
+ * Fix JRuby compatibility (jackc)
23
+
1
24
  # 0.4.3 (October 23, 2015)
2
25
 
3
26
  * Allow dependent option to acts_as_forest (WANG QUANG)
data/edge.gemspec CHANGED
@@ -15,12 +15,10 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Edge::VERSION
17
17
 
18
- gem.add_dependency 'activerecord', ">= 4.0.0"
18
+ gem.add_dependency 'activerecord', ">= 5.0.0"
19
19
 
20
20
  gem.add_development_dependency 'pg'
21
21
  gem.add_development_dependency 'pry'
22
22
  gem.add_development_dependency 'rake'
23
- gem.add_development_dependency 'rspec', "~> 3.1.0"
24
- gem.add_development_dependency 'guard', ">= 0.10.0"
25
- gem.add_development_dependency 'guard-rspec', ">= 0.6.0"
23
+ gem.add_development_dependency 'rspec', "~> 3.6.0"
26
24
  end
@@ -1,5 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "activerecord", "4.0.13"
3
+ gem "activerecord", "~> 5.0.0"
4
4
 
5
5
  gemspec :path=>"../"
data/lib/edge/forest.rb CHANGED
@@ -7,8 +7,9 @@ module Edge
7
7
  # * dependent - passed to children has_many (default: none)
8
8
  # * foreign_key - column name to use for parent foreign_key (default: parent_id)
9
9
  # * order - how to order children (default: none)
10
+ # * optional - passed to belongs_to (default: none)
10
11
  def acts_as_forest(options={})
11
- options.assert_valid_keys :foreign_key, :order, :dependent
12
+ options.assert_valid_keys :foreign_key, :order, :dependent, :optional
12
13
 
13
14
  class_attribute :forest_foreign_key
14
15
  self.forest_foreign_key = options[:foreign_key] || "parent_id"
@@ -23,12 +24,14 @@ module Edge
23
24
 
24
25
  dependent_options = options[:dependent] ? { dependent: options[:dependent] } : {}
25
26
 
26
- belongs_to :parent, common_options.merge(inverse_of: :children)
27
+ optional_options = options[:optional] ? { optional: options[:optional] } : {}
28
+
29
+ belongs_to :parent, **common_options.merge(inverse_of: :children).merge(optional_options)
27
30
 
28
31
  if forest_order
29
- has_many :children, -> { order(forest_order) }, common_options.merge(inverse_of: :parent).merge(dependent_options)
32
+ has_many :children, -> { order(forest_order) }, **common_options.merge(inverse_of: :parent).merge(dependent_options)
30
33
  else
31
- has_many :children, common_options.merge(inverse_of: :parent).merge(dependent_options)
34
+ has_many :children, **common_options.merge(inverse_of: :parent).merge(dependent_options)
32
35
  end
33
36
 
34
37
  scope :root, -> { where(forest_foreign_key => nil) }
@@ -49,11 +52,14 @@ module Edge
49
52
  # # loads all nodes with matching names and all there descendants
50
53
  # Category.where(:name => %w{clothing books electronics}).find_forest
51
54
  def find_forest
52
- manager = recursive_manager.project(Arel.star)
53
- manager.order(forest_order) if forest_order
55
+ new_scope = unscoped.joins("INNER JOIN all_nodes USING(#{connection.quote_column_name primary_key})")
56
+ new_scope = new_scope.order(forest_order) if forest_order
54
57
 
55
- bind_values = current_scope ? current_scope.bind_values : []
56
- records = find_by_sql manager.to_sql, bind_values
58
+ sql = <<-SQL
59
+ #{cte_sql}
60
+ #{new_scope.to_sql}
61
+ SQL
62
+ records = find_by_sql sql
57
63
 
58
64
  records_by_id = records.each_with_object({}) { |r, h| h[r.id] = r }
59
65
 
@@ -97,32 +103,33 @@ module Edge
97
103
  #
98
104
  # Only where scopes can precede this in a scope chain
99
105
  def with_descendants
100
- manager = recursive_manager.project(arel_table[:id])
101
- scope = unscoped.where(arel_table[:id].in manager)
102
- scope.bind_values = current_scope.bind_values if current_scope
103
- scope
106
+ subquery_scope = unscoped
107
+ .joins("INNER JOIN all_nodes USING(#{connection.quote_column_name primary_key})")
108
+ .select(primary_key)
109
+
110
+ subquery_sql = <<-SQL
111
+ #{cte_sql}
112
+ #{subquery_scope.to_sql}
113
+ SQL
114
+
115
+ unscoped.where <<-SQL
116
+ #{connection.quote_column_name primary_key} IN (#{subquery_sql})
117
+ SQL
104
118
  end
105
119
 
106
120
  private
107
- def recursive_manager
108
- all_nodes = Arel::Table.new(:all_nodes)
109
-
110
- original_term = (current_scope || all).select(primary_key, forest_foreign_key).arel
111
- iterated_term = Arel::SelectManager.new Arel::Table.engine
112
- iterated_term.from(arel_table)
113
- .project([arel_table[primary_key.to_sym], arel_table[forest_foreign_key.to_sym]])
114
- .join(all_nodes)
115
- .on(arel_table[forest_foreign_key].eq all_nodes[:id])
116
-
117
- union = original_term.union(iterated_term)
118
-
119
- as_statement = Arel::Nodes::As.new all_nodes, union
120
-
121
- Arel::SelectManager.new(Arel::Table.engine)
122
- .with(:recursive, as_statement)
123
- .from(all_nodes)
124
- .join(arel_table)
125
- .on(all_nodes[:id].eq(arel_table[:id]))
121
+ def cte_sql
122
+ quoted_table_name = '"locations"'
123
+ original_scope = (current_scope || all).select(primary_key, forest_foreign_key)
124
+ iterated_scope = unscoped.select(primary_key, forest_foreign_key)
125
+ .joins("INNER JOIN all_nodes ON #{connection.quote_table_name table_name}.#{connection.quote_column_name forest_foreign_key}=all_nodes.#{connection.quote_column_name primary_key}")
126
+ <<-SQL
127
+ WITH RECURSIVE all_nodes AS (
128
+ #{original_scope.to_sql}
129
+ UNION
130
+ #{iterated_scope.to_sql}
131
+ )
132
+ SQL
126
133
  end
127
134
  end
128
135
 
data/lib/edge/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Edge
2
- VERSION = "0.4.3"
2
+ VERSION = "0.6.1"
3
3
  end
data/spec/forest_spec.rb CHANGED
@@ -164,7 +164,8 @@ describe "Edge::Forest" do
164
164
 
165
165
  it "works when scoped" do
166
166
  forest = Location.where(:name => "USA").find_forest
167
- expect(forest).to include(usa)
167
+ expect(forest).to match_array([usa])
168
+ expect(forest.first.children).to match_array([illinois, indiana])
168
169
  end
169
170
 
170
171
  it "preloads children in proper order" do
@@ -257,4 +258,26 @@ describe "Edge::Forest" do
257
258
  end
258
259
 
259
260
  end
261
+
262
+ if ActiveRecord::VERSION::MAJOR >= 5
263
+ describe "optional option" do
264
+ before do
265
+ @original_value = ActiveRecord::Base.belongs_to_required_by_default
266
+ ActiveRecord::Base.belongs_to_required_by_default = true
267
+ end
268
+
269
+ after do
270
+ ActiveRecord::Base.belongs_to_required_by_default = @original_value
271
+ end
272
+
273
+ it 'parent can be nil' do
274
+ class Location4 < ActiveRecord::Base
275
+ self.table_name = "locations"
276
+ acts_as_forest optional: true
277
+ end
278
+
279
+ expect(Location4.new(name: "Iceland").valid?).to eq true
280
+ end
281
+ end
282
+ end
260
283
  end
data/spec/spec_helper.rb CHANGED
@@ -6,36 +6,18 @@ require 'rspec'
6
6
  database_config = YAML.load_file(File.expand_path("../database.yml", __FILE__))
7
7
  ActiveRecord::Base.establish_connection database_config["test"]
8
8
 
9
-
10
-
11
- # class HstoreRecord < ActiveRecord::Base
12
- # serialize :properties, Surus::Hstore::Serializer.new
13
- # end
14
-
15
- # class TextArrayRecord < ActiveRecord::Base
16
- # serialize :texts, Surus::Array::TextSerializer.new
17
- # end
18
-
19
- # class IntegerArrayRecord < ActiveRecord::Base
20
- # serialize :integers, Surus::Array::IntegerSerializer.new
21
- # end
22
-
23
- # class FloatArrayRecord < ActiveRecord::Base
24
- # serialize :floats, Surus::Array::FloatSerializer.new
25
- # end
26
-
27
- # class DecimalArrayRecord < ActiveRecord::Base
28
- # serialize :decimals, Surus::Array::DecimalSerializer.new
29
- # end
30
-
31
-
32
-
33
9
  RSpec.configure do |config|
34
- config.around :disable_transactions => nil do |example|
10
+ config.before(:all) do |example|
11
+ ActiveRecord::Base.connection.execute <<-SQL
12
+ truncate body_parts;
13
+ truncate locations;
14
+ SQL
15
+ end
16
+
17
+ config.around do |example|
35
18
  ActiveRecord::Base.transaction do
36
19
  example.call
37
20
  raise ActiveRecord::Rollback
38
21
  end
39
22
  end
40
23
  end
41
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Christensen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-23 00:00:00.000000000 Z
11
+ date: 2021-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0
19
+ version: 5.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.0
26
+ version: 5.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pg
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -72,42 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 3.1.0
75
+ version: 3.6.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 3.1.0
83
- - !ruby/object:Gem::Dependency
84
- name: guard
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: 0.10.0
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 0.10.0
97
- - !ruby/object:Gem::Dependency
98
- name: guard-rspec
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: 0.6.0
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: 0.6.0
82
+ version: 3.6.0
111
83
  description: Graph functionality for ActiveRecord
112
84
  email:
113
85
  - jack@jackchristensen.com
@@ -129,9 +101,7 @@ files:
129
101
  - bench/database_structure.sql
130
102
  - bench/forest_find.rb
131
103
  - edge.gemspec
132
- - gemfiles/4.0.gemfile
133
- - gemfiles/4.1.gemfile
134
- - gemfiles/4.2.gemfile
104
+ - gemfiles/5.0.gemfile
135
105
  - lib/edge.rb
136
106
  - lib/edge/forest.rb
137
107
  - lib/edge/version.rb
@@ -143,7 +113,7 @@ files:
143
113
  homepage: https://github.com/JackC/edge
144
114
  licenses: []
145
115
  metadata: {}
146
- post_install_message:
116
+ post_install_message:
147
117
  rdoc_options: []
148
118
  require_paths:
149
119
  - lib
@@ -158,9 +128,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
128
  - !ruby/object:Gem::Version
159
129
  version: '0'
160
130
  requirements: []
161
- rubyforge_project:
162
- rubygems_version: 2.4.5.1
163
- signing_key:
131
+ rubygems_version: 3.0.6
132
+ signing_key:
164
133
  specification_version: 4
165
134
  summary: Graph functionality for ActiveRecord. Provides tree/forest modeling structure
166
135
  that can load entire trees in a single query.
data/gemfiles/4.1.gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "activerecord", "~> 4.1.13"
4
-
5
- gemspec :path=>"../"
data/gemfiles/4.2.gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "activerecord", "~> 4.2.4"
4
-
5
- gemspec :path=>"../"