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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b1a4d6f990d789d3a9a7a7d79995e3bd9177c98a
4
- data.tar.gz: 5c4be473b6ddc9a2c8933207044ae224d8ebe1bc
3
+ metadata.gz: 75b57d1d16a33aaf6039f6aff02fb26342ef15c3
4
+ data.tar.gz: bb177eeae7391ba894d15395d05917bb71b1de82
5
5
  SHA512:
6
- metadata.gz: 1b41222641e271a29db1a2c7d9283d00d005f9ebdca0317d13d2bb8a11daa1d16e3c490afd3ca86ddbceb5bb0b58bbc3d870ed057d09c40c6f2d5596b3b07fa3
7
- data.tar.gz: 4790d98c1bcfd56ba5e8334b0841814f5f4936163449a3c09b8d90682caa390f006fff51c3a59f28af127443f72f044f95212d2ceba9f3b13e38c1dc1565d846
6
+ metadata.gz: f128f08ff9148ec3e97b3c781ca502cbe6863ee5440d577f815723f6d1d6c6cdc6feb6760c840db9818986f5b87cbed10e235a7bb8ad233579c1b9e8d80ee9b5
7
+ data.tar.gz: 9914f5bc4f059db6c6395bf754136d8d910b95233333236c2f4a2d928b35f8d8181e910777eb54fd0c747ca70b6176f9730034971516cfd649cdda7a3cc2b774
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - "1.9.3"
4
- - rbx-19mode
4
+ - "2.1.4"
5
+ #- rbx-19mode
5
6
  #- jruby-19mode # JRuby in 1.9 mode
6
7
 
7
8
  # uncomment this line if your project needs to run something other than `rake`:
data/README.md CHANGED
@@ -2,99 +2,75 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Dase gem provides 'includes_count_of' method on a relation, which works similar to ActiveRecord's 'includes' method.
6
-
7
- ![Dase example](https://vovayartsev-home.s3.amazonaws.com/dase-mockup.png)
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
- ### Basic usage:
9
+ Given this data in the DB:
10
+ ![Dase example](https://dl.dropboxusercontent.com/u/8560625/dase.png)
26
11
 
12
+ and this Rails model definition
13
+ ```ruby
14
+ class Author
15
+ has_many :articles
16
+ end
27
17
  ```
28
- class Author
29
- has_many :articles
30
- end
31
-
32
- Author.includes_count_of(:articles).find_each do |author|
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
- ### Using :conditions hash
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, :conditions => {:year => 2012}) # counts only articles in year 2012
27
+ Author.includes_count_of(:articles, where: {year: 2012} )
42
28
  ```
43
29
 
44
- ### Using scope merging
30
+ using lambda syntax (in v4.1 and greater)
45
31
  ```
46
- class Article
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
- sites = WebSite.includes_count_of(:users, :conditions => {:role => 'admin'}, :as => :admins_count)
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
- ## Compatibility
65
-
66
- ### Rails versions
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
- ### jRuby support
45
+ ## Installation
81
46
 
82
- Not yet
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
- ## How it works
54
+ ## Under the hood
85
55
 
86
- Here's a pseudo-code that gives an idea on how it works internally
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 - he could count and multiply numbers very quickly.
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
- [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/vovayartsev/dase/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
84
+
85
+ [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/vovayartsev/dase/trend.png)](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{Dase gem creates includes_count_of method in ActiveRecord::Relation
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", ">= 4.0", "<= 4.2"
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", ">= 4.0", "<= 4.2"
21
+ gem.add_runtime_dependency "activerecord", "~> 4.2.0"
24
22
  gem.add_development_dependency 'sqlite3', '~> 1.3'
25
23
  end
26
24
 
@@ -27,7 +27,7 @@ module Dase
27
27
 
28
28
  def merge(other)
29
29
  super(other).tap do |result|
30
- result.dase_values.merge!(other.dase_values || {}) if other # other == nil is fine too
30
+ result.dase_values.merge!(other.dase_values) if other # other == nil is fine too
31
31
  end
32
32
  end
33
33
 
data/lib/dase/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dase
2
- VERSION = '4.1.1'
2
+ VERSION = '4.2.0'
3
3
  end
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.1.1
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-10-31 00:00:00.000000000 Z
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: '4.2'
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: '4.2'
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: '4.2'
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: '4.2'
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: "Dase gem creates includes_count_of method in ActiveRecord::Relation\n
96
- \ to count associated records efficiently. See examples at
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: