edge 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: