dase 4.1.1 → 4.2.0
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 +4 -4
- data/.travis.yml +2 -1
- data/README.md +48 -67
- data/dase.gemspec +3 -5
- data/lib/dase/mp_active_record.rb +1 -1
- data/lib/dase/version.rb +1 -1
- metadata +12 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75b57d1d16a33aaf6039f6aff02fb26342ef15c3
|
4
|
+
data.tar.gz: bb177eeae7391ba894d15395d05917bb71b1de82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f128f08ff9148ec3e97b3c781ca502cbe6863ee5440d577f815723f6d1d6c6cdc6feb6760c840db9818986f5b87cbed10e235a7bb8ad233579c1b9e8d80ee9b5
|
7
|
+
data.tar.gz: 9914f5bc4f059db6c6395bf754136d8d910b95233333236c2f4a2d928b35f8d8181e910777eb54fd0c747ca70b6176f9730034971516cfd649cdda7a3cc2b774
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,99 +2,75 @@
|
|
2
2
|
|
3
3
|
## Overview
|
4
4
|
|
5
|
-
Dase gem provides
|
6
|
-
|
7
|
-

|
8
|
-
|
9
|
-
Calling 'includes_count_of(:articles)' on a relation object adds 'articles_count' method to each of the authors:
|
10
|
-
```
|
11
|
-
authors = Author.includes(:publisher).includes_count_of(:articles, :conditions => {:year => 2012})
|
12
|
-
authors.first.name # => 'Billy'
|
13
|
-
authors.first.articles_count # => 2
|
14
|
-
```
|
15
|
-
|
16
|
-
|
17
|
-
## Installation
|
18
|
-
|
19
|
-
Add this line to your Rails 3.2.x application's Gemfile:
|
20
|
-
|
21
|
-
gem 'dase', "~> 3.2.4"
|
5
|
+
Dase gem provides `includes_count_of` method on a relation, which works similar to ActiveRecord's `preload` method and solves [N+1 query problem](http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations) when counting records in `has_many` ActiveRecord associations.
|
22
6
|
|
23
7
|
## Usage
|
24
8
|
|
25
|
-
|
9
|
+
Given this data in the DB:
|
10
|
+

