active_mocker 1.3.2 → 1.4.1

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.
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
@@ -0,0 +1,175 @@
1
+ module ActiveMocker
2
+
3
+ class ModelSchema
4
+
5
+ class Generate
6
+
7
+ attr_reader :schema_file, :models_dir
8
+
9
+ def initialize(schema_file:nil, models_dir:nil, logger:nil)
10
+ @schema_file = schema_file
11
+ @models_dir = models_dir
12
+ Logger.set(logger)
13
+ end
14
+
15
+ def tables
16
+ @tables ||= SchemaReader.new({schema_file: schema_file}).search(nil)
17
+ end
18
+
19
+ def get_table(model , model_name)
20
+ table_name = get_table_name(model.table_name, model_name)
21
+ selected_table = tables.select{|table| table.name == table_name}.first
22
+ if selected_table.nil?
23
+ Logger.error "The Implicit or defined table, `#{table_name}`, can not be found for model #{model_name.camelize}."
24
+ end
25
+ tables.delete(selected_table)
26
+ selected_table
27
+ end
28
+
29
+ # noinspection RubyArgCount
30
+ def run
31
+ model_schemas = models.map do |model_name|
32
+
33
+ model = get_model(model_name)
34
+ next if model == false
35
+ table = get_table(model, model_name)
36
+ attributes = build_attributes(table.fields, primary_key(table.fields, model))
37
+
38
+ ModelSchema.new(class_name: model_name.camelize,
39
+ table_name: table.name,
40
+ attributes: attributes,
41
+ methods: build_methods(model),
42
+ relationships: build_relationships(model),
43
+ constants: model.constants)
44
+ end
45
+
46
+ ModelSchemaCollection.new(model_schemas.compact)
47
+ end
48
+
49
+
50
+
51
+ # noinspection RubyArgCount
52
+ def build_attributes(attributes, primary_attribute)
53
+ attributes.map do |attr|
54
+ attribute = ModelSchema::Attributes
55
+ .new(name: attr.name,
56
+ type: attr.type,
57
+ precision: attr.precision,
58
+ scale: attr.scale,
59
+ default_value: attr.default)
60
+ if primary_attribute == attr
61
+ attribute.primary_key = true
62
+ end
63
+ attribute
64
+ end
65
+ end
66
+
67
+ # noinspection RubyArgCount
68
+ def build_methods(model)
69
+ result = []
70
+ {instance: model.instance_methods_with_arguments,
71
+ class: model.class_methods_with_arguments}.each do |type,methods|
72
+ methods.map do |method|
73
+ method_name = method.keys.first.to_s
74
+ arguments = method.values.first
75
+
76
+ result.push(ModelSchema::Methods.new(name: method_name,arguments: arguments,type:type))
77
+ end
78
+ end
79
+ result
80
+ end
81
+
82
+ def build_relationships(model)
83
+ relations_by_type(model).map do |type, relations|
84
+ relations.map do |relation|
85
+ join_table = nil
86
+ join_table = find_join_table(relation, model) if type == :has_and_belongs_to_many
87
+ Relationships.new(name: relation.name,
88
+ class_name: relation.class_name,
89
+ type: type,
90
+ through: relation.through,
91
+ foreign_key: relation.foreign_key,
92
+ join_table: join_table)
93
+ end
94
+ end.flatten
95
+ end
96
+
97
+ def relations_by_type(model)
98
+ {belongs_to: model.belongs_to,
99
+ has_one: model.has_one,
100
+ has_many: model.has_many,
101
+ has_and_belongs_to_many: model.has_and_belongs_to_many
102
+
103
+ }
104
+ end
105
+
106
+ def find_join_table(relation, model)
107
+ return relation.join_table if relation.respond_to?(:join_table) && relation.join_table
108
+ tables.select do |table|
109
+
110
+ "#{model.table_name}_#{relation.name}" == table.name.to_s || "#{relation.name}_#{model.table_name}" == table.name.to_s
111
+ end.first
112
+ end
113
+
114
+ def primary_key(attributes, model)
115
+ result = model_primary_key_attribute(attributes, model)
116
+ return result unless result.nil?
117
+
118
+ result = find_primary_key(attributes)
119
+ return result unless result.nil?
120
+
121
+ find_id_attribute(attributes)
122
+ end
123
+
124
+ private
125
+
126
+ def model_primary_key_attribute(attributes, model)
127
+ if model.respond_to?(:primary_key) && model.primary_key
128
+ attributes.select do |attr|
129
+ model.primary_key.to_s == attr.name.to_s
130
+ end.first
131
+ end
132
+ end
133
+
134
+ def find_primary_key(attributes)
135
+ attributes.select do |attr|
136
+ attr.try(:primary_key)
137
+ end.first
138
+ end
139
+
140
+ def find_id_attribute(attributes)
141
+ attributes.select do |attr|
142
+ attr.name.to_sym == :id
143
+ end.first
144
+ end
145
+
146
+ public
147
+
148
+ def models
149
+ Dir["#{models_dir}/*.rb"].map do |file|
150
+ Pathname.new(file).basename.to_s.sub('.rb', '')
151
+ end
152
+ end
153
+
154
+ def get_model(model_file_name)
155
+ ModelReader.new({model_dir: models_dir}).parse(model_file_name)
156
+ end
157
+
158
+ def get_table_name(model_table_name, model_name)
159
+ return model_name.tableize if model_table_name.nil?
160
+ return model_table_name
161
+ end
162
+
163
+ def table_to_model_file(table_name)
164
+ table_name.singularize
165
+ end
166
+
167
+ def table_to_class_name(table)
168
+ table.camelize.singularize
169
+ end
170
+
171
+ end
172
+
173
+ end
174
+
175
+ end
@@ -1,8 +1,12 @@
1
+ module ActiveMocker
1
2
  class Reparameterize
2
3
 
3
- def self.call(params, list=false)
4
- return params.map{|state, param| param }.join(", ") if list
4
+ def self.call(params, param_list:false)
5
+ return param_list(params) if param_list
6
+ method_arguments(params)
7
+ end
5
8
 
9
+ def self.method_arguments(params)
6
10
  params.map do |state, param|
7
11
  case state
8
12
  when :req
@@ -11,11 +15,27 @@ class Reparameterize
11
15
  "*#{param}"
12
16
  when :opt
13
17
  "#{param}=nil"
18
+ when :keyreq
19
+ "#{param}:"
20
+ when :key
21
+ "#{param}: nil"
14
22
  else
15
23
  param
16
24
  end
17
- end.join(", ")
25
+ end.join(', ')
26
+
27
+ end
18
28
 
29
+ def self.param_list(params)
30
+ params.map do |state, param|
31
+ case state
32
+ when :key, :keyreq
33
+ "#{param}: #{param}"
34
+ else
35
+ param
36
+ end
37
+ end.join(', ')
19
38
  end
20
39
 
40
+ end
21
41
  end
@@ -4,10 +4,10 @@ module ActiveMocker
4
4
 
5
5
  attr_reader :name, :fields
6
6
 
7
- def initialize(name, fields=[])
7
+ def initialize(name, id=true, fields=[])
8
8
  @name = name
9
9
  @fields = fields
10
- fields.unshift Field.new('id', :integer, {})
10
+ fields.unshift Field.new('id', :integer, [{primary_key: true}]) if id.nil?
11
11
  end
12
12
 
13
13
  def to_h
@@ -1,3 +1,3 @@
1
1
  module ActiveMocker
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.1"
3
3
  end
@@ -4,7 +4,7 @@ gem 'rails', '4.1'
4
4
 
5
5
  group :development, :test do
6
6
  gem 'sqlite3', '~>1.3'
7
- gem 'rspec-rails', '~>2'
7
+ gem 'rspec-rails', '2.14.1'
8
8
  end
9
9
 
10
10
  group :test do
@@ -1,12 +1,24 @@
1
1
  class Micropost < ActiveRecord::Base
2
2
  belongs_to :user
3
3
  default_scope -> { order('created_at DESC') }
4
+ MAGIC_ID_NUMBER = 90
5
+ MAGIC_ID_STRING = 'F-1'
4
6
 
7
+ module DoNotIncludeInMock
8
+
9
+ end
10
+ include DoNotIncludeInMock
11
+ # self.primary_key = :lol
12
+ # self.table_name = :posts
5
13
  # Returns microposts from the users being followed by the given user.
6
- def self.from_users_followed_by(user)
14
+ def self.from_users_followed_by(user=nil)
7
15
  followed_user_ids = "SELECT followed_id FROM relationships
8
16
  WHERE follower_id = :user_id"
9
17
  where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
10
18
  user_id: user.id)
11
19
  end
20
+
21
+ def display_name
22
+
23
+ end
12
24
  end
@@ -37,7 +37,7 @@ ActiveRecord::Schema.define(version: 20130315230445) do
37
37
  create_table "users", force: true do |t|
