active_mocker 1.3.2 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/README.md +136 -24
  4. data/Rakefile +8 -2
  5. data/active_mocker.gemspec +3 -3
  6. data/lib/active_mock/association.rb +7 -0
  7. data/lib/active_mock/base.rb +250 -0
  8. data/lib/active_mock/collection.rb +52 -0
  9. data/lib/active_mock/creators.rb +25 -0
  10. data/lib/active_mock/do_nothing_active_record_methods.rb +51 -0
  11. data/lib/active_mock/has_and_belongs_to_many.rb +7 -0
  12. data/lib/active_mock/has_many.rb +54 -0
  13. data/lib/active_mock/next_id.rb +16 -0
  14. data/lib/active_mock/object_inspect.rb +39 -0
  15. data/lib/{active_mocker/collection → active_mock}/queries.rb +26 -19
  16. data/lib/active_mock/records.rb +81 -0
  17. data/lib/active_mock/relation.rb +8 -0
  18. data/lib/active_mocker.rb +3 -1
  19. data/lib/active_mocker/active_mock.rb +26 -0
  20. data/lib/active_mocker/active_record.rb +18 -0
  21. data/lib/active_mocker/active_record/relationships.rb +57 -6
  22. data/lib/active_mocker/active_record/schema.rb +1 -1
  23. data/lib/active_mocker/active_record/scope.rb +1 -1
  24. data/lib/active_mocker/active_record/unknown_class_method.rb +1 -1
  25. data/lib/active_mocker/active_record/unknown_module.rb +10 -9
  26. data/lib/active_mocker/db_to_ruby_type.rb +26 -0
  27. data/lib/active_mocker/field.rb +16 -8
  28. data/lib/active_mocker/generate.rb +19 -174
  29. data/lib/active_mocker/loaded_mocks.rb +48 -8
  30. data/lib/active_mocker/logger.rb +2 -0
  31. data/lib/active_mocker/mock_template.erb +123 -53
  32. data/lib/active_mocker/model_reader.rb +42 -13
  33. data/lib/active_mocker/model_schema.rb +279 -0
  34. data/lib/active_mocker/model_schema/generate.rb +175 -0
  35. data/lib/active_mocker/reparameterize.rb +23 -3
  36. data/lib/active_mocker/table.rb +2 -2
  37. data/lib/active_mocker/version.rb +1 -1
  38. data/sample_app_rails_4/Gemfile +1 -1
  39. data/sample_app_rails_4/app/models/micropost.rb +13 -1
  40. data/sample_app_rails_4/db/schema.rb +1 -1
  41. data/sample_app_rails_4/spec/compare_mocker_and_record_spec.rb +194 -7
  42. data/sample_app_rails_4/spec/micropost_mock_spec.rb +145 -0
  43. data/sample_app_rails_4/spec/mocks/micropost_mock.rb +81 -55
  44. data/sample_app_rails_4/spec/mocks/relationship_mock.rb +85 -54
  45. data/sample_app_rails_4/spec/mocks/user_mock.rb +71 -72
  46. data/sample_app_rails_4/spec/reload_spec.rb +1 -1
  47. data/sample_app_rails_4/spec/user_mock_spec.rb +25 -7
  48. data/spec/lib/acitve_mock/queriable_spec.rb +207 -0
  49. data/spec/lib/active_mocker/db_to_ruby_type_spec.rb +124 -0
  50. data/spec/lib/active_mocker/loaded_mocks_spec.rb +167 -0
  51. data/spec/lib/active_mocker/logger_spec.rb +32 -0
  52. data/spec/lib/active_mocker/model_reader_spec.rb +79 -28
  53. data/spec/lib/active_mocker/model_schema/generate_spec.rb +111 -0
  54. data/spec/lib/active_mocker/model_schema_spec.rb +145 -0
  55. data/spec/lib/model.rb +2 -1
  56. data/spec/lib/reparameterize_spec.rb +202 -0
  57. data/spec/unit_logger.rb +2 -2
  58. metadata +55 -35
  59. data/lib/active_hash/ar_api.rb +0 -77
  60. data/lib/active_hash/init.rb +0 -32
  61. data/lib/active_mocker/collection/association.rb +0 -12
  62. data/lib/active_mocker/collection/base.rb +0 -65
  63. data/lib/active_mocker/collection/relation.rb +0 -11
  64. data/lib/active_mocker/mock_class_methods.rb +0 -92
  65. data/lib/active_mocker/mock_instance_methods.rb +0 -84
  66. data/lib/active_mocker/mock_requires.rb +0 -10
  67. data/spec/lib/active_mocker/collection.rb +0 -94
