MockActiveRecord 0.1.0

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