rspec-active_record 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dc22932934c76f5aa353ae21165ccccb5dbe12ae02b23384b4bf2be5c3fb2400
4
+ data.tar.gz: ceba6e1dd8edd17ba0b732a458e2a71be87a916213b8a6500394d011e3322074
5
+ SHA512:
6
+ metadata.gz: 4895273f1779660e100f207e9497979f07eaf973ddc1133b138ac56d7b1339bc632387a7ac0a1aa8b8fea0903a644fb5d043f76e5e2eb23289ee916240e60085
7
+ data.tar.gz: 6ee9a41affc0b83ad13cbb54a0c1da7ac0187c13a7ea0bb5104df6f9ed5e8511572f2bab8a9eb5e45a0960faad7d8e76e55e44274aaf3735feff702d990e9e8b
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --format documentation
2
+ --no-color
3
+ --require spec_helper
4
+ --backtrace
data/.rubocop.yml ADDED
@@ -0,0 +1,21 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - "*.gemspec"
7
+ - "spec/**/*"
8
+
9
+ Metrics/MethodLength:
10
+ Enabled: false
11
+
12
+ Style/StringLiterals:
13
+ Enabled: true
14
+ EnforcedStyle: double_quotes
15
+
16
+ Style/StringLiteralsInInterpolation:
17
+ Enabled: true
18
+ EnforcedStyle: double_quotes
19
+
20
+ Layout/LineLength:
21
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-04-23
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rspec-active_record.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Andrius Chamentauskas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # Rspec::ActiveRecord
2
+
3
+ Implements helper methods & matchers when working with RSpec & ActiveRecord.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add rspec-active_record --group test
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install rspec-active_record
14
+
15
+ ## Usage
16
+
17
+ ### create_record
18
+
19
+ Check that block creates a record:
20
+
21
+ ```ruby
22
+ expect { User.create!(name: "RSpec User") }.to create_record(User)
23
+ ```
24
+
25
+ You can also make sure that attributes match, if it fails you'll get RSpec diff between created record and what you expected:
26
+
27
+ ```ruby
28
+ expect { User.create!(name: "RSpec User") }.to create_record(User).matching(name: "RSpec User")
29
+ ```
30
+
31
+ You can also achieve similar results using a scope, but not that in this case you won't see a diff:
32
+
33
+ ```ruby
34
+ expect { User.create!(name: "RSpec User") }.to create_record(User.where(name: "RSpec User"))
35
+ ```
36
+
37
+ ### change_record
38
+
39
+ Check that code updates attributes of your record (note that it will automatically refind the record, so make sure changes are saved):
40
+ ```ruby
41
+ expect { user.update!(name: "RSpec User") }.to change_record(user).to(name: "RSpec User")
42
+ ```
43
+
44
+ Sometimes it's useful to specify what the attributes should've been initially:
45
+ ```ruby
46
+ expect { user.update!(name: "RSpec User") }.to change_record(user).from(name: "Initial Name")
47
+ ```
48
+
49
+ ### destroy_record
50
+
51
+ Check that code destroys a record:
52
+ ```ruby
53
+ expect { user.destroy! }.to destroy_record(user)
54
+ ```
55
+
56
+ ### stub_class
57
+
58
+ Stub class for a spec, pass a block to customize the class:
59
+
60
+ ```ruby
61
+ stub_class :DummyDecorator, ApplicationDecorator do
62
+ def object
63
+ Object.new
64
+ end
65
+ end
66
+ DummyDecorator.new.object #=> #<Object>
67
+ ```
68
+
69
+ ### stub_model
70
+
71
+ Similar to `stub_class` but automatically inherits from ApplicationRecord:
72
+
73
+
74
+ ```ruby
75
+ stub_model :DummyUser do
76
+ belongs_to :client, optional: true
77
+ end
78
+ DummyUser.new.client #=> nil
79
+ ```
80
+
81
+ ### create_temporary_table
82
+
83
+ Requires database that supports modifying structure inside transaction. Combines well with `stub_model` to create table for stubbed model:
84
+
85
+ ```ruby
86
+ create_temporary_table :dummy_users do |t|
87
+ t.belongs_to :client
88
+ end
89
+ ```
90
+
91
+ ## Development
92
+
93
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
94
+
95
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
96
+
97
+ ## Contributing
98
+
99
+ Bug reports and pull requests are welcome on GitHub at https://github.com/andriusch/rspec-active_record.
100
+
101
+ ## License
102
+
103
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ # A matcher
6
+ class ChangeRecord < RecordMatcher
7
+ include RSpec::Matchers::BuiltIn::BaseMatcher::HashFormatting
8
+
9
+ # Attributes of record should match these after block is executed
10
+ def to(**attributes)
11
+ @to = attributes
12
+ self
13
+ end
14
+
15
+ # Attributes of record should match these before block is executed
16
+ def from(**attributes)
17
+ @from = attributes
18
+ self
19
+ end
20
+
21
+ def matches?(block)
22
+ @from_diff = diff_unless_match(@record, @from)
23
+ @to_pre_match = !does_not_match_attributes?(@record, @to)
24
+
25
+ block.call
26
+ @updated_record = @record.class.find(@record.id)
27
+
28
+ @to_diff = diff_unless_match(@updated_record, @to)
29
+ @from_post_match = !does_not_match_attributes?(@updated_record, @from)
30
+
31
+ (@from || @to) && !@from_diff && !@to_pre_match && !@to_diff && !@from_post_match
32
+ end
33
+
34
+ def does_not_match?(block)
35
+ return false if @to || @from.blank?
36
+
37
+ @from_diff = diff_unless_match(@record, @from)
38
+ return false if @from_diff
39
+
40
+ block.call
41
+ @updated_record = @record.class.find(@record.id)
42
+
43
+ @from_post_match = !does_not_match_attributes?(@updated_record, @from)
44
+ end
45
+
46
+ def description
47
+ message = "change #{format_record}"
48
+ message += " from #{format_hash(@from)}" if @from
49
+ message += " to #{format_hash(@to)}" if @to
50
+ message
51
+ end
52
+
53
+ def failure_message
54
+ if @from_post_match
55
+ "expected to change #{format_record} from #{format_hash(@from)} but did not"
56
+ elsif @to_pre_match
57
+ "expected #{format_record} to not match #{format_hash(@to)} initially but it did"
58
+ elsif @from_diff
59
+ "expected #{format_record} to match #{format_hash(@from)} initially but it did not#{@from_diff}"
60
+ elsif @to_diff
61
+ "expected to change #{format_record} to #{format_hash(@to)} but did not#{@to_diff}"
62
+ else
63
+ "please specify from or to for change_record"
64
+ end
65
+ end
66
+
67
+ def failure_message_when_negated
68
+ if @to
69
+ "negative matcher for change_record with to is not supported"
70
+ elsif @from.blank?
71
+ "negative matcher for change_record without from is not supported"
72
+ elsif @from_diff
73
+ "expected #{format_record} to match #{format_hash(@from)} initially but it did not#{@from_diff}"
74
+ elsif !@from_post_match
75
+ "expected not to change #{format_record} from #{format_hash(@from)} but it did"
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def format_hash(hash)
82
+ improve_hash_formatting RSpec::Support::ObjectFormatter.format(surface_descriptions_in(hash))
83
+ end
84
+
85
+ def diff_unless_match(record, attributes)
86
+ diff(record, attributes) unless match_attributes?(record, attributes)
87
+ end
88
+
89
+ def diff(record, attributes)
90
+ "\n\n#{DiffForMultipleRecords.new(attributes, [record]).call}"
91
+ end
92
+
93
+ def match_attributes?(record, attributes)
94
+ return true unless attributes
95
+
96
+ RSpec::Matchers::BuiltIn::HaveAttributes.new(attributes).matches?(record)
97
+ end
98
+
99
+ def does_not_match_attributes?(record, attributes)
100
+ return true unless attributes
101
+
102
+ RSpec::Matchers::BuiltIn::HaveAttributes.new(attributes).does_not_match?(record)
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ # A matcher
6
+ class CreateRecord
7
+ include RSpec::Matchers::Composable
8
+ include RSpec::Matchers::BuiltIn::BaseMatcher::HashFormatting
9
+
10
+ def initialize(scope)
11
+ @scope = scope
12
+ end
13
+
14
+ # Make sure that created record matches attributes
15
+ def matching(**attributes)
16
+ @attributes = attributes
17
+ self
18
+ end
19
+
20
+ def supports_block_expectations?
21
+ true
22
+ end
23
+
24
+ def matches?(block)
25
+ existing_ids = @scope.ids
26
+ block.call
27
+
28
+ @new_records = @scope.where.not(@scope.primary_key => existing_ids)
29
+
30
+ if @attributes
31
+ match_attributes?
32
+ else
33
+ @new_records.present?
34
+ end
35
+ end
36
+
37
+ def description
38
+ message = "create #{scope_name}"
39
+ if @attributes
40
+ message += " matching #{RSpec::Support::ObjectFormatter.format(surface_descriptions_in(@attributes))}"
41
+ end
42
+ improve_hash_formatting message
43
+ end
44
+
45
+ def failure_message
46
+ add_diff "expected to #{description} but did not"
47
+ end
48
+
49
+ def failure_message_when_negated
50
+ "expected not to #{description} but did"
51
+ end
52
+
53
+ private
54
+
55
+ def add_diff(message)
56
+ message += "\n\n#{DiffForMultipleRecords.new(@attributes, @new_records).call}" if @attributes
57
+ message
58
+ end
59
+
60
+ def match_attributes?
61
+ @new_records.any? { |record| RSpec::Matchers::BuiltIn::HaveAttributes.new(@attributes).matches?(record) }
62
+ end
63
+
64
+ def scope_name
65
+ @scope.try(:klass) || @scope
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ # A matcher
6
+ class DestroyRecord < RecordMatcher
7
+ def matches?(block)
8
+ block.call
9
+ !@record.class.exists?(@record.id)
10
+ end
11
+
12
+ def description
13
+ "destroy #{format_record}"
14
+ end
15
+
16
+ def failure_message
17
+ "expected to #{description} but did not"
18
+ end
19
+
20
+ def failure_message_when_negated
21
+ "expected not to #{description} but did"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ # @api private
6
+ class DiffForMultipleRecords
7
+ def initialize(attributes, records)
8
+ @attributes = attributes
9
+ @records = records
10
+ end
11
+
12
+ def call
13
+ @records.map do |record|
14
+ record_attributes = @attributes.keys.index_with { |key| record.__send__(key) }
15
+ diff = RSpec::Expectations.differ.diff(record_attributes, @attributes)
16
+ "Diff for #{record.class.name}##{record.id}\n#{diff}"
17
+ end.join("\n\n")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ # A matcher
6
+ class RecordMatcher
7
+ include RSpec::Matchers::Composable
8
+
9
+ def initialize(record)
10
+ @record = record
11
+ end
12
+
13
+ def supports_block_expectations?
14
+ true
15
+ end
16
+
17
+ private
18
+
19
+ def format_record
20
+ "#{@record.class.name}##{@record.id}"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ # Used for stubbing classes in your tests
6
+ module StubModels
7
+ # Stub a class with specific name for testing.
8
+ # @param name [#to_s] Name of stubbed class.
9
+ # @param parent [Class] Parent class of stubbed class.
10
+ # @yield Pass the block to further customize the class.
11
+ # @example
12
+ # stub_class :DummyDecorator, ApplicationDecorator do
13
+ # def object = Object.new
14
+ # end
15
+ # DummyDecorator.new.object #=> #<Object>
16
+ def stub_class(name, parent = Object, &block)
17
+ stub_const(name.to_s, Class.new(parent, &block))
18
+ end
19
+
20
+ # Stub a model with specific name for testing.
21
+ # @param name [#to_s] Name of stubbed class.
22
+ # @param parent [Class] Parent class of stubbed class.
23
+ # @yield Pass the block to further customize the class.
24
+ # @see #create_temporary_table
25
+ # @example
26
+ # stub_model :DummyUser do
27
+ # belongs_to :client, optional: true
28
+ # end
29
+ # create_temporary_table :dummy_users do |t|
30
+ # t.belongs_to :client
31
+ # end
32
+ # DummyUser.new.client #=> nil
33
+ def stub_model(name, parent = ApplicationRecord, &block)
34
+ stub_class(name, parent) do
35
+ self.table_name = name.to_s.tableize
36
+ class_eval(&block) if block
37
+ end
38
+ end
39
+
40
+ # Creates temporary table. Only works correctly if DDL transactions are enabled.
41
+ # Takes same arguments as `create_table` in ActiveRecord migration.
42
+ def create_temporary_table(*args, **options, &block)
43
+ ::ActiveRecord::Base.connection.create_table(*args, **options, &block)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module ActiveRecord
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "rspec/expectations"
5
+ require "rspec/mocks"
6
+
7
+ module RSpec
8
+ # Various helpers and matchers to help with specs when working with ActiveRecord models.
9
+ # It is automatically included in RSpec specs.
10
+ module ActiveRecord
11
+ autoload :ChangeRecord, "rspec/active_record/change_record"
12
+ autoload :CreateRecord, "rspec/active_record/create_record"
13
+ autoload :DestroyRecord, "rspec/active_record/destroy_record"
14
+ autoload :DiffForMultipleRecords, "rspec/active_record/diff_for_multiple_records"
15
+ autoload :RecordMatcher, "rspec/active_record/record_matcher"
16
+ autoload :StubModels, "rspec/active_record/stub_models"
17
+ autoload :VERSION, "rspec/active_record/version"
18
+
19
+ include StubModels
20
+
21
+ # Allows matching that code inside a block created specific record.
22
+ # @param scope [ActiveRecord::Relation, Class] Model class or a record where the record should be created.
23
+ # @return [CreateRecord]
24
+ # @example Block created any User
25
+ # expect { User.create!(name: "RSpec User") }.to create_record(User)
26
+ # @example Block create a User matching specific name
27
+ # expect { User.create!(name: "RSpec User") }.to create_record(User).matching(name: "RSpec User")
28
+ # @example Block create a User matching specific name
29
+ # expect { User.create!(name: "RSpec User") }.to create_record(User.where(name: "RSpec User"))
30
+ def create_record(scope)
31
+ CreateRecord.new(scope)
32
+ end
33
+
34
+ # Allows matching that code inside a block changed specific record.
35
+ # @param record [ActiveRecord::Base] Model that we're checking for changes
36
+ # @return [ChangeRecord]
37
+ # @example Block updated user name to specific one
38
+ # expect { user.update!(name: "RSpec User") }.to change_record(user).to(name: "RSpec User")
39
+ # @example Block updated user name from specific one
40
+ # expect { user.update!(name: "RSpec User") }.to change_record(user).from(name: "Initial Name")
41
+ def change_record(record)
42
+ ChangeRecord.new(record)
43
+ end
44
+
45
+ # Allows matching that code inside a block destroyed specific record.
46
+ # @param record [ActiveRecord::Base] Model that should be destroyed
47
+ # @return [ChangeRecord]
48
+ # @example Block destroyed record
49
+ # expect { user.destroy! }.to destroy_record(user)
50
+ def destroy_record(record)
51
+ DestroyRecord.new(record)
52
+ end
53
+ end
54
+ end
55
+ RSpec.configuration.include RSpec::ActiveRecord
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rspec/active_record/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rspec-active_record"
7
+ spec.version = RSpec::ActiveRecord::VERSION
8
+ spec.authors = ["Andrius Chamentauskas"]
9
+ spec.email = ["andrius.chamentauskas@gmail.com"]
10
+
11
+ spec.summary = "RSpec matchers for ActiveRecord"
12
+ spec.description = "RSpec matchers to check when ActiveRecord objects are created/updated/destroyed"
13
+ spec.homepage = "https://github.com/andriusch/rspec-active_record"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_dependency "activerecord"
33
+ spec.add_dependency "rspec-expectations"
34
+ spec.add_dependency "rspec-mocks"
35
+
36
+ spec.add_development_dependency "database_cleaner-active_record"
37
+ spec.add_development_dependency "rake"
38
+ spec.add_development_dependency "rspec"
39
+ spec.add_development_dependency "rubocop"
40
+ spec.add_development_dependency "sqlite3"
41
+
42
+ # For more information and examples about making a new gem, check out our
43
+ # guide at: https://bundler.io/guides/creating_gem.html
44
+ end
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module ActiveRecord
3
+ VERSION: String
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-active_record
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrius Chamentauskas
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-expectations
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-mocks
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: database_cleaner-active_record
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sqlite3
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: RSpec matchers to check when ActiveRecord objects are created/updated/destroyed
126
+ email:
127
+ - andrius.chamentauskas@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".rspec"
133
+ - ".rubocop.yml"
134
+ - CHANGELOG.md
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - lib/rspec/active_record.rb
140
+ - lib/rspec/active_record/change_record.rb
141
+ - lib/rspec/active_record/create_record.rb
142
+ - lib/rspec/active_record/destroy_record.rb
143
+ - lib/rspec/active_record/diff_for_multiple_records.rb
144
+ - lib/rspec/active_record/record_matcher.rb
145
+ - lib/rspec/active_record/stub_models.rb
146
+ - lib/rspec/active_record/version.rb
147
+ - rspec-active_record.gemspec
148
+ - sig/r_spec/active_record.rbs
149
+ homepage: https://github.com/andriusch/rspec-active_record
150
+ licenses:
151
+ - MIT
152
+ metadata:
153
+ homepage_uri: https://github.com/andriusch/rspec-active_record
154
+ source_code_uri: https://github.com/andriusch/rspec-active_record
155
+ changelog_uri: https://github.com/andriusch/rspec-active_record/CHANGELOG.md
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: 2.6.0
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubygems_version: 3.3.26
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: RSpec matchers for ActiveRecord
175
+ test_files: []