MockActiveRecord 0.1.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/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: