activerecord_null_object 0.2.0 → 0.6.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: 8e814ba60434b9563a80ed56708733bcce37ac810148403ce512eede9006e0dc
4
+ data.tar.gz: 7a79cb743fb799deb9ed2b899357fbbd34c71eeda7468cdd3e00737a1f1c3329
5
+ SHA512:
6
+ metadata.gz: 5c3d744c96242745bfd230f952de637728e2e8788407b72a5f95ca08d3fa4bbc1e804fbbc5953bde4cca15f5450e14f1e53499aafe37907e6f353b8c937958fc
7
+ data.tar.gz: 95e60bb581a2f19dee479161bcad3a6dda3048986521f31228a2ff344e2808ccde837724b5724362b8d339447b64109499ff1574b6ef3592c622db93d906dbd1
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "bundler"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "daily"
@@ -0,0 +1,59 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ name: Build
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ bundler-cache: true
18
+ - run: bundle exec rake
19
+
20
+ release:
21
+ needs: build
22
+ name: Release
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v2
27
+
28
+ - name: Generate Changelog
29
+ run: |
30
+ # Get version from github ref (remove 'refs/tags/' and prefix 'v')
31
+ version="${GITHUB_REF#refs/tags/v}"
32
+ npx changelog-parser CHANGELOG.md | jq -cr ".versions | .[] | select(.version == \"$version\") | .body" > ${{ github.workflow }}-CHANGELOG.txt
33
+
34
+ - name: Release
35
+ uses: softprops/action-gh-release@v1
36
+ with:
37
+ body_path: ${{ github.workflow }}-CHANGELOG.txt
38
+ env:
39
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
+
41
+ publish:
42
+ needs: [build, release]
43
+ name: Publish
44
+ runs-on: ubuntu-latest
45
+
46
+ steps:
47
+ - uses: actions/checkout@v2
48
+ - uses: ruby/setup-ruby@v1
49
+
50
+ - name: Publish to RubyGems
51
+ run: |
52
+ mkdir -p $HOME/.gem
53
+ touch $HOME/.gem/credentials
54
+ chmod 0600 $HOME/.gem/credentials
55
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
56
+ gem build *.gemspec
57
+ gem push *.gem
58
+ env:
59
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -0,0 +1,24 @@
1
+ name: Build and Test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ gemfile: [rails60, rails61, rails70]
9
+ ruby: ["2.7", "3.0", "3.1"]
10
+ runs-on: ubuntu-latest
11
+ env:
12
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: bundle exec rake
20
+ - name: Coveralls
21
+ uses: coverallsapp/github-action@master
22
+ with:
23
+ github-token: ${{ secrets.GITHUB_TOKEN }}
24
+ path-to-lcov: coverage/lcov.info
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
- .DS_Store
2
- test.db
3
1
  pkg
