westarete-activerecord_null_object 0.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.
- data/.gitignore +2 -0
- data/MIT-LICENSE +20 -0
- data/README +5 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/init.rb +5 -0
- data/lib/activerecord_null_object.rb +46 -0
- data/lib/null_object.rb +33 -0
- data/spec/belongs_to_spec.rb +77 -0
- data/spec/database.yml +3 -0
- data/spec/null_object_spec.rb +70 -0
- data/spec/schema.rb +28 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +29 -0
- metadata +70 -0
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
require 'init'
|
4
|
+
|
5
|
+
desc 'Default: run specs.'
|
6
|
+
task :default => :spec
|
7
|
+
|
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
|
12
|
+
|
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"
|
25
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/init.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
# Add a boolean :null_object option to belongs_to.
|
6
|
+
def belongs_to_with_null_object(association_id, options = {}) #:nodoc:
|
7
|
+
# Extract our custom option.
|
8
|
+
use_null_object = options.delete(:null_object)
|
9
|
+
# Call the real belongs_to so that the association gets defined.
|
10
|
+
belongs_to_without_null_object(association_id, options)
|
11
|
+
# Modify the association if need be.
|
12
|
+
if use_null_object
|
13
|
+
|
14
|
+
# Determine the class of the association.
|
15
|
+
association_class_name = options[:class_name] || association_id.to_s.classify
|
16
|
+
association_class = association_class_name.constantize
|
17
|
+
|
18
|
+
# Determine the null class for this association.
|
19
|
+
null_class_name = "Null" + association_class_name
|
20
|
+
if Object.const_defined?(null_class_name)
|
21
|
+
null_class = Object.const_get(null_class_name.to_sym)
|
22
|
+
else
|
23
|
+
# Define the null class as an ancestor of the association class.
|
24
|
+
null_class = Object.const_set(null_class_name, Class.new(association_class))
|
25
|
+
null_class.class_eval do
|
26
|
+
include Singleton
|
27
|
+
include ActiveRecordNullObject::NullObject
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Modify the "getter" of the belongs_to relationship to return an
|
32
|
+
# instance of the association's null object instead of returning nil.
|
33
|
+
class_eval do
|
34
|
+
define_method("#{association_id}_with_null_object".to_sym) do
|
35
|
+
send("#{association_id}_without_null_object".to_sym) || null_class.instance
|
36
|
+
end
|
37
|
+
alias_method_chain association_id, :null_object
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method_chain :belongs_to, :null_object
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/null_object.rb
ADDED
@@ -0,0 +1,33 @@
|
|
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 new_record?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def save
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def save!
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_attributes(attributes)
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_attributes!(attributes)
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
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
|
11
|
+
|
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 nil for the author's name" do
|
22
|
+
@comment.author.name.should be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "with an author" do
|
27
|
+
before(:each) do
|
28
|
+
@comment.author = Author.create!(:name => 'James Baker')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return the author object" do
|
32
|
+
@comment.author.kind_of?(Author).should be_true
|
33
|
+
@comment.author.kind_of?(NullAuthor).should_not be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return the author's name" do
|
37
|
+
@comment.author.name.should == 'James Baker'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should revert to a null object if assigned nil" do
|
41
|
+
@comment.author = nil
|
42
|
+
@comment.author.name.should be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Post do
|
48
|
+
before(:each) do
|
49
|
+
@post = Post.create!(:body => 'The body.')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should contain a body" do
|
53
|
+
@post.body.should == 'The body.'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not have null object support for the author" do
|
57
|
+
@post.author.should be_nil
|
58
|
+
@post.author.kind_of?(Author).should be_false
|
59
|
+
@post.author.respond_to?(:name).should be_false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Session do
|
64
|
+
before(:each) do
|
65
|
+
@session = Session.create!(:description => 'The description.')
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should contain a description" do
|
69
|
+
@session.description.should == 'The description.'
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not have null object support for the author" do
|
73
|
+
@session.author.should be_nil
|
74
|
+
@session.author.kind_of?(Author).should be_false
|
75
|
+
@session.author.respond_to?(:name).should be_false
|
76
|
+
end
|
77
|
+
end
|
data/spec/database.yml
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
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
|
12
|
+
|
13
|
+
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
|
+
describe "#id" do
|
23
|
+
it "should return nil" do
|
24
|
+
@null_author.id.should be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#new_record?" do
|
29
|
+
it "should return false" do
|
30
|
+
@null_author.new_record?.should be_false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#save" do
|
35
|
+
it "should return true" do
|
36
|
+
@null_author.save.should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not create a new record" do
|
40
|
+
lambda { @null_author.save }.should_not change { NullAuthor.count }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#save!" do
|
45
|
+
it "should return true" do
|
46
|
+
@null_author.save!.should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not create a new record" do
|
50
|
+
lambda { @null_author.save! }.should_not change { NullAuthor.count }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#update_attributes" do
|
55
|
+
it "should return true" do
|
56
|
+
@null_author.update_attributes({}).should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not create a new record" do
|
60
|
+
lambda { @null_author.update_attributes({}) }.should_not change { NullAuthor.count }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#name" do
|
65
|
+
it "should return nil" do
|
66
|
+
@null_author.name.should be_nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
create_table "authors", :force => true do |t|
|
3
|
+
t.string "name"
|
4
|
+
t.datetime "created_at"
|
5
|
+
t.datetime "updated_at"
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table "comments", :force => true do |t|
|
9
|
+
t.text "body"
|
10
|
+
t.integer "author_id"
|
11
|
+
t.datetime "created_at"
|
12
|
+
t.datetime "updated_at"
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table "posts", :force => true do |t|
|
16
|
+
t.text "body"
|
17
|
+
t.integer "author_id"
|
18
|
+
t.datetime "created_at"
|
19
|
+
t.datetime "updated_at"
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table "sessions", :force => true do |t|
|
23
|
+
t.text "description"
|
24
|
+
t.integer "author_id"
|
25
|
+
t.datetime "created_at"
|
26
|
+
t.datetime "updated_at"
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'activerecord'
|
3
|
+
require 'yaml'
|
4
|
+
require 'spec'
|
5
|
+
require File.dirname(__FILE__) + '/../init.rb'
|
6
|
+
|
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")
|
11
|
+
|
12
|
+
# Define ActiveRecord classes to use while testing.
|
13
|
+
class Author < ActiveRecord::Base
|
14
|
+
has_many :posts
|
15
|
+
has_many :comments
|
16
|
+
has_many :sessions
|
17
|
+
end
|
18
|
+
|
19
|
+
class Comment < ActiveRecord::Base
|
20
|
+
belongs_to :author, :null_object => true
|
21
|
+
end
|
22
|
+
|
23
|
+
class Post < ActiveRecord::Base
|
24
|
+
belongs_to :author, :null_object => false
|
25
|
+
end
|
26
|
+
|
27
|
+
class Session < ActiveRecord::Base
|
28
|
+
belongs_to :author
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: westarete-activerecord_null_object
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Scott Woods
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-12 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ""
|
17
|
+
email: info@westarete.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- VERSION
|
30
|
+
- init.rb
|
31
|
+
- lib/activerecord_null_object.rb
|
32
|
+
- lib/null_object.rb
|
33
|
+
- spec/belongs_to_spec.rb
|
34
|
+
- spec/database.yml
|
35
|
+
- spec/null_object_spec.rb
|
36
|
+
- spec/schema.rb
|
37
|
+
- spec/spec.opts
|
38
|
+
- spec/spec_helper.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: http://github.com/westarete/activerecord_null_object/
|
41
|
+
licenses:
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options:
|
44
|
+
- --charset=UTF-8
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.3.5
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: Implements the Null Object Pattern for nil values in ActiveRecord associations.
|
66
|
+
test_files:
|
67
|
+
- spec/belongs_to_spec.rb
|
68
|
+
- spec/null_object_spec.rb
|
69
|
+
- spec/schema.rb
|
70
|
+
- spec/spec_helper.rb
|