@@ -1,24 +1,46 @@
1
- require 'active_mocker/mock_requires'
2
- Object.send(:remove_const, "UserMock") if ActiveMocker.class_exists?("UserMock")
1
+ require 'active_mocker/active_mock'
2
+ Object.send(:remove_const, "UserMock") if Object.const_defined?("UserMock")
3
3
 
4
- class UserMock < ::ActiveHash::Base
5
- include ActiveMocker::ActiveHash::ARApi
6
- include ActiveMocker::MockInstanceMethods
7
- extend ActiveMocker::MockClassMethods
4
+ class UserMock < ActiveMock::Base
8
5
 
9
- def initialize(attributes={}, &block)
10
- @attributes = HashWithIndifferentAccess.new({"id"=>nil, "name"=>nil, "email"=>"", "credits"=>nil, "created_at"=>nil, "updated_at"=>nil, "password_digest"=>nil, "remember_token"=>true, "admin"=>false})
11
- @associations = HashWithIndifferentAccess.new({:microposts=>nil, :relationships=>nil, :followed_users=>nil, :reverse_relationships=>nil, :followers=>nil})
12
- super(attributes, &block)
13
- end
6
+ class << self
14
7
 
8
+ def attributes
9
+ @attributes ||= HashWithIndifferentAccess.new({"id"=>nil, "name"=>nil, "email"=>"", "credits"=>nil, "created_at"=>nil, "updated_at"=>nil, "password_digest"=>nil, "remember_token"=>true, "admin"=>false})
10
+ end
15
11
 
16
- def self.column_names
17
- ["id", "name", "email", "credits", "created_at", "updated_at", "password_digest", "remember_token", "admin"]
18
- end
12
+ def types
13
+ @types ||= { id: build_type(Fixnum), name: build_type(String), email: build_type(String), credits: build_type(BigDecimal), created_at: build_type(DateTime), updated_at: build_type(DateTime), password_digest: build_type(String), remember_token: build_type(Axiom::Types::Boolean), admin: build_type(Axiom::Types::Boolean) }
14
+ end
15
+
16
+ def associations
17
+ @associations ||= {:microposts=>nil, :relationships=>nil, :followed_users=>nil, :reverse_relationships=>nil, :followers=>nil}
18
+ end
19
+
20
+ def model_instance_methods
21
+ @model_instance_methods ||= {"feed"=>:not_implemented, "following?"=>:not_implemented, "follow!"=>:not_implemented, "unfollow!"=>:not_implemented}
22
+ end
23
+
24
+ def model_class_methods
25
+ @model_class_methods ||= {"new_remember_token"=>:not_implemented, "digest"=>:not_implemented}
26
+ end
27
+
28
+ def mocked_class
29
+ 'User'
30
+ end
31
+
32
+ def column_names
33
+ attribute_names
34
+ end
35
+
36
+ def attribute_names
37
+ @attribute_names ||= ["id", "name", "email", "credits", "created_at", "updated_at", "password_digest", "remember_token", "admin"]
38
+ end
39
+
40
+ def primary_key
41
+ "id"
42
+ end
19
43
 
20
- def self.attribute_names
21
- @attribute_names = ["id", "name", "email", "credits", "created_at", "updated_at", "password_digest", "remember_token", "admin"]
22
44
  end
23
45
 
24
46
  ##################################
@@ -26,150 +48,127 @@ class UserMock < ::ActiveHash::Base
26
48
  ##################################
27
49
 
28
50
  def id
29
- @attributes['id']
51
+ read_attribute(:id)
30
52
  end
31
53
 
32
54
  def id=(val)
