dase 3.2.9 → 4.1.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/dase.gemspec +6 -7
- data/lib/dase.rb +7 -0
- data/lib/dase/mp_active_record.rb +18 -7
- data/lib/dase/preloader.rb +18 -15
- data/lib/dase/preloader_methods.rb +23 -14
- data/lib/dase/version.rb +1 -1
- data/test/fixtures/author.rb +1 -3
- data/test/fixtures/book.rb +0 -2
- data/test/helper.rb +10 -13
- data/test/test_dase.rb +99 -95
- metadata +30 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa21a89c14adc39b8906ec72c7b4b4c53dfefbe2
|
4
|
+
data.tar.gz: 1742ddc3cfa7c83952d008ec7d3421e9946883c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a3383ce22ef7a04bc1363a09b15037dd7b92417bf4a65abb12a4f7027a4895c8e7dd3d62e4cd52687acd93d3653c02a18c8301530a986d1ce2a2de80da3e5af
|
7
|
+
data.tar.gz: ce0941ab55f4c38e9fe21b3e559f93640d9e0b61920d3ff744158a91fa1da524ecbf17b202b7d54bba61a3728dc2f7add3519de7dd551fc2ebdf630b0042e2cc
|
data/dase.gemspec
CHANGED
@@ -15,19 +15,18 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.summary = %q{Provides includes_count_of method on ActiveRecord::Relation to count associated records efficiently}
|
16
16
|
gem.homepage = "https://github.com/vovayartsev/dase"
|
17
17
|
|
18
|
-
gem.add_runtime_dependency "activesupport", "
|
19
|
-
|
20
|
-
|
18
|
+
gem.add_runtime_dependency "activesupport", ">= 4.0", "<= 4.2"
|
19
|
+
|
21
20
|
if defined? JRUBY_VERSION
|
22
21
|
gem.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
|
23
22
|
else
|
24
|
-
gem.add_runtime_dependency "activerecord", "
|
25
|
-
gem.add_development_dependency 'sqlite3', '~> 1.3
|
23
|
+
gem.add_runtime_dependency "activerecord", ">= 4.0", "<= 4.2"
|
24
|
+
gem.add_development_dependency 'sqlite3', '~> 1.3'
|
26
25
|
end
|
27
26
|
|
28
27
|
# gem.add_development_dependency 'pry'
|
29
|
-
gem.add_development_dependency 'rake'
|
30
|
-
gem.add_development_dependency 'rspec-core'
|
28
|
+
gem.add_development_dependency 'rake', '~> 10.3'
|
29
|
+
gem.add_development_dependency 'rspec-core', '~> 3.1'
|
31
30
|
|
32
31
|
gem.files = `git ls-files`.split($/)
|
33
32
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/lib/dase.rb
CHANGED
@@ -6,4 +6,11 @@ require "dase/mp_active_record"
|
|
6
6
|
module Dase
|
7
7
|
# take a look at mp_active_record files
|
8
8
|
# (there we monkey-patch Active Record)
|
9
|
+
|
10
|
+
# Syntax definition
|
11
|
+
VALID_DASE_OPTIONS = [:as]
|
12
|
+
VALID_ASSOCIATION_OPTIONS = [:proc, :where, :group, :having, :joins, :merge, :includes, :from]
|
13
|
+
|
14
|
+
# Legacy syntax support
|
15
|
+
VALID_SYNONYMS = {:only => :merge, :conditions => :where}
|
9
16
|
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module Dase
|
2
|
-
module
|
2
|
+
module RelationInstanceMethods
|
3
3
|
def dase_values
|
4
4
|
@dase_values ||= {}
|
5
5
|
end
|
6
6
|
|
7
7
|
def includes_count_of(*args)
|
8
8
|
options = args.extract_options!
|
9
|
-
|
9
|
+
sanitize_dase_options(args, options)
|
10
|
+
apply_synonyms(options)
|
10
11
|
return self if args.empty?
|
11
12
|
clone.tap do |relation|
|
12
13
|
args.each do |arg|
|
@@ -24,8 +25,18 @@ module Dase
|
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
# legacy syntax support
|
29
|
+
def apply_synonyms(options)
|
30
|
+
VALID_SYNONYMS.each do |old, new|
|
31
|
+
if options.has_key?(old)
|
32
|
+
raise "Don't use #{old} and #{new} together" if options.has_key?(new)
|
33
|
+
options[new] = options.delete(old)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def sanitize_dase_options(args, options)
|
39
|
+
options.assert_valid_keys *(VALID_DASE_OPTIONS + VALID_ASSOCIATION_OPTIONS + VALID_SYNONYMS.keys)
|
29
40
|
if options.present? and args.many?
|
30
41
|
raise ArgumentError, 'includes_count_of takes either multiple associations OR single association + options'
|
31
42
|
end
|
@@ -33,14 +44,14 @@ module Dase
|
|
33
44
|
|
34
45
|
def attach_dase_counters_to_records
|
35
46
|
(dase_values || {}).each do |_, options|
|
36
|
-
Dase::Preloader.new(@records, options[:association]
|
47
|
+
Dase::Preloader.new(options).preload(@records, options[:association])
|
37
48
|
end
|
38
49
|
end
|
39
50
|
end
|
40
51
|
end
|
41
52
|
|
42
53
|
ActiveRecord::Relation.class_eval do
|
43
|
-
include Dase::
|
54
|
+
include Dase::RelationInstanceMethods
|
44
55
|
|
45
56
|
private
|
46
57
|
|
@@ -54,6 +65,6 @@ ActiveRecord::Relation.class_eval do
|
|
54
65
|
end
|
55
66
|
|
56
67
|
class << ActiveRecord::Base
|
57
|
-
delegate :includes_count_of, :to => :
|
68
|
+
delegate :includes_count_of, :to => :all
|
58
69
|
end
|
59
70
|
|
data/lib/dase/preloader.rb
CHANGED
@@ -7,39 +7,42 @@ module Dase
|
|
7
7
|
include Dase::PreloaderMethods
|
8
8
|
end
|
9
9
|
|
10
|
-
class HasAndBelongsToMany < ::ActiveRecord::Associations::Preloader::HasAndBelongsToMany
|
11
|
-
include Dase::PreloaderMethods
|
12
|
-
end
|
13
|
-
|
14
10
|
# Not fully implemented yet
|
15
11
|
class HasManyThrough < ::ActiveRecord::Associations::Preloader::HasManyThrough
|
16
12
|
include Dase::PreloaderMethods
|
17
13
|
|
18
|
-
def
|
14
|
+
def foreign_key
|
19
15
|
"#{reflection.active_record.table_name}.#{reflection.active_record_primary_key}"
|
20
16
|
end
|
21
17
|
|
22
18
|
def records_for(ids)
|
23
19
|
reflection.active_record.joins(reflection.name).
|
24
|
-
where(
|
20
|
+
where(foreign_key => ids)
|
25
21
|
end
|
26
22
|
end
|
27
23
|
|
24
|
+
attr_reader :options
|
25
|
+
|
26
|
+
def initialize(options)
|
27
|
+
@options = options
|
28
|
+
end
|
29
|
+
|
28
30
|
# an overloaded version of ActiveRecord::Associations::Preloader's preloader_for
|
29
31
|
# which returns a class of a custom preloader for a given association
|
30
|
-
def preloader_for(reflection)
|
32
|
+
def preloader_for(reflection, owners, rhs_klass)
|
33
|
+
return NullPreloader unless rhs_klass
|
34
|
+
|
35
|
+
if owners.first.association(reflection.name).loaded?
|
36
|
+
return AlreadyLoaded
|
37
|
+
end
|
38
|
+
|
31
39
|
case reflection.macro
|
32
40
|
when :has_many
|
33
|
-
|
34
|
-
HasManyThrough
|
35
|
-
#raise NotImplementedError, "The support for HasManyThrough associations is not implemented yet"
|
36
|
-
else
|
37
|
-
HasMany
|
38
|
-
end
|
41
|
+
reflection.options[:through] ? HasManyThrough : HasMany
|
39
42
|
when :has_one, :belongs_to
|
40
43
|
raise ArgumentError, "You can't use includes_count_of with a #{reflection.macro} association"
|
41
|
-
|
42
|
-
|
44
|
+
else
|
45
|
+
raise NotImplementedError, "#{reflection.macro} not supported"
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
@@ -1,29 +1,38 @@
|
|
1
1
|
module Dase
|
2
2
|
module PreloaderMethods
|
3
|
-
|
4
|
-
|
5
|
-
preload_options = preload_options.reject { |k, _| k == :association }
|
6
|
-
@dase_counter_name = preload_options.delete(:as)
|
7
|
-
@dase_scope_to_merge = preload_options.delete(:only)
|
8
|
-
super(klass, owners, reflection, preload_options)
|
9
|
-
end
|
10
|
-
|
11
|
-
def prefixed_foreign_key
|
12
|
-
"#{scoped.quoted_table_name}.#{reflection.foreign_key}"
|
3
|
+
def foreign_key
|
4
|
+
reflection.klass.arel_table[reflection.foreign_key]
|
13
5
|
end
|
14
6
|
|
15
|
-
def preload
|
7
|
+
def preload(preloader)
|
16
8
|
pk = model.primary_key.to_sym
|
17
9
|
ids = owners.map(&pk)
|
18
10
|
scope = records_for(ids)
|
19
|
-
|
20
|
-
|
11
|
+
|
12
|
+
# applying options like :where => ... or :conditions => ..., or -> {....}
|
13
|
+
scope = apply_association_options(preloader.options.clone, scope)
|
14
|
+
|
15
|
+
# the actual magic of attaching counters to the records comes here
|
16
|
+
counters_hash = scope.group(foreign_key).count(Arel.star)
|
21
17
|
owners.each do |owner|
|
22
|
-
owner.define_singleton_method(
|
18
|
+
owner.define_singleton_method(preloader.options[:as]) do
|
23
19
|
counters_hash[owner[pk]] || 0
|
24
20
|
end
|
25
21
|
end
|
26
22
|
end
|
27
23
|
|
24
|
+
def apply_association_options(options, scope)
|
25
|
+
proc = options.delete(:proc)
|
26
|
+
|
27
|
+
# applying proc syntax: -> {...}
|
28
|
+
scope = scope.instance_eval(&proc) if proc
|
29
|
+
|
30
|
+
options.slice(*VALID_ASSOCIATION_OPTIONS).each do |key, value|
|
31
|
+
scope = scope.send(key, value)
|
32
|
+
end
|
33
|
+
|
34
|
+
scope
|
35
|
+
end
|
36
|
+
|
28
37
|
end
|
29
38
|
end
|
data/lib/dase/version.rb
CHANGED
data/test/fixtures/author.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
class Author < ActiveRecord::Base
|
2
|
-
attr_accessible :name
|
3
|
-
|
4
2
|
has_many :books
|
5
|
-
has_many :old_books,
|
3
|
+
has_many :old_books, -> { where year: 1990 }, class_name: 'Book'
|
6
4
|
|
7
5
|
has_many :quotes, :through => :books
|
8
6
|
has_many :scores, :through => :quotes
|
data/test/fixtures/book.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require "bundler"
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
5
4
|
Bundler.setup
|
6
|
-
|
7
|
-
require 'shoulda'
|
5
|
+
|
8
6
|
require 'active_record'
|
9
7
|
require 'active_record/fixtures'
|
8
|
+
|
10
9
|
require 'dase'
|
11
10
|
|
12
11
|
FIXTURES_PATH = File.join(File.dirname(__FILE__), 'fixtures')
|
@@ -19,12 +18,10 @@ ActiveRecord::Base.establish_connection(
|
|
19
18
|
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
20
19
|
dep.autoload_paths.unshift FIXTURES_PATH
|
21
20
|
|
22
|
-
ActiveRecord::
|
23
|
-
|
24
|
-
load File.join(FIXTURES_PATH, 'schema.rb')
|
25
|
-
end
|
21
|
+
ActiveRecord::Migration.verbose = false
|
22
|
+
load File.join(FIXTURES_PATH, 'schema.rb')
|
26
23
|
|
27
|
-
ActiveRecord::
|
24
|
+
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_PATH, ActiveRecord::Base.connection.tables)
|
28
25
|
|
29
|
-
|
30
|
-
|
26
|
+
# require 'pry' rescue nil # use it when enabled in gemspec
|
27
|
+
require 'minitest/autorun'
|
data/test/test_dase.rb
CHANGED
@@ -1,104 +1,108 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe 'includes_count_of' do
|
5
4
|
def compare_counts(traditional, dase, true_counts)
|
6
5
|
assert_equal true_counts, traditional, "traditional counting failed - fixtures not loaded"
|
7
6
|
assert_equal true_counts, dase, "dase countings failed"
|
8
7
|
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
9
|
+
before do
|
10
|
+
@bobby, @joe, @teddy = Author.order(:name).all
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should count books' do
|
14
|
+
traditional_counts = Author.order(:name).map { |a| a.books.count }
|
15
|
+
dase_counts = Author.includes_count_of(:books).order(:name).map { |a| a.books_count }
|
16
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
17
|
+
true_counts = [1, 3, 0] # see books.yml
|
18
|
+
compare_counts(traditional_counts, dase_counts, true_counts)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should respond_to the counter method' do
|
22
|
+
assert_equal true, Author.includes_count_of(:books).first.respond_to?(:books_count), "doesn't respond'"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should sneeze through scope definitions' do
|
26
|
+
assert_equal true, Author.with_count_of_books.first.respond_to?(:books_count), "doesn't respond'"
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should support :as option' do
|
30
|
+
assert_equal true, Author.includes_count_of(:books, :as => :my_count).first.respond_to?(:my_count), "doesn't respond'"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should support old_books_count and new_books_count simultaneously using :as option' do
|
34
|
+
scope = Author.includes_count_of(:books, :conditions => {:year => 2012}, :as => :new_books_count).
|
35
|
+
includes_count_of(:books, :conditions => {:year => 1990}, :as => :old_books_count)
|
36
|
+
dase_counts = scope.order(:name).map { |a| [a.old_books_count, a.new_books_count] }
|
37
|
+
# the order is Bobby[:old, :new], Joe[:old, :new], Teddy[:old, :new]
|
38
|
+
true_counts = [[1, 0], [2, 1], [0, 0]] # see books.yml
|
39
|
+
assert_equal true_counts, dase_counts, "results mismatch"
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should count old books' do
|
43
|
+
traditional_counts = Author.order(:name).map { |a| a.old_books.count }
|
44
|
+
dase_counts = Author.includes_count_of(:old_books).order(:name).map { |a| a.old_books_count }
|
45
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
46
|
+
true_counts = [1, 2, 0] # see books.yml
|
47
|
+
compare_counts(traditional_counts, dase_counts, true_counts)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should count books for year 1990' do
|
51
|
+
traditional_counts = Author.order(:name).map { |a| a.books.where(:year => 1990).count }
|
52
|
+
dase_counts = Author.includes_count_of(:books, :conditions => {:year => 1990}).order(:name).map { |a| a.books_count }
|
53
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
54
|
+
true_counts = [1, 2, 0] # see books.yml
|
55
|
+
compare_counts(traditional_counts, dase_counts, true_counts)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should support :proc option (where year 1990)' do
|
59
|
+
traditional_counts = Author.order(:name).map { |a| a.books.where(:year => 1990).count }
|
60
|
+
dase_counts = Author.includes_count_of(:books, :proc => proc { where(:year => 1990) }).order(:name).map { |a| a.books_count }
|
61
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
62
|
+
true_counts = [1, 2, 0] # see books.yml
|
63
|
+
compare_counts(traditional_counts, dase_counts, true_counts)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should count books for year 2012 using :only option' do
|
67
|
+
dase_counts = Author.includes_count_of(:books, :only => Book.year2012).order(:name).map { |a| a.books_count }
|
68
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
69
|
+
true_counts = [0, 1, 0] # see books.yml
|
70
|
+
assert_equal true_counts, dase_counts, "results mismatch"
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should allow merge (nil) on a scope with includes_count_of' do
|
74
|
+
assert_equal 3, Author.includes_count_of(:books).merge(nil).all.size
|
75
|
+
end
|
76
|
+
|
77
|
+
# pending "apply: lambda {where...}"
|
78
|
+
|
79
|
+
it 'should count likes' do
|
80
|
+
dase_counts = Author.order(:name).includes_count_of(:scores).map { |a| a.scores_count }
|
81
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
82
|
+
true_counts = [0, 2, 0] # see likes.yml
|
83
|
+
assert_equal true_counts, dase_counts, "results mismatch"
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should count quotations' do
|
87
|
+
traditional_counts = Author.order(:name).map { |a| a.quotes.count }
|
88
|
+
dase_counts = Author.order(:name).includes_count_of(:quotes).map { |a| a.quotes_count }
|
89
|
+
# the order is: Bobby, Joe, Teddy - due to order(:name)
|
90
|
+
true_counts = [2, 1, 0] # see quotes.yml
|
91
|
+
compare_counts(traditional_counts, dase_counts, true_counts)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should support multiple arguments' do
|
95
|
+
joe = Author.includes_count_of(:books, :old_books).where(:name => 'Joe').first
|
96
|
+
assert_equal 3, joe.books_count, "Invalid books_count"
|
97
|
+
assert_equal 2, joe.old_books_count, "Invalid old_books_count"
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should work with find_each' do
|
101
|
+
# the order is: Bobby, Joe, Teddy - due to sort_by(:name)
|
102
|
+
records = []
|
103
|
+
Author.includes_count_of(:books).find_each(batch_size: 2) { |r| records << r }
|
104
|
+
dase_count = records.sort_by(&:name).map { |a| a.books_count }
|
105
|
+
assert_equal [1, 3, 0], dase_count, "dase countings failed" # see books.yml
|
103
106
|
end
|
104
107
|
end
|
108
|
+
|
metadata
CHANGED
@@ -1,99 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.1.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-10-30 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
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '4.0'
|
20
|
+
- - "<="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '4.2'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 3.2.0
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: shoulda
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
26
|
requirements:
|
31
27
|
- - ">="
|
32
28
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
29
|
+
version: '4.0'
|
30
|
+
- - "<="
|
39
31
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
32
|
+
version: '4.2'
|
41
33
|
- !ruby/object:Gem::Dependency
|
42
34
|
name: activerecord
|
43
35
|
requirement: !ruby/object:Gem::Requirement
|
44
36
|
requirements:
|
45
|
-
- - "
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.0'
|
40
|
+
- - "<="
|
46
41
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
42
|
+
version: '4.2'
|
48
43
|
type: :runtime
|
49
44
|
prerelease: false
|
50
45
|
version_requirements: !ruby/object:Gem::Requirement
|
51
46
|
requirements:
|
52
|
-
- - "
|
47
|
+
- - ">="
|
53
48
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
49
|
+
version: '4.0'
|
50
|
+
- - "<="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '4.2'
|
55
53
|
- !ruby/object:Gem::Dependency
|
56
54
|
name: sqlite3
|
57
55
|
requirement: !ruby/object:Gem::Requirement
|
58
56
|
requirements:
|
59
57
|
- - "~>"
|
60
58
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.3
|
59
|
+
version: '1.3'
|
62
60
|
type: :development
|
63
61
|
prerelease: false
|
64
62
|
version_requirements: !ruby/object:Gem::Requirement
|
65
63
|
requirements:
|
66
64
|
- - "~>"
|
67
65
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.3
|
66
|
+
version: '1.3'
|
69
67
|
- !ruby/object:Gem::Dependency
|
70
68
|
name: rake
|
71
69
|
requirement: !ruby/object:Gem::Requirement
|
72
70
|
requirements:
|
73
|
-
- - "
|
71
|
+
- - "~>"
|
74
72
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
73
|
+
version: '10.3'
|
76
74
|
type: :development
|
77
75
|
prerelease: false
|
78
76
|
version_requirements: !ruby/object:Gem::Requirement
|
79
77
|
requirements:
|
80
|
-
- - "
|
78
|
+
- - "~>"
|
81
79
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
80
|
+
version: '10.3'
|
83
81
|
- !ruby/object:Gem::Dependency
|
84
82
|
name: rspec-core
|
85
83
|
requirement: !ruby/object:Gem::Requirement
|
86
84
|
requirements:
|
87
|
-
- - "
|
85
|
+
- - "~>"
|
88
86
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
87
|
+
version: '3.1'
|
90
88
|
type: :development
|
91
89
|
prerelease: false
|
92
90
|
version_requirements: !ruby/object:Gem::Requirement
|
93
91
|
requirements:
|
94
|
-
- - "
|
92
|
+
- - "~>"
|
95
93
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
94
|
+
version: '3.1'
|
97
95
|
description: "Dase gem creates includes_count_of method in ActiveRecord::Relation\n
|
98
96
|
\ to count associated records efficiently. See examples at
|
99
97
|
https://github.com/vovayartsev/dase\n "
|