active_record_block_matchers 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 +4 -4
- data/README.md +34 -2
- data/active_record_block_matchers.gemspec +1 -0
- data/lib/active_record_block_matchers/config.rb +20 -0
- data/lib/active_record_block_matchers/create_a_new_matcher.rb +5 -6
- data/lib/active_record_block_matchers/create_records_matcher.rb +4 -9
- data/lib/active_record_block_matchers/strategies.rb +31 -0
- data/lib/active_record_block_matchers/strategies/id_strategy.rb +29 -0
- data/lib/active_record_block_matchers/strategies/timestamp_strategy.rb +26 -0
- data/lib/active_record_block_matchers/version.rb +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeeaef70749a55d2326e700d7c5bfbb00f15101a
|
4
|
+
data.tar.gz: 5ab0c836a3c6f8bdf0be53aaf20bcd57f748a949
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 395c2b2dbbdc5629545b800f174d03153509f58e700e3954f630d0c016cb343f70ca3cb0b43a25965db3b558e1e88c1e2addb254378043c7fcbd81092c024973
|
7
|
+
data.tar.gz: 9c8bb147aabcfa50531cbbf40d50e2be7cae215e10a071eff716c88f21a8ff2d06ceaeb0abea7ef4e535868acdb8c59bee99070d4a23c600b68c5560bd1176c6
|
data/README.md
CHANGED
@@ -98,8 +98,6 @@ expect { User.create!(username: "BOB", password: "BlueSteel45") }
|
|
98
98
|
|
99
99
|
**Gotcha Warning:** Be careful about your block syntax when chaining `.which` in your tests. If you write the above example with a `do...end`, the example will parse like this: `expect {...}.to(create_a(User).which) do |user| ... end`, so your block will not execute, and it may appear that your test is passing, when it is not.
|
100
100
|
|
101
|
-
This matcher relies on a `created_at` column existing on the given model class. The name of this column can be configured via `ActiveRecordBlockMatchers::Config.created_at_column_name = "your_column_name"`
|
102
|
-
|
103
101
|
#### `create`
|
104
102
|
|
105
103
|
aliases: `create_records`
|
@@ -156,6 +154,40 @@ expect { User.create!(username: "bob"); User.create!(username: "rhonda") }
|
|
156
154
|
)
|
157
155
|
```
|
158
156
|
|
157
|
+
## Record Retrieval Strategies
|
158
|
+
|
159
|
+
There are currently two retrieval strategies implemented: `:id` and `:timestamp`. `:id` is the default, but this can be configured via the `default_strategy` configuration variable (more details [below](#configuration)).
|
160
|
+
|
161
|
+
The ID and Timestamp Strategies work similarly. The ID Strategy queries the appropriate table(s) to find the highest ID value(s) before the block, then finds new records by looking for records with an ID that higher than that. The Timestamp Strategy uses `Time.current` to record the time before the block. Then it finds new records by looking for records that have a timestamp later than that.
|
162
|
+
|
163
|
+
The ID Strategy is the default because it doesn't rely on time values that may be imprecise or mocked out. The Timestamp Strategy is useful if your tables don't have autoincrementing integer primary keys.
|
164
|
+
|
165
|
+
## Configuration
|
166
|
+
|
167
|
+
You can configure the column names used by the ID or Timestamp Strategies. Put code like this in your `spec_helper.rb` or similar file:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
ActiveRecordBlockMatchers.configure do |config|
|
171
|
+
|
172
|
+
# default value is "id"
|
173
|
+
config.id_column_name = "primary_key"
|
174
|
+
|
175
|
+
# default value is "created_at"
|
176
|
+
config.created_at_column_name = "created_timestamp"
|
177
|
+
|
178
|
+
# default value is :id
|
179
|
+
# must be one of [:id, :timestamp]
|
180
|
+
config.default_strategy = :timestamp
|
181
|
+
end
|
182
|
+
```
|
183
|
+
|
184
|
+
You can also override the default strategy for individual assertions if needed:
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
Timecop.freeze
|
188
|
+
expect { Person.create! }.to create_a(Person, strategy: :id)
|
189
|
+
```
|
190
|
+
|
159
191
|
|
160
192
|
## Development
|
161
193
|
|
@@ -28,5 +28,6 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_development_dependency "rspec", "~> 3.2"
|
29
29
|
spec.add_development_dependency "pry", "~> 0.10.1"
|
30
30
|
spec.add_development_dependency "sqlite3", "~> 1.3.10"
|
31
|
+
spec.add_development_dependency "database_cleaner", "~> 1.5.1"
|
31
32
|
spec.add_development_dependency "standalone_migrations", "~> 2.1.5"
|
32
33
|
end
|
@@ -1,6 +1,18 @@
|
|
1
1
|
module ActiveRecordBlockMatchers
|
2
2
|
class Config
|
3
3
|
|
4
|
+
def self.configure
|
5
|
+
yield self
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.default_strategy
|
9
|
+
@default_strategy || :id
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.default_strategy=(strategy_key)
|
13
|
+
@default_strategy = strategy_key.to_sym
|
14
|
+
end
|
15
|
+
|
4
16
|
def self.created_at_column_name
|
5
17
|
@created_at_column_name || "created_at"
|
6
18
|
end
|
@@ -8,5 +20,13 @@ module ActiveRecordBlockMatchers
|
|
8
20
|
def self.created_at_column_name=(column_name)
|
9
21
|
@created_at_column_name = column_name
|
10
22
|
end
|
23
|
+
|
24
|
+
def self.id_column_name
|
25
|
+
@id_column_name || "id"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.id_column_name=(column_name)
|
29
|
+
@id_column_name = column_name
|
30
|
+
end
|
11
31
|
end
|
12
32
|
end
|
@@ -13,14 +13,13 @@ RSpec::Matchers.define :create_a_new do |klass|
|
|
13
13
|
@which_block = block
|
14
14
|
end
|
15
15
|
|
16
|
-
match do |block|
|
17
|
-
|
16
|
+
match do |options={}, block|
|
17
|
+
fetching_strategy =
|
18
|
+
ActiveRecordBlockMatchers::Strategies.for_key(options[:strategy]).new(block)
|
18
19
|
|
19
|
-
|
20
|
+
@created_records = fetching_strategy.new_records([klass])[klass]
|
20
21
|
|
21
|
-
|
22
|
-
@created_records = klass.where("#{column_name} > ?", time_before)
|
23
|
-
return false unless @created_records.count == 1
|
22
|
+
return false unless @created_records.count == 1 # ? this shouldn't be necessary for all strategies...
|
24
23
|
|
25
24
|
record = @created_records.first
|
26
25
|
|
@@ -20,16 +20,11 @@ RSpec::Matchers.define :create_records do |record_counts|
|
|
20
20
|
@which_block = block
|
21
21
|
end
|
22
22
|
|
23
|
-
match do |block|
|
24
|
-
|
23
|
+
match do |options={}, block|
|
24
|
+
fetching_strategy =
|
25
|
+
ActiveRecordBlockMatchers::Strategies.for_key(options[:strategy]).new(block)
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
@new_records =
|
29
|
-
record_counts.keys.each_with_object({}) do |klass, new_records|
|
30
|
-
column_name = ActiveRecordBlockMatchers::Config.created_at_column_name
|
31
|
-
new_records[klass] = klass.where("#{column_name} > ?", time_before).to_a
|
32
|
-
end
|
27
|
+
@new_records = fetching_strategy.new_records(record_counts.keys)
|
33
28
|
|
34
29
|
@incorrect_counts =
|
35
30
|
@new_records.each_with_object({}) do |(klass, new_records), incorrect|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ActiveRecordBlockMatchers
|
2
|
+
class Strategies
|
3
|
+
|
4
|
+
def self.all_strategies
|
5
|
+
@all_strategies ||= {
|
6
|
+
id: IdStrategy,
|
7
|
+
timestamp: TimestampStrategy,
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.default
|
12
|
+
get_strategy!(Config.default_strategy)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.for_key(strategy_key)
|
16
|
+
if strategy_key.nil?
|
17
|
+
default
|
18
|
+
else
|
19
|
+
get_strategy!(strategy_key)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def self.get_strategy!(strategy_key)
|
26
|
+
all_strategies.fetch(strategy_key)
|
27
|
+
rescue KeyError
|
28
|
+
raise UnknownStrategyError, "#{strategy_key.inspect} is not a known strategy (known strategies are #{all_strategies.keys})"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActiveRecordBlockMatchers
|
2
|
+
class IdStrategy
|
3
|
+
|
4
|
+
def initialize(block)
|
5
|
+
@block = block
|
6
|
+
end
|
7
|
+
|
8
|
+
def new_records(classes)
|
9
|
+
ids_before = classes.each_with_object({}) do |klass, ids_before|
|
10
|
+
ids_before[klass] = klass.select("MAX(#{column_name}) as max_id").first.try(:max_id) || 0
|
11
|
+
end
|
12
|
+
|
13
|
+
block.call
|
14
|
+
|
15
|
+
classes.each_with_object({}) do |klass, new_records|
|
16
|
+
id_before = ids_before[klass]
|
17
|
+
new_records[klass] = klass.where("#{column_name} > ?", id_before).to_a
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :block
|
24
|
+
|
25
|
+
def column_name
|
26
|
+
@column_name ||= ActiveRecordBlockMatchers::Config.id_column_name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveRecordBlockMatchers
|
2
|
+
class TimestampStrategy
|
3
|
+
|
4
|
+
def initialize(block)
|
5
|
+
@block = block
|
6
|
+
end
|
7
|
+
|
8
|
+
def new_records(classes)
|
9
|
+
time_before = Time.current
|
10
|
+
|
11
|
+
block.call
|
12
|
+
|
13
|
+
classes.each_with_object({}) do |klass, new_records|
|
14
|
+
new_records[klass] = klass.where("#{column_name} > ?", time_before).to_a
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :block
|
21
|
+
|
22
|
+
def column_name
|
23
|
+
@column_name ||= ActiveRecordBlockMatchers::Config.created_at_column_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_block_matchers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Wallace
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.3.10
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: database_cleaner
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.5.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.5.1
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: standalone_migrations
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -148,6 +162,9 @@ files:
|
|
148
162
|
- lib/active_record_block_matchers/config.rb
|
149
163
|
- lib/active_record_block_matchers/create_a_new_matcher.rb
|
150
164
|
- lib/active_record_block_matchers/create_records_matcher.rb
|
165
|
+
- lib/active_record_block_matchers/strategies.rb
|
166
|
+
- lib/active_record_block_matchers/strategies/id_strategy.rb
|
167
|
+
- lib/active_record_block_matchers/strategies/timestamp_strategy.rb
|
151
168
|
- lib/active_record_block_matchers/version.rb
|
152
169
|
homepage: https://github.com/nwallace/active_record_block_matchers
|
153
170
|
licenses:
|