33
- type = (types[:id] ||= Virtus::Attribute.build(Fixnum))
34
- @attributes['id'] = type.coerce(val)
55
+ write_attribute(:id, val)
35
56
  end
36
57
 
37
58
  def name
38
- @attributes['name']
59
+ read_attribute(:name)
39
60
  end
40
61
 
41
62
  def name=(val)
42
- type = (types[:name] ||= Virtus::Attribute.build(String))
43
- @attributes['name'] = type.coerce(val)
63
+ write_attribute(:name, val)
44
64
  end
45
65
 
46
66
  def email
47
- @attributes['email']
67
+ read_attribute(:email)
48
68
  end
49
69
 
50
70
  def email=(val)
51
- type = (types[:email] ||= Virtus::Attribute.build(String))
52
- @attributes['email'] = type.coerce(val)
71
+ write_attribute(:email, val)
53
72
  end
54
73
 
55
74
  def credits
56
- @attributes['credits']
75
+ read_attribute(:credits)
57
76
  end
58
77
 
59
78
  def credits=(val)
60
- type = (types[:credits] ||= Virtus::Attribute.build(BigDecimal))
61
- @attributes['credits'] = type.coerce(val)
79
+ write_attribute(:credits, val)
62
80
  end
63
81
 
64
82
  def created_at
65
- @attributes['created_at']
83
+ read_attribute(:created_at)
66
84
  end
67
85
 
68
86
  def created_at=(val)
69
- type = (types[:created_at] ||= Virtus::Attribute.build(DateTime))
70
- @attributes['created_at'] = type.coerce(val)
87
+ write_attribute(:created_at, val)
71
88
  end
72
89
 
73
90
  def updated_at
74
- @attributes['updated_at']
91
+ read_attribute(:updated_at)
75
92
  end
76
93
 
77
94
  def updated_at=(val)
78
- type = (types[:updated_at] ||= Virtus::Attribute.build(DateTime))
79
- @attributes['updated_at'] = type.coerce(val)
95
+ write_attribute(:updated_at, val)
80
96
  end
81
97
 
82
98
  def password_digest
83
- @attributes['password_digest']
99
+ read_attribute(:password_digest)
84
100
  end
85
101
 
86
102
  def password_digest=(val)
87
- type = (types[:password_digest] ||= Virtus::Attribute.build(String))
88
- @attributes['password_digest'] = type.coerce(val)
103
+ write_attribute(:password_digest, val)
89
104
  end
90
105
 
91
106
  def remember_token
92
- @attributes['remember_token']
107
+ read_attribute(:remember_token)
93
108
  end
94
109
 
95
110
  def remember_token=(val)
96
- type = (types[:remember_token] ||= Virtus::Attribute.build(Virtus::Attribute::Boolean))
97
- @attributes['remember_token'] = type.coerce(val)
111
+ write_attribute(:remember_token, val)
98
112
  end
99
113
 
100
114
  def admin
101
- @attributes['admin']
115
+ read_attribute(:admin)
102
116
  end
103
117
 
104
118
  def admin=(val)
105
- type = (types[:admin] ||= Virtus::Attribute.build(Virtus::Attribute::Boolean))
106
- @attributes['admin'] = type.coerce(val)
119
+ write_attribute(:admin, val)
107
120
  end
108
121
 
109
122
  ##################################
110
- # Association getter/setters #
123
+ # Associations #
111
124
  ##################################
112
125
 
113
- def self.association_names
114
- @association_names = [:microposts, :relationships, :followed_users, :reverse_relationships, :followers]
115
- end
116
126
 
127
+ # has_many
117
128
  def microposts
118
- associations['microposts'] ||= ActiveMocker::Collection::Association.new
129
+ @associations[:microposts] ||= ActiveMock::HasMany.new([],'user_id', @attributes['id'], classes('Micropost'))
119
130
  end
120
131
 
121
132
  def microposts=(val)
122
- associations['microposts'] = ActiveMocker::Collection::Association.new(val)
133
+ @associations[:microposts] ||= ActiveMock::HasMany.new(val,'user_id', @attributes['id'], classes('Micropost'))
123
134
  end
124
135
 
125
136
  def relationships
126
- associations['relationships'] ||= ActiveMocker::Collection::Association.new
137
+ @associations[:relationships] ||= ActiveMock::HasMany.new([],'follower_id', @attributes['id'], classes('Relationship'))
127
138
  end
128
139
 
129
140
  def relationships=(val)
130
- associations['relationships'] = ActiveMocker::Collection::Association.new(val)
141
+ @associations[:relationships] ||= ActiveMock::HasMany.new(val,'follower_id', @attributes['id'], classes('Relationship'))
131
142
  end
132
143
 
133
144
  def followed_users
134
- associations['followed_users'] ||= ActiveMocker::Collection::Association.new
145
+ @associations[:followed_users] ||= ActiveMock::HasMany.new([],'user_id', @attributes['id'], classes('FollowedUser'))
135
146
  end
136
147
 
137
148
  def followed_users=(val)
138
- associations['followed_users'] = ActiveMocker::Collection::Association.new(val)
149
+ @associations[:followed_users] ||= ActiveMock::HasMany.new(val,'user_id', @attributes['id'], classes('FollowedUser'))
139
150
  end
140
151
 
141
152
  def reverse_relationships
142
- associations['reverse_relationships'] ||= ActiveMocker::Collection::Association.new
153
+ @associations[:reverse_relationships] ||= ActiveMock::HasMany.new([],'followed_id', @attributes['id'], classes('Relationship'))
143
154
  end
144
155
 
145
156
  def reverse_relationships=(val)
146
- associations['reverse_relationships'] = ActiveMocker::Collection::Association.new(val)
157
+ @associations[:reverse_relationships] ||= ActiveMock::HasMany.new(val,'followed_id', @attributes['id'], classes('Relationship'))
147
158
  end
148
159
 
149
160
  def followers
150
- associations['followers'] ||= ActiveMocker::Collection::Association.new
161
+ @associations[:followers] ||= ActiveMock::HasMany.new([],'user_id', @attributes['id'], classes('Follower'))
151
162
  end
152
163
 
153
164
  def followers=(val)
154
- associations['followers'] = ActiveMocker::Collection::Association.new(val)
165
+ @associations[:followers] ||= ActiveMock::HasMany.new(val,'user_id', @attributes['id'], classes('Follower'))
155
166
  end
156
167
 
157
168
  ##################################
158
169
  # Model Methods getter/setters #
159
170
  ##################################
160
171
 
161
- def self.model_instance_methods
162
- @model_instance_methods ||= {"feed"=>:not_implemented, "following?"=>:not_implemented, "follow!"=>:not_implemented, "unfollow!"=>:not_implemented}
163
- end
164
-
165
- def self.model_class_methods
166
- @model_class_methods ||= {"new_remember_token"=>:not_implemented, "digest"=>:not_implemented}
167
- end
168
-
169
- def self.clear_mock
170
- @model_class_methods, @model_instance_methods = nil, nil
171
- delete_all
172
- end
173
172
 
174
173
  def feed()
175
174
  block = model_instance_methods['feed']
@@ -207,10 +206,10 @@ class UserMock < ::ActiveHash::Base
207
206
  instance_exec(*[token], &block)
208
207
  end
209
208
 
209
+ private
210
+
210
211
  def self.reload
211
212
  load __FILE__
212
213
  end
213
214
 
214
- end
215
-
216
- ActiveMocker::LoadedMocks.add(UserMock)
215
+ end
@@ -11,7 +11,7 @@ RSpec.configure do |config|
11
11
  end
12
12
 
13
13
  $:.unshift File.expand_path('../../', __FILE__)
14
- APP_ROOT = File.expand_path('../../', __FILE__)
14
+ APP_ROOT = File.expand_path('../../', __FILE__) unless defined? APP_ROOT
15
15
  require 'config/initializers/active_mocker.rb'
16
16
  load 'mocks/user_mock.rb'
17
17
 
@@ -1,9 +1,10 @@
1
1
  require 'rspec'
2
2
  $:.unshift File.expand_path('../../', __FILE__)