38
38
  t.string "name"
39
39
  t.string "email", default: ""
40
- t.decimal "credits"
40
+ t.decimal "credits", precision: 19, scale: 6
41
41
  t.datetime "created_at"
42
42
  t.datetime "updated_at"
43
43
  t.string "password_digest"
@@ -26,7 +26,7 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
26
26
  describe '::superclass' do
27
27
 
28
28
  it 'mock has super of active hash' do
29
- expect(UserMock.superclass.name).to eq "ActiveHash::Base"
29
+ expect(UserMock.superclass.name).to eq "ActiveMock::Base"
30
30
  end
31
31
 
32
32
  it 'ar has super of ar' do
@@ -95,7 +95,9 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
95
95
  describe '#attributes' do
96
96
 
97
97
  let(:user_ar){User.new(attributes)}
98
- let(:user_mock){UserMock.new(attributes)}
98
+ let(:user_mock){
99
+ UserMock.new(attributes)
100
+ }
99
101
 
100
102
  it 'mock' do
101
103
  expect(user_mock.attributes).to eq({"id" => nil, "name" => "Dustin Zeisler", "email" => "dustin@example.com", "credits" => nil, "created_at" => nil, "updated_at" => nil, "password_digest" => nil, "remember_token" => true, "admin" => false})
@@ -292,7 +294,7 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
292
294
  end
293
295
 
294
296
  it 'UserMock' do
295
- where_no_options(UserMock, ActiveMocker::Collection::Queries::WhereNotChain)
297
+ where_no_options(UserMock, ActiveMock::Queries::WhereNotChain)
296
298
  end
297
299
 
298
300
  end
@@ -400,7 +402,7 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
400
402
  end
401
403
 
402
404
  it 'UserMock' do
403
- supported_array_methods(UserMock, MicropostMock, ActiveMocker::Collection::Association)
405
+ supported_array_methods(UserMock, MicropostMock, ActiveMock::HasMany)
404
406
  end
405
407
 
406
408
  end
@@ -420,7 +422,7 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
420
422
  end
421
423
 
422
424
  it 'UserMock' do
423
- collection_find(UserMock, MicropostMock, ActiveMocker::Collection::Association)
425
+ collection_find(UserMock, MicropostMock, ActiveMock::Association)
424
426
  end
425
427
 
426
428
  end
@@ -438,7 +440,7 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
438
440
  end
439
441
 
440
442
  it 'UserMock' do
441
- collection_finds(UserMock, MicropostMock, ActiveMocker::Collection::Association)
443
+ collection_finds(UserMock, MicropostMock, ActiveMock::Association)
442
444
  end
443
445
 
444
446
  end
@@ -822,7 +824,7 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
822
824
  end
823
825
 
824
826
  it 'UserMock' do
825
- find_by_exception(UserMock, ActiveMocker::RecordNotFound)
827
+ find_by_exception(UserMock, ActiveMock::RecordNotFound)
826
828
  end
827
829
 
828
830
  end
@@ -846,6 +848,191 @@ describe 'Comparing ActiveMocker Api to ActiveRecord Api' do
846
848
 
847
849
  end
848
850
 
851
+ describe '::transaction' do
849
852
 