2
+ coverage
3
+ Gemfile.lock
4
+ tmp
5
+ vendor
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Change Log
2
+
3
+ ## 0.6.0
4
+
5
+ - [PLAT-183] Ruby 3.0, Rails 7 and coveralls github action
6
+
7
+ ## 0.5.0
8
+
9
+ - [TT-8620] Update to build with github actions / ruby 3.0 / Rails 6.1
10
+
11
+ ## 0.4.0
12
+
13
+ * Use coverage kit to enforce maximum coverage
14
+ * [TT-6631] Fix present? and blank? checks on Rails6
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ ActiveRecord Null Object
2
+ ========================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/activerecord_null_object.svg)](http://badge.fury.io/rb/activerecord_null_object)
5
+ [![Build Status](https://github.com/sealink/activerecord_null_object/workflows/Build%20and%20Test/badge.svg?branch=master)](https://github.com/sealink/activerecord_null_object/actions)
6
+ [![Coverage Status](https://coveralls.io/repos/sealink/activerecord_null_object/badge.png)](https://coveralls.io/r/sealink/activerecord_null_object)
7
+ [![Code Climate](https://codeclimate.com/github/sealink/activerecord_null_object.png)](https://codeclimate.com/github/sealink/activerecord_null_object)
8
+
9
+ # DESCRIPTION
10
+
11
+ Implements the Null Object Pattern for nil values in ActiveRecord associations.
12
+
13
+ # RELEASE
14
+
15
+ To publish a new version of this gem the following steps must be taken.
16
+
17
+ * Update the version in the following files
18
+ ```
19
+ CHANGELOG.md
20
+ lib/activerecord_null_object/version.rb
21
+ ````
22
+ * Create a tag using the format v0.1.0
23
+ * Follow build progress in GitHub actions
24
+
25
+ Copyright (c) 2009 West Arete Computing, Inc., released under the MIT license
data/Rakefile CHANGED
@@ -1,25 +1,12 @@
1
- require 'spec'
2
- require 'spec/rake/spectask'
3
- require 'init'
1
+ require "bundler/gem_tasks"
4
2
 
5
3
  desc 'Default: run specs.'
6
4
  task :default => :spec
7
5
 
8
- Spec::Rake::SpecTask.new do |t|
9
- t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
10
- t.spec_files = FileList['spec/**/*_spec.rb']
11
- end
6
+ require 'rspec/core/rake_task'
12
7
 
13
- begin
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |s|
16
- s.name = %q{activerecord_null_object}
17
- s.summary = %q{Implements the Null Object Pattern for nil values in ActiveRecord associations.}
18
- s.email = %q{info@westarete.com}
19
- s.homepage = %q{http://github.com/westarete/activerecord_null_object/}
20
- s.description = ""
21
- s.authors = ["Scott Woods"]
22
- end
23
- rescue LoadError
24
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
8
+ desc "Run specs"
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
11
+ # Put spec opts in a file named .rspec in root
25
12
  end
@@ -1,54 +1,30 @@
1
- # -*- encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
2
 
3
- Gem::Specification.new do |s|
4
- s.name = %q{activerecord_null_object}
5
- s.version = "0.2.0"
3
+ require File.expand_path('lib/activerecord_null_object/version', __dir__)
6
4
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Scott Woods"]
9
- s.date = %q{2009-09-02}
10
- s.description = %q{}
11
- s.email = %q{info@westarete.com}
12
- s.extra_rdoc_files = [
13
- "README"
14
- ]
15
- s.files = [
16
- ".gitignore",
17
- "MIT-LICENSE",
18
- "README",
19
- "Rakefile",
20
- "VERSION",
21
- "activerecord_null_object.gemspec",
22
- "init.rb",
23
- "lib/activerecord_null_object.rb",
24
- "lib/null_object.rb",
25
- "spec/belongs_to_spec.rb",
26
- "spec/database.yml",
27
- "spec/null_object_spec.rb",
28
- "spec/schema.rb",
29
- "spec/spec.opts",
30
- "spec/spec_helper.rb"
31
- ]
32
- s.has_rdoc = true
33
- s.homepage = %q{http://github.com/westarete/activerecord_null_object/}
34
- s.rdoc_options = ["--charset=UTF-8"]
35
- s.require_paths = ["lib"]
36
- s.rubygems_version = %q{1.3.1}
37
- s.summary = %q{Implements the Null Object Pattern for nil values in ActiveRecord associations.}
38
- s.test_files = [
39
- "spec/belongs_to_spec.rb",
40
- "spec/null_object_spec.rb",
41
- "spec/schema.rb",
42
- "spec/spec_helper.rb"
43
- ]
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "activerecord_null_object"
7
+ spec.version = ActiveRecordNullObject::VERSION
8
+ spec.authors = ["Scott Woods", "Alessandro Berardi"]
9
+ spec.email = ["support@travellink.com.au"]
10
+ spec.description = %q{Implements the Null Object Pattern for nil values in ActiveRecord associations.}
11
+ spec.summary = %q{Implements the Null Object Pattern for nil values in ActiveRecord associations.}
12
+ spec.homepage = 'http://github.com/sealink/activerecord_null_object'
44
13
 
45
- if s.respond_to? :specification_version then
46
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
- s.specification_version = 2
14
+ spec.license = "MIT"
48
15
 
49
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
- else
51
- end
52
- else
53
- end
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "activesupport", ">= 6.0", "< 8"
22
+ spec.add_runtime_dependency "activerecord", ">= 6.0", "< 8"
23
+ spec.add_development_dependency "bundler"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "rspec-its"
27
+ spec.add_development_dependency "coverage-kit"
28
+ spec.add_development_dependency 'sqlite3'
29
+ spec.add_development_dependency 'pry-byebug'
54
30
  end
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activesupport', '~> 6.0'
6
+ gem 'activerecord', '~> 6.0'
7
+ gem 'actionpack', '~> 6.0'
8
+ end
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activesupport', '~> 6.1'
6
+ gem 'activerecord', '~> 6.1'
7
+ gem 'actionpack', '~> 6.1'
8
+ end
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activesupport', '~> 7.0'
6
+ gem 'activerecord', '~> 7.0'
7
+ gem 'actionpack', '~> 7.0'
8
+ end
@@ -0,0 +1,36 @@
1
+ require 'active_support/concern'
2
+
3
+ module ActiveRecordNullObject
4
+ module NullObject
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ validate :unsavable
9
+ end
10
+
11
+ def id
12
+ nil
13
+ end
14
+
15
+ def nil?
16
+ true
17
+ end
18
+
19
+ def empty?
20
+ true
21
+ end
22
+
23
+ def blank?
24
+ true
25
+ end
26
+
27
+ def present?
28
+ false
29
+ end
30
+
31
+ def unsavable
32
+ errors.add(:base, "is a null object and can't be saved")
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,64 @@
1
+ require 'active_support/concern'
2
+
3
+ module ActiveRecordNullObject
4
+ module NullObjectSupport
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+
9
+ # Add null object support to the given accessor method.
10
+ def add_null_object_support(name, options = {}) #:nodoc:
11
+ # Determine the class of the association.
12
+ association_class_name = options[:class_name] || name.to_s.classify
13
+ association_class = association_class_name.constantize
14
+ null_class_name = "Null" + association_class_name
15
+
16
+ # Determine the null class for this association.
17
+ null_class = options[:null_object].to_s.classify.safe_constantize || null_class_name.safe_constantize
18
+
19
+ unless null_class
20
+ # Define the null class as an ancestor of the association class.
21
+ null_class = Object.const_set(null_class_name, Class.new(association_class))
22
+ null_class.class_eval do
23
+ include ::Singleton
24
+ include ::ActiveRecordNullObject::NullObject
25
+ end
26
+ end
27
+
28
+ # Modify the "getter" of the relationship to return an
29
+ # instance of the association's null object instead of returning nil.
30
+ class_eval do
31
+ define_method("#{name}".to_sym) do |*args|
32
+ super(*args) || null_class.instance
33
+ end
34
+ end
35
+ end
36
+
37
+ # Add a :null_object option to belongs_to.
38
+ def belongs_to(name, scope = nil, **options)
39
+ # args << options.except(:null_object)
40
+ # Call the real belongs_to so that the association gets defined.
41
+ super(name, scope, **options.except(:null_object))
42
+
43
+ # Modify the association if need be.
44
+ if options[:null_object]
45
+ add_null_object_support(name, options)
46
+ end
47
+ end
48
+
49
+ # Add a :null_object option to has_one.
50
+ def has_one(name, scope = nil, **options)
51
+ # args = options.except(:null_object)
52
+
53
+ # Call the real belongs_to so that the association gets defined.
54
+ super(name, scope, **options.except(:null_object))
55
+
56
+ # Modify the association if need be.
57
+ if options[:null_object]
58
+ add_null_object_support(name, options)
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveRecordNullObject
2
+ VERSION = '0.6.0'
3
+ end
@@ -1,58 +1,7 @@
1
- module ActiveRecord
2
- module Associations
3
- module ClassMethods
4
-
5
- # Add null object support to the given accessor method.
6
- def add_null_object_support(association_id, options = {}) #:nodoc:
7
- # Determine the class of the association.
8
- association_class_name = options[:class_name] || association_id.to_s.classify
9
- association_class = association_class_name.constantize
1
+ require 'active_record'
10
2
 
11
- # Determine the null class for this association.
12
- null_class_name = "Null" + association_class_name
13
- if Object.const_defined?(null_class_name)
14
- null_class = Object.const_get(null_class_name.to_sym)
15
- else
16
- # Define the null class as an ancestor of the association class.
17
- null_class = Object.const_set(null_class_name, Class.new(association_class))
18
- null_class.class_eval do
19
- include Singleton
20
- include ActiveRecordNullObject::NullObject
21
- end
22
- end
3
+ require 'activerecord_null_object/version'
4
+ require 'activerecord_null_object/null_object'
5
+ require 'activerecord_null_object/null_object_support'
23
6
 
24
- # Modify the "getter" of the relationship to return an
25
- # instance of the association's null object instead of returning nil.
26
- class_eval do
27
- define_method("#{association_id}_with_null_object".to_sym) do
28
- send("#{association_id}_without_null_object".to_sym) || null_class.instance
29
- end
30
- alias_method_chain association_id, :null_object
31
- end
32
- end
33
-
34
- # Add a boolean :null_object option to belongs_to.
35
- def belongs_to_with_null_object(association_id, options = {}) #:nodoc:
36
- # Extract our custom option.
37
- use_null_object = options.delete(:null_object)
38
- # Call the real belongs_to so that the association gets defined.
39
- belongs_to_without_null_object(association_id, options)
40
- # Modify the association if need be.
41
- add_null_object_support(association_id, options) if use_null_object
42
- end
43
- alias_method_chain :belongs_to, :null_object
44
-
45
- # Add a boolean :null_object option to has_one.
46
- def has_one_with_null_object(association_id, options = {}) #:nodoc:
47
- # Extract our custom option.
48
- use_null_object = options.delete(:null_object)
49
- # Call the real has_one so that the association gets defined.
50
- has_one_without_null_object(association_id, options)
51
- # Modify the association if need be.
52
- add_null_object_support(association_id, options) if use_null_object
53
- end
54
- alias_method_chain :has_one, :null_object
55
-
56
- end
57
- end
58
- end
7
+ ActiveRecord::Base.send :include, ActiveRecordNullObject::NullObjectSupport
@@ -1,93 +1,61 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe Comment do
4
- before(:each) do
5
- @comment = Comment.create!(:body => 'The body.')
6
- end
7
-
8
- it "should contain a body" do
9
- @comment.body.should == 'The body.'
10
- end
4
+ subject(:comment) { Comment.create!(:body => 'The body.') }
11
5
 
12
- describe "without an author" do
13
- it "should return a null object for the author" do
14
- @comment.author.kind_of?(NullAuthor).should be_true
15
- end
16
-
17
- it "should be nil" do
18
- @comment.author.should be_nil
19
- end
20
-
21
- it "should return true for comment.author.nil?" do
22
- @comment.author.nil?.should be_true
23
- end
24
-
25
- it "should return false for comment.author.present?" do
26
- @comment.author.present?.should be_false
27
- end
28
-
29
- it "should return nil for the author's name" do
30
- @comment.author.name.should be_nil
31
- end
32
- end
33
-
34
- describe "with an author" do
35
- before(:each) do
36
- @comment.author = Author.create!(:name => 'James Baker')
37
- end
38
-
39
- it "should return the author object" do
40
- @comment.author.kind_of?(Author).should be_true
41
- @comment.author.kind_of?(NullAuthor).should_not be_true
42
- end
43
-
44
- it "should return false for comment.author.nil?" do
45
- @comment.author.nil?.should be_false
46
- end
47
-
48
- it "should return true for comment.author.present?" do
49
- @comment.author.present?.should be_true
50
- end
51
-
52
- it "should return the author's name" do
53
- @comment.author.name.should == 'James Baker'
6
+ its(:body) { should == 'The body.' }
7
+
8
+ context "its author" do
9
+ subject(:author) { comment.author }
10
+
11
+ context "when not present" do
12
+ it { should be_kind_of NullAuthor }
13
+ it { should be_nil }
14
+ it { should_not be_present }
15
+ its(:name) { should be_nil }
54
16
  end
55
-
56
- it "should revert to a null object if assigned nil" do
57
- @comment.author = nil
58
- @comment.author.name.should be_nil
17
+
18
+ context "when present" do
19
+ before { comment.create_author!(:name => 'James Baker') }
20
+
21
+ it { should be_kind_of Author }
22
+ it { should_not be_kind_of NullAuthor }
23
+ it { should_not be_nil }
24
+ it { should be_present }
25
+ its(:name) { should == 'James Baker' }
26
+
27
+ context "when removed" do
28
+ before { comment.author = nil }
29
+ its(:name) { should be_nil }
30
+ end
59
31
  end
60
32
  end
61
33
  end
62
34
 
63
35
  describe Post do
64
- before(:each) do
65
- @post = Post.create!(:body => 'The body.')
66
- end
67
-
68
- it "should contain a body" do
69
- @post.body.should == 'The body.'
70
- end
71
-
72
- it "should not have null object support for the author" do
73
- @post.author.should be_nil
74
- @post.author.kind_of?(Author).should be_false
75
- @post.author.respond_to?(:name).should be_false
36
+ subject(:post) { Post.create!(:body => 'The body.') }
37
+
38
+ its(:body) { should == 'The body.' }
39
+
40
+ context "without null object support for the author" do
41
+ subject(:author) { post.author }
42
+
43
+ it { should be_nil }
44
+ it { should_not be_kind_of Author }
45
+ it { should_not respond_to :name }
76
46
  end
77
47
  end
78
48
 
79
49
  describe Session do
80
- before(:each) do
81
- @session = Session.create!(:description => 'The description.')
82
- end
83
-
84
- it "should contain a description" do
85
- @session.description.should == 'The description.'
86
- end
87
-
88
- it "should not have null object support for the author" do
89
- @session.author.should be_nil
90
- @session.author.kind_of?(Author).should be_false
91
- @session.author.respond_to?(:name).should be_false
50
+ subject(:session) { Session.create!(:description => 'The description.') }
51
+
52
+ its(:description) { should == 'The description.' }
53
+
54
+ context "without null object support for the author" do
55
+ subject(:author) { session.author }
56
+
57
+ it { should be_nil }
58
+ it { should_not be_kind_of Author }
59
+ it { should_not respond_to :name }
92
60
  end
93
61
  end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Author do
4
+ subject(:author) { Author.create!(:name => 'James Madison') }
5
+
6
+ context "its profile" do
7
+ subject(:profile) { author.profile }
8
+
9
+ context "when not present" do
10
+ context "without null object support for the profile" do
11
+ it { should be_nil }
12
+ it { should_not be_kind_of Profile }
13
+ it { should_not respond_to :age }
14
+ end
15
+ end
16
+
17
+ context "when present" do
18
+ before { author.create_profile!(:age => 56) }
19
+
20
+ its(:age) { should == 56 }
21
+ end
22
+ end
23
+
24
+ context "its account" do
25
+ subject(:account) { author.account }
26
+
27
+ context "when not present" do
28
+ context "without null object support for the account" do
29
+ it { should be_nil }
30
+ it { should_not be_kind_of Account }
31
+ it { should_not respond_to :password }
32
+ end
33
+ end
34
+
35
+ context "when present" do
36
+ before { author.create_account!(:password => 'secret') }
37
+
38
+ its(:password) { should == 'secret' }
39
+ end
40
+ end
41
+
42
+
43
+ context "its address" do
44
+ subject(:address) { author.address }
45
+
46
+ context "when not present" do
47
+ it { should be_kind_of NullAddress }
48
+ it { should be_nil }
49
+ it { should_not be_present }
50
+ its(:street) { should be_nil }
51
+ end
52
+
53
+ context "when present" do
54
+ before { author.create_address!(:street => '1600 Pennsylvania Ave') }
55
+
56
+ it { should be_kind_of Address }
57
+ it { should_not be_kind_of NullAddress }
58
+ it { should_not be_nil }
59
+ it { should be_present }
60
+ its(:street) { should == '1600 Pennsylvania Ave' }
61
+
62
+ context "when the address is removed" do
63
+ before { author.address = nil }
64
+ its(:street) { should be_nil }
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -1,99 +1,67 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe NullAuthor do
4
-
5
- before(:each) do
6
- @null_author = Comment.new.author
7
- end
8
-
9
- it "should be a kind of Author" do
10
- @null_author.kind_of?(Author).should be_true
11
- end
4
+
5
+ subject(:null_author) { Comment.new.author }
6
+
7
+ it { should be_kind_of Author }
12
8
 
13
9
  it "should be a singleton" do
14
- lambda { NullAuthor.new }.should raise_error(NoMethodError)
15
- end
16
-
17
- it "should be nil" do
18
- @null_author.nil?.should be_true
19
- @null_author.should be_nil
20
- end
21
-
22
- it "should be empty" do
23
- @null_author.empty?.should be_true
24
- end
25
-
26
- it "should be blank" do
27
- @null_author.blank?.should be_true
28
- end
29
-
30
- it "should not be present" do
31
- @null_author.present?.should be_false
10
+ expect { NullAuthor.new }.to raise_error(NoMethodError)
32
11
  end
33
12
 
34
- describe "#id" do
35
- it "should return nil" do
36
- @null_author.id.should be_nil
37
- end
38
- end
39
-
40
- describe "#new_record?" do
41
- it "should return true" do
42
- @null_author.new_record?.should be_true
43
- end
44
- end
45
-
46
- describe "#save" do
47
- it "should return false" do
48
- @null_author.save.should be_false
49
- end
50
-
13
+ it { should be_nil }
14
+ it { should be_empty }
15
+ it { should be_blank }
16
+ it { should_not be_present }
17
+ its(:id) { should be_nil }
18
+ it { should be_new_record }
19
+
20
+ context "when saving with save" do
21
+ its(:save) { should be false }
22
+
51
23
  it "should not create a new record" do
52
- lambda { @null_author.save }.should_not change { NullAuthor.count }
24
+ expect { null_author.save }.to_not change { NullAuthor.count }
53
25
  end
54
-
26
+
55
27
  it "should add an error" do
56
- @null_author.errors.on(:base).should == "is a null object and can't be saved"
28
+ expect(null_author.errors[:base]).to eq ["is a null object and can't be saved"]
57
29
  end
58
30
  end
59
-
60
- describe "#save!" do
31
+
32
+ context "when saving with save!" do
61
33
  it "should raise an exception" do
62
- lambda { @null_author.save! }.should raise_error(ActiveRecord::RecordInvalid)
34
+ expect { null_author.save! }.to raise_error(ActiveRecord::RecordInvalid)
63
35
  end
64
-
36
+
65
37
  it "should not create a new record" do
66
- lambda {
38
+ expect {
67
39
  begin
68
- @null_author.save!
40
+ null_author.save!
69
41
  rescue ActiveRecord::RecordInvalid
70
42
  end
71
- }.should_not change { NullAuthor.count }
43
+ }.to_not change { NullAuthor.count }
72
44
  end
73
45
 
74
46
  it "should add an error" do
75
- @null_author.errors.on(:base).should == "is a null object and can't be saved"
47
+ expect(null_author.errors[:base]).to eq ["is a null object and can't be saved"]
76
48
  end
77
49
  end
78
50
 
79
- describe "#update_attributes" do
51
+ context "when updating attributes" do
80
52
  it "should return false" do
81
- @null_author.update_attributes({}).should be_false
53
+ expect(null_author.update({})).to be false
82
54
  end
83
-
55
+
84
56
  it "should not create a new record" do
85
- lambda { @null_author.update_attributes({}) }.should_not change { NullAuthor.count }
57
+ expect { null_author.update({}) }.to_not change { NullAuthor.count }
86
58
  end
87
59
 
88
60
  it "should add an error" do
89
- @null_author.errors.on(:base).should == "is a null object and can't be saved"
90
- end
91
- end
92
-
93
- describe "#name" do
94
- it "should return nil" do
95
- @null_author.name.should be_nil
61
+ expect(null_author.errors[:base]).to eq ["is a null object and can't be saved"]
96
62
  end
97
63
  end
98
-
99
- end
64
+
65
+ its(:name) { should be_nil }
66
+
67
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,19 +1,29 @@
1
1
  require 'rubygems'
2
+ require 'bundler/setup'
2
3
  require 'active_record'
3
4
  require 'yaml'
4
- require 'spec'
5
- require File.dirname(__FILE__) + '/../init.rb'
5
+ require 'rspec'
6
+ require 'rspec/its'
6
7
 
7
- # Establish database connection.
8
- config = YAML::load(File.open(File.dirname(__FILE__) + '/database.yml'))
9
- ActiveRecord::Base.establish_connection(config['test'])
10
- load(File.dirname(__FILE__) + "/schema.rb")
8
+ I18n.enforce_available_locales = true if I18n.respond_to? :enforce_available_locales=
9
+
10
+ require 'support/coverage_loader'
11
+
12
+ require 'activerecord_null_object'
11
13
 
12
14
  # Fixes 'address'.singularize # => 'addres'
13
15
  ActiveSupport::Inflector.inflections do |inflect|
14
16
  inflect.singular(/ess$/i, 'ess')
15
17
  end
16
18
 
19
+ DB_FILE = 'tmp/test_db'
20
+ FileUtils.mkdir_p File.dirname(DB_FILE)
21
+ FileUtils.rm_f DB_FILE
22
+
23
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => DB_FILE
24
+
25
+ load('spec/schema.rb')
26
+
17
27
  class Account < ActiveRecord::Base
18
28
  end
19
29
 
@@ -29,12 +39,20 @@ class Author < ActiveRecord::Base
29
39
  has_many :comments
30
40
  has_many :sessions
31
41
  has_one :profile
32
- has_one :account, :null_object => false
42
+ if ::ActiveRecord::VERSION::MAJOR == 4
43
+ has_one :account, -> {order :created_at}, :null_object => false
44
+ else
45
+ has_one :account, :null_object => false
46
+ end
33
47
  has_one :address, :null_object => true
34
48
  end
35
49
 
36
50
  class Comment < ActiveRecord::Base
37
- belongs_to :author, :null_object => true
51
+ if ::ActiveRecord::VERSION::MAJOR == 4
52
+ belongs_to :author, -> {order :name}, :null_object => true
53
+ else
54
+ belongs_to :author, :null_object => true
55
+ end
38
56
  end
39
57
 
40
58
  class Post < ActiveRecord::Base
@@ -45,3 +63,6 @@ class Session < ActiveRecord::Base
45
63
  belongs_to :author
46
64
  end
47
65
 
66
+ RSpec.configure do |config|
67
+ config.raise_errors_for_deprecations!
68
+ end
@@ -0,0 +1,3 @@
1
+ require 'coverage/kit'
2
+
3
+ Coverage::Kit.setup(minimum_coverage: 100)
metadata CHANGED
@@ -1,72 +1,215 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: activerecord_null_object
3
- version: !ruby/object:Gem::Version
4
- version: 0.2.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Scott Woods
8
+ - Alessandro Berardi
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
-
12
- date: 2009-09-02 00:00:00 -04:00
13
- default_executable:
14
- dependencies: []
15
-
16
- description: ""
17
- email: info@westarete.com
12
+ date: 2022-01-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '6.0'
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '8'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: '6.0'
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '8'
34
+ - !ruby/object:Gem::Dependency
35
+ name: activerecord
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ - - "<"
42
+ - !ruby/object:Gem::Version
43
+ version: '8'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '6.0'
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '8'
54
+ - !ruby/object:Gem::Dependency
55
+ name: bundler
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rake
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rspec-its
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: coverage-kit
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: sqlite3
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ - !ruby/object:Gem::Dependency
139
+ name: pry-byebug
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ description: Implements the Null Object Pattern for nil values in ActiveRecord associations.
153
+ email:
154
+ - support@travellink.com.au
18
155
  executables: []
19
-
20
156
  extensions: []
21
-
22
- extra_rdoc_files:
23
- - README
24
- files:
25
- - .gitignore
157
+ extra_rdoc_files: []
158
+ files:
159
+ - ".github/dependabot.yml"
160
+ - ".github/workflows/release.yml"
161
+ - ".github/workflows/ruby.yml"
162
+ - ".gitignore"
163
+ - ".ruby-version"
164
+ - CHANGELOG.md
165
+ - Gemfile
26
166
  - MIT-LICENSE
27
- - README
167
+ - README.md
28
168
  - Rakefile
29
169
  - VERSION
30
170
  - activerecord_null_object.gemspec
31
- - init.rb
171
+ - gemfiles/rails60.gemfile
172
+ - gemfiles/rails61.gemfile
173
+ - gemfiles/rails70.gemfile
32
174
  - lib/activerecord_null_object.rb
33
- - lib/null_object.rb
175
+ - lib/activerecord_null_object/null_object.rb
176
+ - lib/activerecord_null_object/null_object_support.rb
177
+ - lib/activerecord_null_object/version.rb
34
178
  - spec/belongs_to_spec.rb
35
- - spec/database.yml
179
+ - spec/has_one_spec.rb
36
180
  - spec/null_object_spec.rb
37
181
  - spec/schema.rb
38
182
  - spec/spec.opts
39
183
  - spec/spec_helper.rb
40
- has_rdoc: true
41
- homepage: http://github.com/westarete/activerecord_null_object/
42
- licenses: []
43
-
184
+ - spec/support/coverage_loader.rb
185
+ homepage: http://github.com/sealink/activerecord_null_object
186
+ licenses:
187
+ - MIT
188
+ metadata: {}
44
189
  post_install_message:
45
- rdoc_options:
46
- - --charset=UTF-8
47
- require_paths:
190
+ rdoc_options: []
191
+ require_paths:
48
192
  - lib
49
- required_ruby_version: !ruby/object:Gem::Requirement
50
- requirements:
193
+ required_ruby_version: !ruby/object:Gem::Requirement
194
+ requirements:
51
195
  - - ">="
52
- - !ruby/object:Gem::Version
53
- version: "0"
54
- version:
55
- required_rubygems_version: !ruby/object:Gem::Requirement
56
- requirements:
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ requirements:
57
200
  - - ">="
58
- - !ruby/object:Gem::Version
59
- version: "0"
60
- version:
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
61
203
  requirements: []
62
-
63
- rubyforge_project:
64
- rubygems_version: 1.3.5
204
+ rubygems_version: 3.3.3
65
205
  signing_key:
66
- specification_version: 2
206
+ specification_version: 4
67
207
  summary: Implements the Null Object Pattern for nil values in ActiveRecord associations.
68
- test_files:
208
+ test_files:
69
209
  - spec/belongs_to_spec.rb
210
+ - spec/has_one_spec.rb
70
211
  - spec/null_object_spec.rb
71
212
  - spec/schema.rb
213
+ - spec/spec.opts
72
214
  - spec/spec_helper.rb
215
+ - spec/support/coverage_loader.rb
data/README DELETED
@@ -1,5 +0,0 @@
1
- = ActiveRecordWithNullObject
2
-
3
- Implements the Null Object Pattern for nil values in ActiveRecord associations.
4
-
5
- Copyright (c) 2009 West Arete Computing, Inc., released under the MIT license
data/init.rb DELETED
@@ -1,5 +0,0 @@
1
- require 'rubygems'
2
- require 'active_record'
3
- ActiveRecord::ActiveRecordError # Workaround for loading bug in AR 2.3.2.
4
- require File.dirname(__FILE__) + '/lib/activerecord_null_object'
5
- require File.dirname(__FILE__) + '/lib/null_object'
data/lib/null_object.rb DELETED
@@ -1,21 +0,0 @@
1
- module ActiveRecordNullObject
2
- module NullObject
3
-
4
- def id
5
- nil
6
- end
7
-
8
- def nil?
9
- true
10
- end
11
-
12
- def empty?
13
- true
14
- end
15
-
16
- def validate
17
- errors.add_to_base("is a null object and can't be saved")
18
- end
19
-
20
- end
21
- end
data/spec/database.yml DELETED
@@ -1,3 +0,0 @@
1
- test:
2
- :adapter: sqlite3
3
- :database: test.db