3
- load 'spec/mocks/user_mock.rb'
4
- APP_ROOT = File.expand_path('../../', __FILE__)
3
+ require 'active_support'
4
+ require 'spec/mocks/user_mock.rb'
5
+ APP_ROOT = File.expand_path('../../', __FILE__) unless defined? APP_ROOT
5
6
  require 'config/initializers/active_mocker.rb'
6
-
7
+ require 'forwardable'
7
8
 
8
9
  describe 'UserMock' do
9
10
 
@@ -12,6 +13,23 @@ describe 'UserMock' do
12
13
  UserMock.clear_mock
13
14
  }
14
15
 
16
+ describe '::mocked_class' do
17
+
18
+ it 'returns the name of the class being mocked' do
19
+ expect(UserMock.mocked_class).to eq 'User'
20
+ end
21
+
22
+ end
23
+
24
+ describe 'ActiveMocker::LoadedMocks' do
25
+
26
+ it 'will be added when sub classed' do
27
+ expect(ActiveMocker::LoadedMocks.all.keys.include?('UserMock')).to eq true
28
+ end
29
+
30
+ end
31
+
32
+
15
33
  describe '::column_names' do
16
34
 
17
35
  it 'returns an array of column names found from the schema.rb file' do
@@ -29,7 +47,7 @@ describe 'UserMock' do
29
47
  end
30
48
 
31
49
  it 'will raise error if not an attribute or association' do
32
- expect{UserMock.new(baz: "Hello")}.to raise_error(ActiveMocker::RejectedParams, '{:baz=>"Hello"} for UserMock')
50
+ expect{UserMock.new(baz: "Hello")}.to raise_error(ActiveMock::RejectedParams, '{:baz=>"Hello"} for UserMock')
33
51
  end
34
52
 
35
53
  end
@@ -106,10 +124,10 @@ describe 'UserMock' do
106
124
 
107
125
  end
108
126
 
109
- context 'active_hash' do
127
+ context 'active_mock' do
110
128
 
111
- it 'uses active_hash::base as superclass' do
112
- expect(UserMock.superclass.name).to eq 'ActiveHash::Base'
129
+ it 'uses active_mock::base as superclass' do
130
+ expect(UserMock.superclass.name).to eq 'ActiveMock::Base'
113
131
  end
114
132
 
115
133
  it 'can save to class and then find instance by attribute' do
