active_null 0.0.6 → 1.0.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: cd467d1bb5d62ddde65883fa1c81aa8a55d8747c
4
- data.tar.gz: c092e04b7d8c27ad222097cd619b6d425d41e8b9
3
+ metadata.gz: 34802b6bb45c168b836473546d630a125fe6b116
4
+ data.tar.gz: db5beef0d960320f86938d4a04cc38b22d9be4bd
5
5
  SHA512:
6
- metadata.gz: 0839b2c1846c5f1caf4aec78851177b3db1024e810b77524bd2c12a3a32fe9e3862a99d761cfeae9ba0b35630fbd72bcfecea731835d1cf24155fffed0c0db29
7
- data.tar.gz: 30379d39ba04426101921d1c72d19b1dc2371c9573f5dedda4af23c8c3bd624e394ca3b8f1107710edbf3b4c12bbd6f1c8ae2c7265e6db4154f846c7806e44e9
6
+ metadata.gz: 53077a09ae14ecb32e5ef97df52b7178580fabde3cb0f9e5136219e9e6fdabae7eefa200986d95c899a76c76ec682d237a222ebcac9f978422979d82377c6d9d
7
+ data.tar.gz: d9a9dbf632553cf2eaa5ec794b17a1fd83b3f510cd77d81eeaa94d47c1cd5960fb3c2ca2b88f641f83279b48ada6168af5fbf1d28c1b1fbd52d0218c317e0011
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ [![Circle CI](https://circleci.com/gh/Originate/active_null.svg?style=shield)](https://circleci.com/gh/Originate/active_null)
2
+ [![Coverage Status](https://coveralls.io/repos/Originate/active_null/badge.svg?branch=master&service=github)](https://coveralls.io/github/Originate/active_null?branch=master)
3
+ [![Code Climate](https://codeclimate.com/github/Originate/active_null/badges/gpa.svg)](https://codeclimate.com/github/Originate/active_null)
4
+
1
5
  # ActiveNull
2
6
 
3
7
  Using Null Objects can make life a lot easier and avoid having excessive `nil?` checks.
@@ -34,13 +38,11 @@ For each model you would like to be null aware, `extend ActiveNull`.
34
38
  class Post < ActiveRecord::Base
35
39
  extend ActiveNull
36
40
  has_many :comments
37
- null_model
38
41
  end
39
42
 
40
43
  class Comment < ActiveRecord::Base
41
44
  extend ActiveNull
42
45
  belongs_to :post
43
- null_model
44
46
  end
45
47
  ```
46
48
 
@@ -74,6 +76,17 @@ class Post < ActiveRecord::Base
74
76
  end
75
77
  ```
76
78
 
79
+ When using polymorphic relationships, ActiveNull must be told a default
80
+ model to use for the Null Object representation.
81
+
82
+ ```ruby
83
+ class Post < ActiveRecord::Base
84
+ extend ActiveNull
85
+ belongs_to :author, polymorphic: true
86
+ null_defaults_for_polymorphic author: 'User'
87
+ end
88
+ ```
89
+
77
90
  If you have `Draper` included in your project, the Null Object versions of
78
91
  your model will respond as expected to `decorate`.
79
92
 
data/active_null.gemspec CHANGED
@@ -23,7 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency 'bundler', '~> 1.6'
24
24
  spec.add_development_dependency 'rake'
25
25
  spec.add_development_dependency 'rspec'
26
- spec.add_development_dependency 'activerecord', '~> 4.1'
26
+ spec.add_development_dependency 'activerecord', '~> 4.2'
27
27
  spec.add_development_dependency 'sqlite3'
28
- spec.add_development_dependency 'draper', '~> 1.3'
28
+ spec.add_development_dependency 'draper', '~> 2.1'
29
+ spec.add_development_dependency 'coveralls'
29
30
  end
data/circle.yml ADDED
@@ -0,0 +1,3 @@
1
+ database:
2
+ override:
3
+ - echo skip database setup
@@ -15,12 +15,22 @@ module ActiveNull
15
15
  config.impersonate model
16
16
 
17
17
  model.reflect_on_all_associations.each do |relation|
18
+ klass = begin
19
+ if relation.options[:polymorphic]
20
+ model.polymorphic_null_defaults[relation.name].constantize
21
+ else
22
+ relation.klass
23
+ end
24
+ rescue
25
+ nil
26
+ end
27
+ next unless klass
18
28
  if relation.collection?
19
- define_method(relation.name) { relation.klass.none }
29
+ define_method(relation.name) { klass.none }
20
30
  else
21
31
  define_method(relation.name) do
22
- return unless relation.klass.respond_to? :null
23
- relation.klass.null
32
+ return unless klass.respond_to? :null
33
+ klass.null
24
34
  end
25
35
  end
26
36
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveNull
2
- VERSION = '0.0.6'
2
+ VERSION = '1.0.0'
3
3
  end
data/lib/active_null.rb CHANGED
@@ -6,6 +6,14 @@ module ActiveNull
6
6
  null_class.get
7
7
  end
8
8
 
9
+ def null_defaults_for_polymorphic mappings
10
+ @polymorphic_null_defaults = mappings
11
+ end
12
+
13
+ def polymorphic_null_defaults
14
+ @polymorphic_null_defaults || {}
15
+ end
16
+
9
17
  def null_model(&block)
10
18
  @null_model_overrides = if block_given?
11
19
  Module.new.tap { |m| m.module_eval(&block) }
@@ -19,11 +27,21 @@ module ActiveNull
19
27
  def null_associations
20
28
  self.reflect_on_all_associations.each do |relation|
21
29
  unless relation.collection?
30
+ klass = begin
31
+ if relation.options[:polymorphic]
32
+ polymorphic_null_defaults[relation.name]
33
+ elsif relation.klass
34
+ relation.klass.name
35
+ end
36
+ rescue
37
+ nil
38
+ end
39
+ next unless klass
22
40
  class_eval <<-CODE
23
41
  def #{relation.name}(*args)
24
42
  result = association(:#{relation.name}).reader(*args)
25
- return result if result || !#{relation.klass.name}.respond_to?(:null)
26
- #{relation.klass.name}.null
43
+ return result if result || !#{klass}.respond_to?(:null)
44
+ #{klass}.null
27
45
  end
28
46
  CODE
29
47
  end
@@ -4,10 +4,11 @@ describe ActiveNull do
4
4
  it 'defines the null class only when accessing it for the first time (ie: with a .null or .null_class call)' do
5
5
  expect(Object.const_defined? 'NullPost').to be_falsey
6
6
  expect(Object.const_defined? 'NullMicroPost').to be_falsey
7
- expect(Post.null).to be_instance_of(NullPost)
7
+ expect(Post.null).to be_instance_of NullPost
8
8
  expect(MicroPost.null_class).to eq NullMicroPost
9
9
  expect(Object.const_defined? 'NullPost').to be_truthy
10
10
  expect(Object.const_defined? 'NullMicroPost').to be_truthy
11
+ expect(Test::TestModel.null).to be_instance_of Test::NullTestModel
11
12
  end
12
13
 
13
14
  describe '.null_class' do
@@ -24,6 +25,10 @@ describe ActiveNull do
24
25
  specify { expect(Post.null.override).to eq 'I am an override.' }
25
26
  end
26
27
 
28
+ describe '.find_by' do
29
+ specify { expect(Test::TestModel.find_by(id: 42)).to be_instance_of(Test::NullTestModel) }
30
+ end
31
+
27
32
  describe 'a has many' do
28
33
  specify { expect(Post.null.comments).to eq [] }
29
34
  specify { expect(Post.null.comments).to be_instance_of(Comment::ActiveRecord_Relation) }
@@ -34,6 +39,8 @@ describe ActiveNull do
34
39
  describe 'a belongs to' do
35
40
  specify { expect(Comment.null.post).to be_instance_of(NullPost) }
36
41
  specify { expect(Comment.new.post).to be_instance_of(NullPost) }
42
+ specify { expect(Comment.null.author).to be_instance_of(NullUser) }
43
+ specify { expect(Comment.new.author).to be_instance_of(NullUser) }
37
44
  end
38
45
 
39
46
  it 'supports draper' do
data/spec/models.rb CHANGED
@@ -10,13 +10,18 @@ end
10
10
 
11
11
  class MicroPost < Post
12
12
  extend ActiveNull
13
- null_model
13
+ end
14
+
15
+ class User < ActiveRecord::Base
16
+ extend ActiveNull
17
+ has_many :comments, as: :author
14
18
  end
15
19
 
16
20
  class Comment < ActiveRecord::Base
17
21
  extend ActiveNull
18
22
  belongs_to :post
19
- null_model
23
+ belongs_to :author, polymorphic: true
24
+ null_defaults_for_polymorphic author: 'User'
20
25
  end
21
26
 
22
27
  class NullPostDecorator < Draper::Decorator
@@ -30,6 +35,5 @@ end
30
35
  module Test
31
36
  class TestModel < ActiveRecord::Base
32
37
  extend ActiveNull
33
- null_model
34
38
  end
35
39
  end
data/spec/null_spec.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Null Models' do
4
+ subject(:null_model) { Test::TestModel.null }
5
+
6
+ describe '#nil?' do
7
+ specify { expect(null_model.nil?).to be_truthy }
8
+ end
9
+
10
+ describe '#present?' do
11
+ specify { expect(null_model.present?).to be_falsey }
12
+ end
13
+
14
+ describe '#blank?' do
15
+ specify { expect(null_model.blank?).to be_truthy }
16
+ end
17
+
18
+ describe '#to_json' do
19
+ specify { expect(null_model.to_json).to eq '{}' }
20
+ end
21
+
22
+ context 'Decoratable Null Models' do
23
+ subject(:null_model) { Post.null }
24
+
25
+ describe '#decorate' do
26
+ specify { expect(null_model.decorate).to be_decorated_with(null_model.decorator_class) }
27
+ end
28
+
29
+ describe '#decorator_class?' do
30
+ specify { expect(null_model.decorator_class?).to eq NullPostDecorator }
31
+ end
32
+
33
+ describe '#decorator_class' do
34
+ specify { expect(null_model.decorator_class).to eq NullPostDecorator }
35
+ end
36
+
37
+ context 'when not yet decorated' do
38
+ describe '#decorated?' do
39
+ specify { expect(null_model.decorated?).to be_falsey }
40
+ end
41
+
42
+ describe '#decorated_with?' do
43
+ specify { expect(null_model.decorated_with?(null_model.decorator_class)).to be_falsey }
44
+ end
45
+
46
+ describe '#applied_decorators' do
47
+ specify { expect(null_model.applied_decorators).to eq [] }
48
+ end
49
+ end
50
+
51
+ context 'when decorated' do
52
+ subject(:null_model) { Post.null.decorate }
53
+
54
+ describe '#decorated?' do
55
+ specify { expect(null_model.decorated?).to be_truthy }
56
+ end
57
+
58
+ describe '#decorated_with?' do
59
+ specify { expect(null_model.decorated_with?(null_model.decorator_class)).to be_truthy }
60
+ end
61
+
62
+ describe '#applied_decorators' do
63
+ specify { expect(null_model.applied_decorators).to eq [NullPostDecorator] }
64
+ end
65
+ end
66
+ end
67
+ end
data/spec/schema.rb CHANGED
@@ -4,16 +4,22 @@ ActiveRecord::Schema.define do
4
4
  create_table :posts, force: true do |t|
5
5
  t.string :title
6
6
  t.string :_type
7
- t.timestamps
7
+ t.timestamps null: true
8
+ end
9
+
10
+ create_table :users, force: true do |t|
11
+ t.string :name
12
+ t.timestamps null: true
8
13
  end
9
14
 
10
15
  create_table :comments, force: true do |t|
11
16
  t.string :content
12
17
  t.references :post
13
- t.timestamps
18
+ t.references :author, polymorphic: true
19
+ t.timestamps null: true
14
20
  end
15
21
 
16
22
  create_table :test_models, force: true do |t|
17
- t.timestamps
23
+ t.timestamps null: true
18
24
  end
19
25
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
1
4
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
5
  require 'active_null'
3
6
  require 'active_record'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_null
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alexpeachey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-25 00:00:00.000000000 Z
11
+ date: 2016-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: naught
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '4.1'
75
+ version: '4.2'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '4.1'
82
+ version: '4.2'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: sqlite3
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +100,28 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '1.3'
103
+ version: '2.1'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '1.3'
110
+ version: '2.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: coveralls
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'
111
125
  description: Make ActiveRecord null model aware.
112
126
  email:
113
127
  - alex.peachey@originate.com
@@ -117,17 +131,18 @@ extra_rdoc_files: []
117
131
  files:
118
132
  - ".gitignore"
119
133
  - ".rspec"
120
- - ".travis.yml"
121
134
  - Gemfile
122
135
  - LICENSE.txt
123
136
  - README.md
124
137
  - Rakefile
125
138
  - active_null.gemspec
139
+ - circle.yml
126
140
  - lib/active_null.rb
127
141
  - lib/active_null/null_model_builder.rb
128
142
  - lib/active_null/version.rb
129
143
  - spec/active_null_spec.rb
130
144
  - spec/models.rb
145
+ - spec/null_spec.rb
131
146
  - spec/schema.rb
132
147
  - spec/spec_helper.rb
133
148
  homepage: https://github.com/Originate/active_null
@@ -150,12 +165,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
165
  version: '0'
151
166
  requirements: []
152
167
  rubyforge_project:
153
- rubygems_version: 2.4.5
168
+ rubygems_version: 2.4.6
154
169
  signing_key:
155
170
  specification_version: 4
156
171
  summary: Make ActiveRecord null model aware.
157
172
  test_files:
158
173
  - spec/active_null_spec.rb
159
174
  - spec/models.rb
175
+ - spec/null_spec.rb
160
176
  - spec/schema.rb
161
177
  - spec/spec_helper.rb
data/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.1.2