853
+ context 'will run code in block' do
854
+
855
+ def transaction(user_class)
856
+ user_class.transaction do
857
+ user_class.create(email: '1')
858
+ user_class.create(email: '2')
859
+ end
860
+
861
+ expect(user_class.count).to eq 2
862
+ end
863
+
864
+ it 'User' do
865
+ transaction(User)
866
+ end
867
+
868
+ it 'UserMock' do
869
+ transaction(UserMock)
870
+ end
871
+
872
+ end
873
+
874
+ end
875
+
876
+ describe 'belongs_to association' do
877
+
878
+ describe 'when setting association by object it will set id if object is persisted' do
879
+
880
+ def id_set_by_object(post_class, user_class)
881
+ user = user_class.create
882
+ post = post_class.create(user: user)
883
+ expect(post.user_id).to eq user.id
884
+ end
885
+
886
+ it 'User' do
887
+ id_set_by_object(Micropost, User)
888
+ end
889
+
890
+ it 'UserMock' do
891
+ id_set_by_object(MicropostMock, UserMock)
892
+ end
893
+
894
+ end
895
+
896
+ describe 'when setting association by object it will set the child association', pending:true do
897
+
898
+ def set_by_object(post_class, user_class)
899
+ user = user_class.create
900
+ post = post_class.create(user: user)
901
+ expect(user.microposts).to eq [post]
902
+ end
903
+
904
+ it 'User' do
905
+ set_by_object(Micropost, User)
906
+ end
907
+
908
+ it 'UserMock' do
909
+ set_by_object(MicropostMock, UserMock)
910
+ end
911
+
912
+ end
913
+
914
+ describe 'when setting association by id it will set the object on the parent' do
915
+
916
+ def object_set_by_id(post_class, user_class)
917
+ user = user_class.create
918
+ post = post_class.create(user_id: user.id)
919
+ expect(post.user).to eq user
920
+ end
921
+
922
+ it 'User' do
923
+ object_set_by_id(Micropost, User)
924
+ end
925
+
926
+ it 'UserMock' do
927
+ object_set_by_id(MicropostMock, UserMock)
928
+ end
929
+
930
+ end
931
+
932
+ describe 'when setting association by object it will not set id if object is not persisted' do
933
+
934
+ def id_set_by_object(post_class, user_class)
935
+ user = user_class.new
936
+ post = post_class.new(user: user)
937
+ expect(post.user_id).to eq nil
938
+ end
939
+
940
+ it 'User' do
941
+ id_set_by_object(Micropost, User)
942
+ end
943
+
944
+ it 'UserMock' do
945
+ id_set_by_object(MicropostMock, UserMock)
946
+ end
947
+
948
+ end
949
+
950
+ describe 'can build' do
951
+
952
+ def build_belong_to(post_class, user_class)
953
+ post = post_class.new
954
+ user = post.build_user
955
+ expect(user.class).to eq user_class
956
+ expect(post.user).to eq user
957
+ end
958
+
959
+ it 'User' do
960
+ build_belong_to(Micropost, User)
961
+ end
962
+
963
+ it 'UserMock' do
964
+ build_belong_to(MicropostMock, UserMock)
965
+ end
966
+
967
+ end
968
+
969
+ end
970
+
971
+ describe 'has_many association' do
972
+
973
+ describe 'when passing in collection all item in collection will set its foreign key to the parent', pending: true do
974
+
975
+ def id_set_to_children(user_class, post_class)
976
+ posts = [post_class.create, post_class.create, post_class.create]
977
+ user = user_class.create(microposts: posts)
978
+ expect(user.microposts.map(&:user_id)).to eq posts.map(&:user_id)
979
+ expect(posts.map(&:user_id)).to eq [user.id, user.id, user.id]
980
+ end
981
+
982
+ it 'User' do
983
+ id_set_to_children(User, Micropost)
984
+ end
985
+
986
+ it 'UserMock' do
987
+ id_set_to_children(UserMock, MicropostMock)
988
+ end
989
+
990
+ end
991
+
992
+ end
993
+
994
+ describe 'can build new object from collection' do
995
+
996
+ def new_record_on_collection(user_class, post_class)
997
+ user = user_class.create
998
+ new_post = user.microposts.build
999
+ expect(new_post.class).to eq(post_class)
1000
+ expect(new_post.attributes).to eq({"id" => nil, "content" => nil, "user_id" => 1, "up_votes" => nil, "created_at" => nil, "updated_at" => nil})
1001
+ expect(user.microposts.count).to eq 0
1002
+ new_post.save
1003
+ expect(user.microposts.count).to eq(1)
1004
+ expect(user.microposts.first).to eq(new_post)
1005
+ end
1006
+
1007
+ it 'User' do
1008
+ new_record_on_collection(User, Micropost)
1009
+ end
1010
+
1011
+ it 'UserMock' do
1012
+ new_record_on_collection(UserMock, MicropostMock)
1013
+ end
1014
+
1015
+ end
1016
+
1017
+ describe 'can create new object from collection' do
1018
+
1019
+ def create_record_on_collection(user_class, post_class)
1020
+ user = user_class.create
1021
+ new_post = user.microposts.create
1022
+ expect(new_post.class).to eq(post_class)
1023
+ expect(new_post.user_id).to eq(1)
1024
+ expect(user.microposts.count).to eq 1
1025
+ expect(user.microposts.first).to eq(new_post)
1026
+ end
1027
+
1028
+ it 'User' do
1029
+ create_record_on_collection(User, Micropost)
1030
+ end
1031
+
1032
+ it 'UserMock' do
1033
+ create_record_on_collection(UserMock, MicropostMock)
1034
+ end
1035
+
1036
+ end
850
1037
 
851
1038
  end