@@ -0,0 +1,207 @@
1
+ require 'rspec'
2
+ $:.unshift File.expand_path('../../', __FILE__)
3
+ require 'active_support/all'
4
+ require 'active_mock/queries'
5
+ require 'active_mock/collection'
6
+ require 'ostruct'
7
+
8
+ describe ActiveMock::Queries do
9
+
10
+ before do
11
+
12
+ class Queriable < ActiveMock::Collection
13
+ include ActiveMock::Queries
14
+ end
15
+
16
+ end
17
+
18
+ subject{ Queriable.new }
19
+
20
+ describe '#sum' do
21
+
22
+ it 'sum values by attribute name' do
23
+ subject << [OpenStruct.new(value: 1), OpenStruct.new(value: 1)]
24
+ expect(subject.sum(:value)).to eq 2
25
+ end
26
+
27
+ end
28
+
29
+ describe '#limit' do
30
+
31
+ let!(:given_collection){ [OpenStruct.new(value: 1),
32
+ OpenStruct.new(value: 2),
33
+ OpenStruct.new(value: 3)]}
34
+
35
+ it 'will return only the n-number of items' do
36
+ subject << given_collection
37
+ expect(subject.limit(1).count).to eq 1
38
+ end
39
+
40
+ end
41
+
42
+ describe '#<<' do
43
+
44
+ it 'will add a single item to the array' do
45
+
46
+ subject << "item"
47
+ expect(subject.count).to eq 1
48
+ expect(subject.first).to eq 'item'
49
+
50
+ end
51
+
52
+ it 'will add a many item to the array' do
53
+
54
+ subject << ['item1', 'item2', 'item3']
55
+ expect(subject.count).to eq 3
56
+ expect(subject).to eq ['item1', 'item2', 'item3']
57
+
58
+ end
59
+
60
+ end
61
+
62
+ describe 'new' do
63
+
64
+ it 'take optional item and adds to collection' do
65
+
66
+ subject = Queriable.new(1)
67
+
68
+ expect(subject.first).to eq 1
69
+
70
+ end
71
+
72
+ it 'can take an array' do
73
+
74
+ subject = Queriable.new([1])
75
+
76
+ expect(subject.first).to eq 1
77
+
78
+ subject = Queriable.new([1,2])
79
+
80
+ expect(subject.last).to eq 2
81
+
82
+ end
83
+
84
+ end
85
+
86
+ describe 'empty?' do
87
+
88
+ it 'returns true if collection is empty' do
89
+ expect(subject.empty?).to eq true
90
+ end
91
+
92
+ it 'returns false if collection is not empty' do
93
+ subject << 1
94
+ expect(subject.empty?).to eq false
95
+ end
96
+
97
+ end
98
+
99
+ describe 'each' do
100
+
101
+ it 'can iterate over array' do
102
+ sum = 0
103
+ Queriable.new([1, 2]).each { |a| sum += a }
104
+ expect(sum).to eq 3
105
+ end
106
+
107
+ end
108
+
109
+ describe 'map' do
110
+
111
+ it 'return a new array' do
112
+ expect(Queriable.new([1, 2]).map { |a| a + a }).to eq [2, 4]
113
+ end
114
+
115
+ it 'return an instance of the class' do
116
+ expect(Queriable.new([1, 2]).map { |a| a + a }).to be_a_kind_of Array
117
+ end
118
+
119
+ end
120
+
121
+ describe 'delete_all' do
122
+
123
+ let!(:given_collection) { [double(delete: true),
124
+ double(delete: true),
125
+ double(delete: true)] }
126
+
127
+ before do
128
+ given_collection.each do |item|
129
+ expect(item).to receive(:delete)
130
+ end
131
+ subject << given_collection
132
+ end
133
+
134
+ it 'calls delete on every item in the collection' do
135
+ subject.delete_all
136
+ end
137
+
138
+ context 'alias destroy_all' do
139
+
140
+ it 'calls delete on every item in the collection' do
141
+ subject.destroy_all
142
+ end
143
+
144
+ end
145
+
146
+ end
147
+
148
+ describe '#all' do
149
+ subject{ Queriable.new(given_collection)}
150
+
151
+ let(:given_collection) { [1,1,1] }
152
+
153
+ it 'return the collection' do
154
+ expect(subject.all).to eq given_collection
155
+ end
156
+
157
+ it 'returns an instance of the class' do
158
+ expect(subject.all).to be_a_kind_of Queriable
159
+ end
160
+
161
+ end
162
+
163
+ describe 'where' do
164
+
165
+ context 'with condition' do
166
+
167
+ subject{ Queriable.new(given_collection)}
168
+
169
+ let(:given_collection) { [OpenStruct.new(value: 1),
170
+ OpenStruct.new(value: 2),
171
+ OpenStruct.new(value: 3)] }
172
+
173
+ it 'returns array of values that meet the condition' do
174
+ expect(subject.where(value: 1)).to eq [given_collection.first]
175
+ end
176
+
177
+ it 'returns an instance of the class' do
178
+ expect(subject.where(value: 1)).to be_a_kind_of(Queriable)
179
+ end
180
+
181
+ end
182
+
183
+ context 'without condition' do
184
+
185
+ subject { Queriable.new(given_collection) }
186
+
187
+ it 'return a WhereNotChain' do
188
+ expect(subject.where).to be_a_kind_of(ActiveMock::Queries::WhereNotChain)
189
+ end
190
+
191
+ let(:given_collection) { [OpenStruct.new(value: 1),
192
+ OpenStruct.new(value: 2),
193
+ OpenStruct.new(value: 3)] }
194
+
195
+ it 'takes .not(condition)' do
196
+ expect(subject.where.not(value: 1)).to eq [given_collection[1], given_collection[2]]
197
+ end
198
+
199
+ it '.not(condition) return the class' do
200
+ expect(subject.where.not(value: 1)).to be_a_kind_of(Queriable)
201
+ end
202
+
203
+ end
204
+
205
+ end
206
+
207
+ end