edge 0.4.3 → 0.6.1

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
- 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=>"../"