active_null 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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