MockActiveRecord 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +21 -0
- data/README +32 -0
- data/lib/mock_active_record.rb +162 -0
- data/tests/mock_active_record_test.rb +69 -0
- metadata +57 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2007 Lone Star Software Engineering Services, Inc.
|
2
|
+
Written by Tony Payne
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Provides facilities for creating mock ActiveRecord objects and their associations.
|
2
|
+
|
3
|
+
Author:: Tony Payne <tony@lonestarsoftware.net>
|
4
|
+
Copyright:: Lone Star Software Engineering Services, Inc., 2007
|
5
|
+
Homepage:: http://lonestarsoftware.net
|
6
|
+
Blog:: http://blog.lonestarsoftware.net
|
7
|
+
License:: MIT
|
8
|
+
Version:: 0.1
|
9
|
+
Dependencies:: RubyGems, ActiveSupport (Inflector)
|
10
|
+
|
11
|
+
Currently, there is not a whole lot of ActiveRecord functionality supported. I've only implemented
|
12
|
+
what I need for the active_resources plugin. Hopefully this will provide a good basis to build on
|
13
|
+
for other needs, as well.
|
14
|
+
|
15
|
+
As of 0.1, *the tests pass with 100% code coverage and pass heckling with no mutations remaining*
|
16
|
+
|
17
|
+
Example:
|
18
|
+
|
19
|
+
include MockActiveRecord::Mixin
|
20
|
+
mock :Book do |book|
|
21
|
+
book.column :id, :integer
|
22
|
+
book.column :title, :string, :default => ''
|
23
|
+
book.column :publisher_id, :integer
|
24
|
+
book.column :foo, :string, :content => false
|
25
|
+
book.column :bar_id, :integer, :content => true
|
26
|
+
|
27
|
+
book.has_many :authorships
|
28
|
+
book.has_many :authors, :through => :authorships
|
29
|
+
book.belongs_to :publisher
|
30
|
+
book.has_one :fresnarus
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
# :include:README
|
5
|
+
# :main:MockActiveRecord
|
6
|
+
# :title:MockActiveRecord Documentation
|
7
|
+
module MockActiveRecord
|
8
|
+
# Represents an association reflection as returned by MockActiveRecord::Base#reflect_on_all_associations
|
9
|
+
class Association
|
10
|
+
include Inflector
|
11
|
+
attr_reader :name, :macro, :primary_key_name, :active_record, :through_reflection, :class_name, :options
|
12
|
+
def initialize(name, macro, active_record, options = {})
|
13
|
+
pk = options.delete(:primary_key_name) || underscore(active_record.name.to_s) + "_id"
|
14
|
+
cn = options.delete(:class_name) || camelize(singularize(name.to_s))
|
15
|
+
@name = name
|
16
|
+
@macro = macro
|
17
|
+
@active_record = active_record
|
18
|
+
@primary_key_name = pk
|
19
|
+
@options = options
|
20
|
+
@class_name = cn
|
21
|
+
@through_reflection = true if options[:through]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Represents an active record column as returned by MockActiveRecord::Base#columns
|
26
|
+
class Column
|
27
|
+
attr_reader :name, :type, :default
|
28
|
+
def initialize(name, type, default=nil)
|
29
|
+
@name = name
|
30
|
+
@type = type
|
31
|
+
@default = default
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Base class from which all mock model objects inherit
|
36
|
+
class Base
|
37
|
+
@@name = ''
|
38
|
+
@@columns = {}
|
39
|
+
@@content_columns = {}
|
40
|
+
@@associations = {}
|
41
|
+
|
42
|
+
# Returns the model name
|
43
|
+
def self.name
|
44
|
+
@@name
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns a list of MockActiveRecord::Column objects in the model
|
48
|
+
def self.columns
|
49
|
+
@@columns.values
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns a hash of MockActiveRecord::Column objects in the model with the name as the key value
|
53
|
+
def self.columns_hash()
|
54
|
+
return @@columns
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns a list of MockActiveRecord::Column objects in the model which contain content
|
58
|
+
def self.content_columns
|
59
|
+
@@content_columns.keys
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns a list of all MockActiveRecord::Association objects in the model
|
63
|
+
def self.reflect_on_all_associations
|
64
|
+
@@associations.values
|
65
|
+
end
|
66
|
+
|
67
|
+
# Adds a :has_many association to the model class
|
68
|
+
# Example:
|
69
|
+
# MockClass.has_many :fresnari, :through => :sharpoze
|
70
|
+
#
|
71
|
+
# Supported options are:
|
72
|
+
# [:through] creates a has-many :through association
|
73
|
+
# [:class_name] sets the name of the associated class
|
74
|
+
def self.has_many(name, options = {})
|
75
|
+
@@associations[name] = MockActiveRecord::Association.new(name, :has_many, self, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Adds a :has_one association to the model class
|
79
|
+
# Example:
|
80
|
+
# MockClass.has_one :fresnarus, :class_name => Sharpoze
|
81
|
+
#
|
82
|
+
# Supported options are:
|
83
|
+
# [:class_name] sets the name of the associated class
|
84
|
+
def self.has_one(name, options = {})
|
85
|
+
@@associations[name] = MockActiveRecord::Association.new(name, :has_one, self, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Adds a :belongs_to association to the model class
|
89
|
+
# Example:
|
90
|
+
# MockClass.belongs_to :fresnarus
|
91
|
+
#
|
92
|
+
# Supported options are:
|
93
|
+
# [:class_name] sets the name of the associated class
|
94
|
+
def self.belongs_to(name, options = {})
|
95
|
+
@@associations[name] = MockActiveRecord::Association.new(name, :belongs_to, self, options)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Adds a column to the model class
|
99
|
+
# Example:
|
100
|
+
# MockClass.column :id, :integer
|
101
|
+
# MockClass.column :kind, :string, :default => 'fresnarus'
|
102
|
+
#
|
103
|
+
# name:: name of column
|
104
|
+
# type:: type of column (:integer, :string, etc)
|
105
|
+
# options:: Supported values are:
|
106
|
+
# [:default] sets the default value for the column
|
107
|
+
# [:content] overrides the default behavior for determining if a column contains meaningful data.
|
108
|
+
# By default, this is determined by the absence of "_id" at the end of the column name
|
109
|
+
# except for the special columns (id, created|update|deleted_at|on, lock_version)
|
110
|
+
def self.column(name, type, options = {})
|
111
|
+
mock_ar_column = MockActiveRecord::Column.new(name.to_s, type, options[:default])
|
112
|
+
@@columns[name.to_sym] = mock_ar_column
|
113
|
+
if options.has_key?(:content)
|
114
|
+
@@content_columns[name.to_sym] = true if options[:content]
|
115
|
+
else
|
116
|
+
@@content_columns[name.to_sym] = true if is_content_column?(name)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Creates a new instance of the model object
|
121
|
+
# attrs:: Set the initial values for the object's columns
|
122
|
+
def initialize(attrs={})
|
123
|
+
@attrs = attrs.dup
|
124
|
+
self.class.columns.each do |column|
|
125
|
+
@attrs[column.name] = column.default
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns the current attribute values for the model instance
|
130
|
+
def attributes
|
131
|
+
@attrs
|
132
|
+
end
|
133
|
+
|
134
|
+
protected
|
135
|
+
# Returns true if the column name looks like it holds meaningful data
|
136
|
+
def self.is_content_column?(name)
|
137
|
+
return false if name.to_s == 'id'
|
138
|
+
return false if name.to_s =~ /_id$/
|
139
|
+
return false if %w(created_at created_on update_at updated_on deleted_at deleted_on lock_version).include?(name.to_s)
|
140
|
+
return true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
module Mixin
|
145
|
+
# Create a new mock class with the given name. The class is yielded to the block so that you can call the setup methods:
|
146
|
+
# mock :Book do |book|
|
147
|
+
# book.column :id, :integer
|
148
|
+
# book.column :title, :string
|
149
|
+
# book.has_many :authorships
|
150
|
+
# book.has_many :authors, :through => :authorships
|
151
|
+
# etc...
|
152
|
+
# end
|
153
|
+
def mock(name, &block) # :yields: Class
|
154
|
+
Kernel.module_eval <<-__END__
|
155
|
+
class #{name} < MockActiveRecord::Base
|
156
|
+
@@name = "#{name}"
|
157
|
+
end
|
158
|
+
__END__
|
159
|
+
yield Kernel.const_get(name)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/mock_active_record")
|
3
|
+
class ActiveResourcesTest < Test::Unit::TestCase
|
4
|
+
include MockActiveRecord::Mixin
|
5
|
+
public
|
6
|
+
def setup
|
7
|
+
mock :Book do |book|
|
8
|
+
book.column :id, :integer
|
9
|
+
book.column :title, :string, :default => ''
|
10
|
+
book.column :publisher_id, :integer
|
11
|
+
book.column :foo, :string, :content => false
|
12
|
+
book.column :bar_id, :integer, :content => true
|
13
|
+
|
14
|
+
book.has_many :authorships
|
15
|
+
book.has_many :authors, :through => :authorships
|
16
|
+
book.belongs_to :publisher
|
17
|
+
book.has_one :fresnarus
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_name
|
22
|
+
assert_equal 'Book', Book.name
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_columns
|
26
|
+
assert_equal ['bar_id', 'foo', 'id', 'publisher_id', 'title'], Book.columns.collect{|c| c.name}.sort
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_columns_hash
|
30
|
+
h = Book.columns_hash
|
31
|
+
|
32
|
+
assert h.has_key?(:id)
|
33
|
+
assert_equal 'id', h[:id].name
|
34
|
+
assert_equal :integer, h[:id].type
|
35
|
+
|
36
|
+
assert h.has_key?(:publisher_id)
|
37
|
+
assert_equal 'publisher_id', h[:publisher_id].name
|
38
|
+
assert_equal :integer, h[:publisher_id].type
|
39
|
+
|
40
|
+
assert h.has_key?(:title)
|
41
|
+
assert_equal 'title', h[:title].name
|
42
|
+
assert_equal :string, h[:title].type
|
43
|
+
|
44
|
+
assert h.has_key?(:foo)
|
45
|
+
assert_equal 'foo', h[:foo].name
|
46
|
+
assert_equal :string, h[:foo].type
|
47
|
+
|
48
|
+
assert h.has_key?(:bar_id)
|
49
|
+
assert_equal 'bar_id', h[:bar_id].name
|
50
|
+
assert_equal :integer, h[:bar_id].type
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_content_columns
|
54
|
+
assert_equal ['bar_id', 'title'], Book.content_columns.collect{|c| c.to_s}.sort
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_reflect_on_all_associations
|
58
|
+
assert_equal ['authors', 'authorships', 'fresnarus', 'publisher'], Book.reflect_on_all_associations.collect{|a| a.name.to_s}.sort
|
59
|
+
assert_equal [:has_many, :has_many, :has_one, :belongs_to], Book.reflect_on_all_associations.sort_by{|a| a.name.to_s}.collect{|a| a.macro}
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_new
|
63
|
+
assert_equal 'Book', Book.new.class.name
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_attrs
|
67
|
+
assert_equal({'bar_id' => nil, 'foo' => nil, 'id' => nil, 'publisher_id' => nil, 'title' => ''}, Book.new.attributes)
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: MockActiveRecord
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-03-09 00:00:00 -08:00
|
8
|
+
summary: Mock ActiveRecord Classes
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: tony@lonestarsoftware.net
|
12
|
+
homepage: http://lonestarsoftware.net/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: mock_active_record
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Tony Payne
|
31
|
+
files:
|
32
|
+
- tests/mock_active_record_test.rb
|
33
|
+
- lib/mock_active_record.rb
|
34
|
+
- README
|
35
|
+
- MIT-LICENSE
|
36
|
+
test_files:
|
37
|
+
- tests/mock_active_record_test.rb
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
executables: []
|
43
|
+
|
44
|
+
extensions: []
|
45
|
+
|
46
|
+
requirements: []
|
47
|
+
|
48
|
+
dependencies:
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: activesupport
|
51
|
+
version_requirement:
|
52
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.0.0
|
57
|
+
version:
|