|
26
11
|
|
12
|
+
and this Rails model definition
|
13
|
+
```ruby
|
14
|
+
class Author
|
15
|
+
has_many :articles
|
16
|
+
end
|
27
17
|
```
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
puts "#{author.name} has #{author.articles_count} articles published"
|
34
|
-
end
|
18
|
+
you can now write this:
|
19
|
+
```
|
20
|
+
authors = Author.includes_count_of(:articles)
|
21
|
+
billy = authors.first # => #<Author name: 'Billy'>
|
22
|
+
billy.articles_count # => 2
|
35
23
|
```
|
36
24
|
|
37
|
-
|
38
|
-
Specify a hash of options which will be passed to the underlying finder
|
39
|
-
which retrieves the association. Valid keys are: :conditions, :group, :having, :joins, :include
|
25
|
+
with conditions on associated records (only articles in year 2012)
|
40
26
|
```
|
41
|
-
Author.includes_count_of(:articles, :
|
27
|
+
Author.includes_count_of(:articles, where: {year: 2012} )
|
42
28
|
```
|
43
29
|
|
44
|
-
|
30
|
+
using lambda syntax (in v4.1 and greater)
|
45
31
|
```
|
46
|
-
|
47
|
-
belongs_to :author
|
48
|
-
scope this_year, lambda { where(:year => 2012) }
|
49
|
-
end
|
50
|
-
|
51
|
-
results = Author.includes_count_of(:articles, :only => Article.this_year)
|
52
|
-
results.first.articles_count # => # number of articles of given Author for year 2012 only
|
32
|
+
Author.includes_count_of(:articles, -> { where(year: 2012) } )
|
53
33
|
```
|
54
|
-
This is achieved by merging the association scope with the scope provided as ":only => ..." option.
|
55
|
-
No additional checks are performed, and providing the association of proper type is solely your responsibility.
|
56
34
|
|
57
|
-
|
58
|
-
### Renaming counter column
|
35
|
+
with renamed counter method
|
59
36
|
```
|
60
|
-
|
61
|
-
sites.each { |site| puts "Site #{site.url} has #{site.admins_count} admin users" }
|
37
|
+
Author.includes_count_of(:articles, -> { where(year: 2012) }, as: :number_of_articles_in_2012)
|
62
38
|
```
|
63
39
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
This gem is for Rails 3.2.x . Earlier versions are not supported.
|
69
|
-
|
70
|
-
Note: the Dase gem version number correlates with the Active Record's versions number,
|
71
|
-
which it has been tested with.
|
72
|
-
E.g. the latest 3.2.* version of Dase will play nicely with the latest 3.2.* version of Active Record.
|
73
|
-
Since dase gem is a sort of a "hack", make sure you specified the version number for "dase" gem in your Gemfile.
|
74
|
-
|
75
|
-
### Polymorphic associations and HasManyThrough associations
|
76
|
-
|
77
|
-
Polymorphic associations and HasManyThrough associations support should work, but it is not tested quite well.
|
78
|
-
Bug reports and pull requests are very welcome.
|
40
|
+
with multiple associations counted at once
|
41
|
+
```
|
42
|
+
Author.includes_count_of(:articles, :photos, :tweets)
|
43
|
+
```
|
79
44
|
|
80
|
-
|
45
|
+
## Installation
|
81
46
|
|
82
|
-
|
47
|
+
| Rails version | Add this to Gemfile |
|
48
|
+
|---------------|------------------------|
|
49
|
+
| 3.2.x | gem 'dase', '~> 3.2.0' |
|
50
|
+
| 4.0.x | ----- N/A ----- |
|
51
|
+
| 4.1.x | gem 'dase', '~> 4.1.0' |
|
52
|
+
| 4.2.0.beta2 | gem 'dase', :github => 'vovayartsev/dase', :branch => 'rails-4-2' |
|
83
53
|
|
84
|
-
##
|
54
|
+
## Under the hood
|
85
55
|
|
86
|
-
|
56
|
+
When a relation is "materialized", we run a custom preloader which calculates the hash of counters in a single SQL query like this:
|
87
57
|
```
|
88
58
|
counters_hash = Article.where(:year => 2012).count(:group => :author_id)
|
89
|
-
Author.find_each do |author|
|
90
|
-
puts "#{author.name} has #{counters_hash[author.id] || 0} articles published"
|
91
|
-
end
|
92
59
|
```
|
60
|
+
then we add counters to the parent records like this:
|
61
|
+
```
|
62
|
+
define_method(:articles_count) { counters_hash[author.id] || 0 }
|
63
|
+
```
|
64
|
+
|
65
|
+
## Alternative approaches
|
66
|
+
Dase calculates counters dynamically every time you make an SQL query. It makes an extra SQL query for each association processed. These alternatives may be more efficient:
|
67
|
+
* Cache column in the DB - see [counter_culture](https://github.com/magnusvk/counter_culture) gem, or [counter_cache](http://guides.rubyonrails.org/association_basics.html#counter_cache) in Rails Guides.
|
68
|
+
* Using subquery in SELECT clause, or JOIN+SELECT+GROUP approach, as explained in [that video](http://www.youtube.com/watch?v=rJg3I-leoo4)
|
93
69
|
|
94
70
|
## Name origin
|
95
71
|
|
96
72
|
The gem is named by the german mathematician [Johann Dase](http://en.wikipedia.org/wiki/Zacharias_Dase),
|
97
|
-
who was a mental calculator
|
73
|
+
who was a [mental calculator](http://en.wikipedia.org/wiki/Mental_calculator) and could add and multiply numbers very quickly.
|
98
74
|
|
99
75
|
## Contributing
|
100
76
|
|
@@ -105,5 +81,10 @@ who was a mental calculator - he could count and multiply numbers very quickly.
|
|
105
81
|
5. Create new Pull Request
|
106
82
|
|
107
83
|
|
108
|
-
|
84
|
+
|
85
|
+
[](https://bitdeli.com/free "Bitdeli Badge")
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
109
90
|
|
data/dase.gemspec
CHANGED
@@ -9,18 +9,16 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["Vladimir Yartsev"]
|
10
10
|
gem.licenses = ["MIT"]
|
11
11
|
gem.email = ["vovayartsev@gmail.com"]
|
12
|
-
gem.description = %q{
|
13
|
-
to count associated records efficiently. See examples at https://github.com/vovayartsev/dase
|
14
|
-
}
|
12
|
+
gem.description = %q{includes_count_of method on ActiveRecord::Relation to solve N+1 query problem when counting associated records }
|
15
13
|
gem.summary = %q{Provides includes_count_of method on ActiveRecord::Relation to count associated records efficiently}
|
16
14
|
gem.homepage = "https://github.com/vovayartsev/dase"
|
17
15
|
|
18
|
-
gem.add_runtime_dependency "activesupport", "
|
16
|
+
gem.add_runtime_dependency "activesupport", "~> 4.2.0"
|
19
17
|
|
20
18
|
if defined? JRUBY_VERSION
|
21
19
|
gem.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
|
22
20
|
else
|
23
|
-
gem.add_runtime_dependency "activerecord", "
|
21
|
+
gem.add_runtime_dependency "activerecord", "~> 4.2.0"
|
24
22
|
gem.add_development_dependency 'sqlite3', '~> 1.3'
|
25
23
|
end
|
26
24
|
|
data/lib/dase/version.rb
CHANGED
metadata
CHANGED
@@ -1,55 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Yartsev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '4.0'
|
20
|
-
- - "<="
|
17
|
+
- - "~>"
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
19
|
+
version: 4.2.0
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '4.0'
|
30
|
-
- - "<="
|
24
|
+
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
26
|
+
version: 4.2.0
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: activerecord
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
|
-
- - "
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '4.0'
|
40
|
-
- - "<="
|
31
|
+
- - "~>"
|
41
32
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
33
|
+
version: 4.2.0
|
43
34
|
type: :runtime
|
44
35
|
prerelease: false
|
45
36
|
version_requirements: !ruby/object:Gem::Requirement
|
46
37
|
requirements:
|
47
|
-
- - "
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '4.0'
|
50
|
-
- - "<="
|
38
|
+
- - "~>"
|
51
39
|
- !ruby/object:Gem::Version
|
52
|
-
version:
|
40
|
+
version: 4.2.0
|
53
41
|
- !ruby/object:Gem::Dependency
|
54
42
|
name: sqlite3
|
55
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,9 +80,8 @@ dependencies:
|
|
92
80
|
- - "~>"
|
93
81
|
- !ruby/object:Gem::Version
|
94
82
|
version: '3.1'
|
95
|
-
description:
|
96
|
-
|
97
|
-
https://github.com/vovayartsev/dase\n "
|
83
|
+
description: 'includes_count_of method on ActiveRecord::Relation to solve N+1 query
|
84
|
+
problem when counting associated records '
|
98
85
|
email:
|
99
86
|
- vovayartsev@gmail.com
|
100
87
|
executables: []
|
@@ -161,4 +148,3 @@ test_files:
|
|
161
148
|
- test/fixtures/schema.rb
|
162
149
|
- test/helper.rb
|
163
150
|
- test/test_dase.rb
|
164
|
-
has_rdoc:
|