collection_extensions 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -4
- data/Gemfile +2 -0
- data/README.md +35 -22
- data/lib/collection_extensions.rb +21 -14
- data/lib/collection_extensions/version.rb +1 -1
- data/spec/collection_extensions_spec.rb +45 -47
- metadata +2 -2
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# CollectionExtensions
|
2
2
|
|
3
3
|
Sometimes an operation just doesn't fit well into a scope, but you don't want to lose your declarative code style
|
4
|
-
by operating on all the objects individually. This gem adds a few lines of code to make it easier to add methods
|
4
|
+
by operating on all the objects individually. This gem adds a few lines of code to make it easier to add methods
|
5
|
+
to collections of ActiveRecord objects.
|
5
6
|
|
6
7
|
<img src="https://secure.travis-ci.org/arches/collection_extensions.png" />
|
7
8
|
|
@@ -9,44 +10,56 @@ by operating on all the objects individually. This gem adds a few lines of code
|
|
9
10
|
|
10
11
|
Add this line to your application's Gemfile:
|
11
12
|
|
12
|
-
|
13
|
+
```ruby
|
14
|
+
gem 'collection_extensions'
|
15
|
+
```
|
13
16
|
|
14
17
|
And then execute:
|
15
18
|
|
16
|
-
|
19
|
+
```bash
|
20
|
+
$ bundle
|
21
|
+
```
|
17
22
|
|
18
23
|
Or install it yourself as:
|
19
24
|
|
20
|
-
|
25
|
+
```bash
|
26
|
+
$ gem install collection_extensions
|
27
|
+
```
|
21
28
|
|
22
29
|
## Usage
|
23
30
|
|
24
|
-
|
31
|
+
A collections of records will be extended based on the naming convention `%sCollectionExtensions`, where the `%s` substitution
|
32
|
+
is the camel-cased name of the class. For example, collections of User objects will be extended with the methods in the
|
33
|
+
`UserCollectionExtensions` model and collections of BlogPost objects will be extended with the methods in the `BlogPostCollectionExtensions`
|
34
|
+
module.
|
25
35
|
|
26
|
-
|
27
|
-
|
28
|
-
has_many :orders, :preferences
|
29
|
-
extend_collections :orders, :preferences
|
30
|
-
|
31
|
-
# the original unextended collection is still available, aliased as orig_* (eg, orig_orders or orig_preferences)
|
32
|
-
end
|
33
|
-
|
34
|
-
This will use the modules OrdersCollectionExtensions and PreferencesCollectionExtensions to extend those associations
|
35
|
-
whenever you use them. For example:
|
36
|
+
```ruby
|
37
|
+
module BlogPostCollectionExtensions
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
# hash key is user ID, hash value is the number of comments they've posted on this set of blog posts
|
40
|
+
def comments_per_user
|
41
|
+
comment_counts = {}
|
42
|
+
|
43
|
+
# 'self' is the array of blog posts
|
44
|
+
each do |blog_post|
|
45
|
+
blog_post.comments.each do |comment|
|
46
|
+
comment_counts[comment.user_id] ||= 0
|
47
|
+
comment_counts[comment.user_id] += 1
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
44
|
-
|
51
|
+
comment_counts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
```
|
45
55
|
|
46
|
-
|
56
|
+
### Naming Convention
|
47
57
|
|
48
|
-
|
58
|
+
If you want a different naming convention, set the config variable using `%s` string substitution:
|
49
59
|
|
60
|
+
```ruby
|
61
|
+
CollectionExtensions::Config.naming_convention = "MethodsForCollectionsOf%s"
|
62
|
+
```
|
50
63
|
|
51
64
|
## Contributing
|
52
65
|
|
@@ -1,25 +1,32 @@
|
|
1
1
|
require "collection_extensions/version"
|
2
2
|
require "collection_extensions/cattr"
|
3
3
|
require "collection_extensions/config"
|
4
|
+
require "active_record"
|
4
5
|
|
5
|
-
|
6
|
+
class ActiveRecord::Relation
|
7
|
+
alias :orig_to_a :to_a
|
8
|
+
alias :orig_method_missing :method_missing
|
6
9
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
+
def to_a
|
11
|
+
records = orig_to_a
|
12
|
+
|
13
|
+
records.extend extension_module if extension_module
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
Array(associations).each do |association|
|
14
|
-
alias_method "orig_#{association}", association
|
15
|
+
records
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
18
|
+
def extension_module
|
19
|
+
extension_klass = CollectionExtensions::Config.naming_convention % @klass.to_s
|
20
|
+
if Object.constants.include? extension_klass.to_sym
|
21
|
+
Object.const_get(extension_klass)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def method_missing(method, *args, &block)
|
26
|
+
if extension_module and extension_module.method_defined? method
|
27
|
+
to_a.send(method, *args, &block)
|
28
|
+
else
|
29
|
+
orig_method_missing(method, *args, &block)
|
30
|
+
end
|
31
|
+
end
|
25
32
|
end
|
@@ -1,69 +1,67 @@
|
|
1
|
+
require 'active_record'
|
1
2
|
require 'collection_extensions'
|
2
3
|
|
3
|
-
module
|
4
|
-
def
|
5
|
-
"
|
4
|
+
module UserCollectionExtensions
|
5
|
+
def utest
|
6
|
+
"ufoo"
|
6
7
|
end
|
7
8
|
end
|
8
9
|
|
9
|
-
module
|
10
|
-
def operate_on_all_foobars
|
11
|
-
"operate_on_all_foobars"
|
12
|
-
end
|
10
|
+
module ExtensionMethodsForUserCollections
|
13
11
|
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
"
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
class CollectionTester
|
22
|
-
include CollectionExtensions
|
23
|
-
|
24
|
-
def examples
|
25
|
-
"original examples method"
|
13
|
+
describe "#extension_class" do
|
14
|
+
context "when the extension module exists" do
|
15
|
+
it "returns the constant" do
|
16
|
+
r = ActiveRecord::Relation.new :User, :users
|
17
|
+
r.extension_module.should == UserCollectionExtensions
|
18
|
+
end
|
26
19
|
end
|
27
20
|
|
28
|
-
|
29
|
-
"
|
21
|
+
context "when the extension module doesn't exist" do
|
22
|
+
it "returns nil" do
|
23
|
+
r = ActiveRecord::Relation.new :Order, :orders
|
24
|
+
r.extension_module.should be_nil
|
25
|
+
end
|
30
26
|
end
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
describe CollectionExtensions do
|
36
|
-
let(:ct) { CollectionTester.new }
|
28
|
+
context "when the naming convention has been changed" do
|
29
|
+
before { CollectionExtensions::Config.naming_convention = "ExtensionMethodsForUserCollections" }
|
30
|
+
after { CollectionExtensions::Config.naming_convention = CollectionExtensions::Config::DEFAULT_NAMING_CONVENTION }
|
37
31
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
ct.examples.should be_a ExamplesCollectionExtensions
|
42
|
-
ct.examples.operate_on_all_examples.should == "operate_on_all_examples"
|
43
|
-
end
|
44
|
-
|
45
|
-
it "aliases the foobars" do
|
46
|
-
ct.orig_foobars.should == "original foobars method"
|
47
|
-
ct.foobars.should be_a FoobarsCollectionExtensions
|
48
|
-
ct.foobars.operate_on_all_foobars.should == "operate_on_all_foobars"
|
32
|
+
it "uses the proper convention to return the constant" do
|
33
|
+
r = ActiveRecord::Relation.new :User, :users
|
34
|
+
r.extension_module.should == ExtensionMethodsForUserCollections
|
49
35
|
end
|
50
36
|
end
|
51
37
|
end
|
52
38
|
|
53
|
-
describe "
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
39
|
+
describe "calling methods on the array" do
|
40
|
+
it "pulls extension methods from the module" do
|
41
|
+
r = ActiveRecord::Relation.new :User, :users
|
42
|
+
r.stub(orig_to_a: [])
|
43
|
+
r.to_a.utest.should == "ufoo"
|
58
44
|
end
|
45
|
+
end
|
59
46
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
47
|
+
describe "calling methods on the relation" do
|
48
|
+
it "pulls extension methods from the module" do
|
49
|
+
r = ActiveRecord::Relation.new :User, :users
|
50
|
+
r.stub(orig_to_a: [])
|
51
|
+
r.utest.should == "ufoo"
|
64
52
|
end
|
65
|
-
end
|
66
53
|
|
67
|
-
|
54
|
+
it "lets non-extension methods pass through" do
|
55
|
+
r = ActiveRecord::Relation.new :User, :users
|
56
|
+
r.stub(orig_to_a: ['first'])
|
57
|
+
r.first.should == 'first'
|
58
|
+
end
|
68
59
|
|
60
|
+
context "when the extension module doesn't exist" do
|
61
|
+
it "lets methods pass through" do
|
62
|
+
r = ActiveRecord::Relation.new :Order, :orders
|
63
|
+
r.stub(orig_to_a: ['first'])
|
64
|
+
r.first.should == 'first'
|
65
|
+
end
|
66
|
+
end
|
69
67
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: collection_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-05 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: Lightweight framework for adding methods to groups of ActiveRecord objects
|
15
15
|
email:
|