edge 0.2.0 → 0.2.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c25599a81a0c7af695a8155fda82079ab4bb21d5
4
+ data.tar.gz: d870f4eb3cf382ca5e1e828da2a5b1235939a44e
5
+ SHA512:
6
+ metadata.gz: 7528d8b4bf34d7bd2f93cead42b34290b3bce459975d885a32e35e6e9ebc4d27440492e7b3a01e66c85ee2a278a5ab20db68dab7d41321cf10724a636a3e5541
7
+ data.tar.gz: cf043a89a0b47ba43a49270403acef578313cd618b0efc73b79c0f6f0f7e11aee5c0952d1a5705f4d381be081737b894c57fe67f8aa3f4d8ec7bdb2986da6d0e
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # 0.2.1 (March 6, 2013)
2
+
3
+ * Fix: acts_as_forest survives multiple calls
4
+
5
+ # 0.2.0 (February 22, 2013)
6
+
7
+ * Added with_descendents
8
+
9
+ # 0.1.0 (March 11, 2012)
10
+
11
+ * Initial release
data/README.md CHANGED
@@ -45,7 +45,7 @@ acts_as_forest.
45
45
  Location.find_tree usa.id # load a single tree.
46
46
 
47
47
  It also provides the with_descendents scope to get all currently selected
48
- nodes and all there descendents. It can be chained after where scopes, but
48
+ nodes and all their descendents. It can be chained after where scopes, but
49
49
  must not be used after any other type of scope.
50
50
 
51
51
  Location.where(name: "Illinois").with_descendents.all # [illinois, chicago]
data/lib/edge/forest.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Edge
2
2
  module Forest
3
3
  # acts_as_forest models a tree/multi-tree structure.
4
- module ClassMethods
4
+ module ActsAsForest
5
5
  # options:
6
6
  #
7
7
  # * foreign_key - column name to use for parent foreign_key (default: parent_id)
@@ -33,86 +33,89 @@ module Edge
33
33
  scope :root, where(forest_foreign_key => nil)
34
34
 
35
35
  include Edge::Forest::InstanceMethods
36
+ extend Edge::Forest::ClassMethods
37
+ end
38
+ end
36
39
 
37
- # Finds entire forest and preloads all associations. It can be used at
38
- # the end of an ActiveRecord finder chain.
39
- #
40
- # Example:
41
- # # loads all locations
42
- # Location.find_forest
43
- #
44
- # # loads all nodes with matching names and all there descendants
45
- # Category.where(:name => %w{clothing books electronics}).find_forest
46
- def find_forest
47
- manager = recursive_manager.project(Arel.star)
48
- manager.order(forest_order) if forest_order
49
-
50
- records = find_by_sql manager.to_sql
51
-
52
- records_by_id = records.each_with_object({}) { |r, h| h[r.id] = r }
53
-
54
- # Set all children associations to an empty array
55
- records.each do |r|
56
- children_association = r.association(:children)
57
- children_association.target = []
58
- end
40
+ module ClassMethods
41
+ # Finds entire forest and preloads all associations. It can be used at
42
+ # the end of an ActiveRecord finder chain.
43
+ #
44
+ # Example:
45
+ # # loads all locations
46
+ # Location.find_forest
47
+ #
48
+ # # loads all nodes with matching names and all there descendants
49
+ # Category.where(:name => %w{clothing books electronics}).find_forest
50
+ def find_forest
51
+ manager = recursive_manager.project(Arel.star)
52
+ manager.order(forest_order) if forest_order
59
53
 
60
- top_level_records = []
54
+ records = find_by_sql manager.to_sql
61
55
 
62
- records.each do |r|
63
- parent = records_by_id[r[forest_foreign_key]]
64
- if parent
65
- r.association(:parent).target = parent
66
- parent.association(:children).target.push(r)
67
- else
68
- top_level_records.push(r)
69
- end
70
- end
56
+ records_by_id = records.each_with_object({}) { |r, h| h[r.id] = r }
71
57
 
72
- top_level_records
58
+ # Set all children associations to an empty array
59
+ records.each do |r|
60
+ children_association = r.association(:children)
61
+ children_association.target = []
73
62
  end
74
63
 
75
- # Finds an a tree or trees by id.
76
- #
77
- # If any requested ids are not found it raises
78
- # ActiveRecord::RecordNotFound.
79
- def find_tree(id_or_ids)
80
- trees = where(:id => id_or_ids).find_forest
81
- if id_or_ids.kind_of?(Array)
82
- raise ActiveRecord::RecordNotFound unless trees.size == id_or_ids.size
83
- trees
64
+ top_level_records = []
65
+
66
+ records.each do |r|
67
+ parent = records_by_id[r[forest_foreign_key]]
68
+ if parent
69
+ r.association(:parent).target = parent
70
+ parent.association(:children).target.push(r)
84
71
  else
85
- raise ActiveRecord::RecordNotFound if trees.empty?
86
- trees.first
72
+ top_level_records.push(r)
87
73
  end
88
74
  end
89
75
 
90
- # Returns a new scope that includes previously scoped records and their descendants by subsuming the previous scope into a subquery
91
- #
92
- # Only where scopes can precede this in a scope chain
93
- def with_descendants
94
- manager = recursive_manager.project('id')
95
- unscoped.where(id: manager)
76
+ top_level_records
77
+ end
78
+
79
+ # Finds an a tree or trees by id.
80
+ #
81
+ # If any requested ids are not found it raises
82
+ # ActiveRecord::RecordNotFound.
83
+ def find_tree(id_or_ids)
84
+ trees = where(:id => id_or_ids).find_forest
85
+ if id_or_ids.kind_of?(Array)
86
+ raise ActiveRecord::RecordNotFound unless trees.size == id_or_ids.size
87
+ trees
88
+ else
89
+ raise ActiveRecord::RecordNotFound if trees.empty?
90
+ trees.first
96
91
  end
92
+ end
97
93
 
98
- private
99
- def recursive_manager
100
- all_nodes = Arel::Table.new(:all_nodes)
94
+ # Returns a new scope that includes previously scoped records and their descendants by subsuming the previous scope into a subquery
95
+ #
96
+ # Only where scopes can precede this in a scope chain
97
+ def with_descendants
98
+ manager = recursive_manager.project('id')
99
+ unscoped.where(id: manager)
100
+ end
101
101
 
102
- original_term = (current_scope || scoped).arel
103
- iterated_term = Arel::SelectManager.new Arel::Table.engine
104
- iterated_term.from(arel_table)
105
- .project(arel_table.columns)
106
- .join(all_nodes)
107
- .on(arel_table[forest_foreign_key].eq all_nodes[:id])
102
+ private
103
+ def recursive_manager
104
+ all_nodes = Arel::Table.new(:all_nodes)
108
105
 
109
- union = original_term.union(iterated_term)
106
+ original_term = (current_scope || scoped).arel
107
+ iterated_term = Arel::SelectManager.new Arel::Table.engine
108
+ iterated_term.from(arel_table)
109
+ .project(arel_table.columns)
110
+ .join(all_nodes)
111
+ .on(arel_table[forest_foreign_key].eq all_nodes[:id])
110
112
 
111
- as_statement = Arel::Nodes::As.new all_nodes, union
113
+ union = original_term.union(iterated_term)
112
114
 
113
- manager = Arel::SelectManager.new Arel::Table.engine
114
- manager.with(:recursive, as_statement).from(all_nodes)
115
- end
115
+ as_statement = Arel::Nodes::As.new all_nodes, union
116
+
117
+ manager = Arel::SelectManager.new Arel::Table.engine
118
+ manager.with(:recursive, as_statement).from(all_nodes)
116
119
  end
117
120
  end
118
121
 
@@ -156,4 +159,4 @@ module Edge
156
159
  end
157
160
  end
158
161
 
159
- ActiveRecord::Base.extend Edge::Forest::ClassMethods
162
+ ActiveRecord::Base.extend Edge::Forest::ActsAsForest
data/lib/edge/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Edge
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
data/spec/forest_spec.rb CHANGED
@@ -212,4 +212,14 @@ describe "Edge::Forest" do
212
212
  end
213
213
  end
214
214
  end
215
+
216
+ describe "self.acts_as_forest" do
217
+ it 'can be used twice' do
218
+ Location2 = Class.new(ActiveRecord::Base) do
219
+ self.table_name = 'locations'
220
+ acts_as_forest :order => "name"
221
+ end
222
+ Location2.find_forest
223
+ end
224
+ end
215
225
  end
metadata CHANGED
@@ -1,52 +1,46 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jack Christensen
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-22 00:00:00.000000000 Z
11
+ date: 2013-03-06 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activerecord
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 3.2.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 3.2.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: pg
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,33 +55,29 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: guard
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: 0.10.0
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: 0.10.0
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: guard-rspec
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: 0.6.0
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: 0.6.0
94
83
  description: Graph functionality for ActiveRecord
@@ -100,6 +89,7 @@ extra_rdoc_files: []
100
89
  files:
101
90
  - .gitignore
102
91
  - .rspec
92
+ - CHANGELOG.md
103
93
  - Gemfile
104
94
  - Guardfile
105
95
  - LICENSE
@@ -119,27 +109,26 @@ files:
119
109
  - spec/spec_helper.rb
120
110
  homepage: https://github.com/JackC/edge
121
111
  licenses: []
112
+ metadata: {}
122
113
  post_install_message:
123
114
  rdoc_options: []
124
115
  require_paths:
125
116
  - lib
126
117
  required_ruby_version: !ruby/object:Gem::Requirement
127
- none: false
128
118
  requirements:
129
- - - ! '>='
119
+ - - '>='
130
120
  - !ruby/object:Gem::Version
131
121
  version: '0'
132
122
  required_rubygems_version: !ruby/object:Gem::Requirement
133
- none: false
134
123
  requirements:
135
- - - ! '>='
124
+ - - '>='
136
125
  - !ruby/object:Gem::Version
137
126
  version: '0'
138
127
  requirements: []
139
128
  rubyforge_project:
140
- rubygems_version: 1.8.23
129
+ rubygems_version: 2.0.0
141
130
  signing_key:
142
- specification_version: 3
131
+ specification_version: 4
143
132
  summary: Graph functionality for ActiveRecord. Provides tree/forest modeling structure
144
133
  that can load entire trees in a single query.
145
134
  test_files: