guacamole 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +3 -0
  3. data/{config/reek.yml → .reek.yml} +5 -0
  4. data/.travis.yml +3 -0
  5. data/CHANGELOG.md +19 -0
  6. data/GOALS.md +20 -0
  7. data/Gemfile +1 -11
  8. data/Guardfile +0 -4
  9. data/README.md +147 -11
  10. data/Rakefile +33 -3
  11. data/guacamole.gemspec +12 -1
  12. data/lib/guacamole.rb +1 -0
  13. data/lib/guacamole/callbacks.rb +259 -0
  14. data/lib/guacamole/collection.rb +50 -32
  15. data/lib/guacamole/configuration.rb +92 -15
  16. data/lib/guacamole/model.rb +39 -1
  17. data/lib/guacamole/railtie.rb +9 -3
  18. data/lib/guacamole/version.rb +1 -1
  19. data/lib/rails/generators/guacamole/callbacks/callbacks_generator.rb +26 -0
  20. data/lib/rails/generators/guacamole/callbacks/templates/callbacks.rb.tt +13 -0
  21. data/lib/rails/generators/rspec/callbacks/callbacks_generator.rb +14 -0
  22. data/lib/rails/generators/rspec/callbacks/templates/callbacks_spec.rb.tt +7 -0
  23. data/lib/rails/generators/test_unit/callbacks/callbacks_generator.rb +13 -0
  24. data/lib/rails/generators/test_unit/callbacks/templates/callbacks_test.rb.tt +9 -0
  25. data/lib/rails/generators/test_unit/collection/collection_generator.rb +13 -0
  26. data/lib/rails/generators/test_unit/collection/templates/collection_test.rb.tt +10 -0
  27. data/spec/acceptance/aql_spec.rb +0 -12
  28. data/spec/acceptance/basic_spec.rb +16 -25
  29. data/spec/acceptance/callbacks_spec.rb +181 -0
  30. data/spec/acceptance/config/guacamole.yml +1 -1
  31. data/spec/acceptance/spec_helper.rb +24 -6
  32. data/spec/fabricators/article.rb +12 -0
  33. data/spec/fabricators/comment.rb +7 -0
  34. data/spec/fabricators/pony.rb +6 -4
  35. data/spec/fabricators/pony_fabricator.rb +7 -0
  36. data/spec/spec_helper.rb +5 -4
  37. data/spec/support/guacamole.yml.erb +5 -0
  38. data/spec/unit/callbacks_spec.rb +139 -0
  39. data/spec/unit/collection_spec.rb +85 -66
  40. data/spec/unit/configuration_spec.rb +165 -21
  41. data/spec/unit/identiy_map_spec.rb +2 -2
  42. data/spec/unit/model_spec.rb +36 -3
  43. metadata +181 -12
  44. data/Gemfile.devtools +0 -67
  45. data/config/devtools.yml +0 -4
  46. data/config/flay.yml +0 -3
  47. data/config/flog.yml +0 -2
  48. data/config/mutant.yml +0 -3
  49. data/config/yardstick.yml +0 -2
  50. data/tasks/adjustments.rake +0 -34
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ <% module_namespacing do -%>
4
+ describe <%= class_name %>Callbacks do
5
+ pending "add some examples to (or delete) #{__FILE__}"
6
+ end
7
+ <% end -%>
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'rails/generators/guacamole_generator'
4
+
5
+ module TestUnit
6
+ module Generators
7
+ class CallbacksGenerator < ::Guacamole::Generators::Base
8
+ def create_test_file
9
+ template 'callbacks_test.rb.tt', File.join('test/callbacks', class_path, "#{file_name}_callbacks_test.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+
3
+ <% module_namespacing do -%>
4
+ class <%= class_name %>CallbacksTest < ActiveSupport::TestCase
5
+ # test "the truth" do
6
+ # assert true
7
+ # end
8
+ end
9
+ <% end -%>
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'rails/generators/guacamole_generator'
4
+
5
+ module TestUnit
6
+ module Generators
7
+ class CollectionGenerator < ::Guacamole::Generators::Base
8
+ def create_test_file
9
+ template 'collection_test.rb.tt', File.join('test/collections', class_path, "#{file_name}_collection_test.rb")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ require 'test_helper'
2
+
3
+ <% module_namespacing do -%>
4
+ class <%= class_name %>CollectionTest < ActiveSupport::TestCase
5
+ # test "the truth" do
6
+ # assert true
7
+ # end
8
+ end
9
+ <% end -%>
10
+
@@ -3,18 +3,6 @@
3
3
  require 'guacamole'
4
4
  require 'acceptance/spec_helper'
5
5
 
6
- class Pony
7
- include Guacamole::Model
8
-
9
- attribute :name, String
10
- attribute :color, String
11
- attribute :type, Array[String]
12
- end
13
-
14
- class PoniesCollection
15
- include Guacamole::Collection
16
- end
17
-
18
6
  describe 'BasicAQLSupport' do
19
7
  subject { PoniesCollection }
20
8
 
@@ -2,29 +2,6 @@
2
2
  require 'guacamole'
3
3
  require 'acceptance/spec_helper'
4
4
 
5
- class Comment
6
- include Guacamole::Model
7
-
8
- attribute :text, String
9
- end
10
-
11
- class Article
12
- include Guacamole::Model
13
-
14
- attribute :title, String
15
- attribute :comments, Array[Comment]
16
-
17
- validates :title, presence: true
18
- end
19
-
20
- class ArticlesCollection
21
- include Guacamole::Collection
22
-
23
- map do
24
- embeds :comments
25
- end
26
- end
27
-
28
5
  describe 'ModelBasics' do
29
6
 
30
7
  describe Article do
@@ -45,9 +22,9 @@ describe 'ModelBasics' do
45
22
  end
46
23
 
47
24
  it 'should validate its attributes' do
48
- expect(subject.valid?).to be_false
25
+ expect(subject.valid?).to be false
49
26
  subject.title = 'The Legend of Zelda'
50
- expect(subject.valid?).to be_true
27
+ expect(subject.valid?).to be true
51
28
  end
52
29
 
53
30
  it 'should know its model name' do
@@ -100,6 +77,20 @@ describe 'CollectionBasics' do
100
77
  expect(result.title).to eq 'Disturbed'
101
78
  end
102
79
 
80
+ context 'delete documents' do
81
+ it 'should delete a document by key' do
82
+ deleted_key = subject.delete(some_article.key)
83
+
84
+ expect { subject.by_key(deleted_key) }.to raise_error(Ashikawa::Core::DocumentNotFoundException)
85
+ end
86
+
87
+ it 'should delete a document by model' do
88
+ deleted_key = subject.delete(some_article)
89
+
90
+ expect { subject.by_key(deleted_key) }.to raise_error(Ashikawa::Core::DocumentNotFoundException)
91
+ end
92
+ end
93
+
103
94
  it 'should allow to nest models' do
104
95
  article_with_comments = Fabricate(:article_with_two_comments)
105
96
  found_article = subject.by_key(article_with_comments.key)
@@ -0,0 +1,181 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'guacamole'
4
+ require 'acceptance/spec_helper'
5
+
6
+ require 'bcrypt'
7
+
8
+ class SecurePonyCallbacks
9
+ include Guacamole::Callbacks
10
+
11
+ # Those will be triggered by the collection
12
+ before_create :encrypt_password
13
+ after_create :throw_welcome_party
14
+ around_create :log_create_time
15
+
16
+ # Those will be triggered by the model
17
+ before_validate :generate_token
18
+ after_validate :remove_safety_switch
19
+ around_validate :log_validate_time
20
+
21
+ def encrypt_password
22
+ object.encrypted_password = BCrypt::Password.create(object.password)
23
+ end
24
+
25
+ def throw_welcome_party
26
+ Party.throw!
27
+ end
28
+
29
+ def log_create_time
30
+ TimingLogger.log_time 'before_create'
31
+ yield
32
+ TimingLogger.log_time 'after_create'
33
+ end
34
+
35
+ def generate_token
36
+ object.token = SecureRandom.hex
37
+ end
38
+
39
+ def remove_safety_switch
40
+ object.safety_switch = :removed
41
+ end
42
+
43
+ def log_validate_time
44
+ TimingLogger.log_time 'before_validate'
45
+ yield
46
+ TimingLogger.log_time 'after_validate'
47
+ end
48
+ end
49
+
50
+ class SecurePony
51
+ include Guacamole::Model
52
+
53
+ callbacks :secure_pony_callbacks
54
+
55
+ attribute :name, String
56
+ attribute :token, String
57
+ attribute :encrypted_password, String
58
+
59
+ # define a virtual attribute
60
+ attr_accessor :password, :safety_switch
61
+ end
62
+
63
+ class SecurePoniesCollection
64
+ include Guacamole::Collection
65
+ end
66
+
67
+ class Party
68
+ def self.throw!; end
69
+ end
70
+
71
+ class TimingLogger
72
+ def self.log_time(*args); end
73
+ end
74
+
75
+ describe 'CallbacksSpec' do
76
+ subject { SecurePonyCallbacks }
77
+
78
+ let(:pinkie_pie) { SecurePony.new name: 'Pinkie Pie', password: 'cupcakes' }
79
+
80
+ before do
81
+ allow(TimingLogger).to receive(:log_time)
82
+ end
83
+
84
+ describe 'collection based callbacks' do
85
+ let(:collection) { SecurePoniesCollection }
86
+
87
+ it 'should fire the before create callback' do
88
+ collection.save pinkie_pie
89
+
90
+ expect(BCrypt::Password.new(pinkie_pie.encrypted_password)).to eq pinkie_pie.password
91
+ end
92
+
93
+ it 'should fire the after create callback' do
94
+ expect(Party).to receive(:throw!)
95
+
96
+ collection.save pinkie_pie
97
+ end
98
+
99
+ it 'should fire the around create callback' do
100
+ expect(TimingLogger).to receive(:log_time).with('before_create').ordered
101
+ expect(TimingLogger).to receive(:log_time).with('after_create').ordered
102
+
103
+ collection.save pinkie_pie
104
+ end
105
+
106
+ context 'fill time stamp attributes' do
107
+ let(:past) { 'Oct 26 1955 01:21'.to_datetime }
108
+ let(:now) { 'Oct 26 1985 01:21'.to_datetime }
109
+
110
+ it 'should fill created_at and updated_at on create' do
111
+ Timecop.freeze(now) do
112
+ collection.save pinkie_pie
113
+ end
114
+
115
+ expect(pinkie_pie.created_at).to eq now
116
+ expect(pinkie_pie.updated_at).to eq now
117
+ end
118
+
119
+ it 'should update updated_at on update' do
120
+ collection.save pinkie_pie
121
+ pinkie_pie.name = 'Pinkie Pie - Updated'
122
+
123
+ Timecop.freeze(now) do
124
+ collection.save pinkie_pie
125
+ end
126
+
127
+ expect(pinkie_pie.updated_at).to eq now
128
+ end
129
+
130
+ context 'with the default callback' do
131
+ let(:pinkie_pie) { Fabricate.build(:pony, name: 'Pinkie Pie') }
132
+ let(:collection) { PoniesCollection }
133
+
134
+ it 'should fill created_at and updated_at on create' do
135
+ Timecop.freeze(now) do
136
+ collection.save pinkie_pie
137
+ end
138
+
139
+ expect(pinkie_pie.created_at).to eq now
140
+ expect(pinkie_pie.updated_at).to eq now
141
+ end
142
+
143
+ it 'should update updated_at on update' do
144
+ Timecop.freeze(past) do
145
+ collection.save pinkie_pie
146
+ end
147
+
148
+ pinkie_pie.color = 'pink'
149
+
150
+ Timecop.freeze(now) do
151
+ collection.save pinkie_pie
152
+ end
153
+
154
+ expect(pinkie_pie.created_at).to eq past
155
+ expect(pinkie_pie.updated_at).to eq now
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ describe 'model based callbacks' do
162
+ it 'should fire the before validate callback' do
163
+ pinkie_pie.valid?
164
+
165
+ expect(pinkie_pie.token).not_to be_nil
166
+ end
167
+
168
+ it 'should fire the after validate callback' do
169
+ pinkie_pie.valid?
170
+
171
+ expect(pinkie_pie.safety_switch).to be_truthy
172
+ end
173
+
174
+ it 'should fire the around validate callback' do
175
+ expect(TimingLogger).to receive(:log_time).with('before_validate')
176
+ expect(TimingLogger).to receive(:log_time).with('after_validate')
177
+
178
+ pinkie_pie.valid?
179
+ end
180
+ end
181
+ end
@@ -8,4 +8,4 @@ test:
8
8
  port: 8529
9
9
  password: ''
10
10
  username: ''
11
- database: '_system'
11
+ database: 'guacamole_acceptance_test'
@@ -8,12 +8,8 @@ require 'fabrication'
8
8
  require 'faker'
9
9
  require 'logging'
10
10
  require 'ashikawa-core'
11
-
12
- begin
13
- require 'debugger'
14
- rescue LoadError
15
- puts "Debugger is not available. Maybe you're Travis."
16
- end
11
+ require 'pry'
12
+ require 'timecop'
17
13
 
18
14
  # This is required to remove the deprecation warning introduced in this commit:
19
15
  # https://github.com/svenfuchs/i18n/commit/3b6e56e06fd70f6e4507996b017238505e66608c.
@@ -50,6 +46,12 @@ Guacamole.configure do |config|
50
46
  config.load File.join(File.dirname(__FILE__), 'config', 'guacamole.yml')
51
47
  end
52
48
 
49
+ begin
50
+ Guacamole.configuration.database.create
51
+ rescue Ashikawa::Core::ClientError
52
+ # Database already exists, don't worry
53
+ end
54
+
53
55
  RSpec.configure do |config|
54
56
  config.expect_with :rspec do |c|
55
57
  c.syntax = :expect
@@ -63,3 +65,19 @@ RSpec.configure do |config|
63
65
  Guacamole.configuration.database.truncate
64
66
  end
65
67
  end
68
+
69
+ # Collections for fabricator models
70
+
71
+ require 'fabricators/article'
72
+
73
+ class ArticlesCollection
74
+ include Guacamole::Collection
75
+
76
+ map do
77
+ embeds :comments
78
+ end
79
+ end
80
+
81
+ class PoniesCollection
82
+ include Guacamole::Collection
83
+ end
@@ -0,0 +1,12 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'fabricators/comment'
4
+
5
+ class Article
6
+ include Guacamole::Model
7
+
8
+ attribute :title, String
9
+ attribute :comments, Array[Comment]
10
+
11
+ validates :title, presence: true
12
+ end
@@ -0,0 +1,7 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ class Comment
4
+ include Guacamole::Model
5
+
6
+ attribute :text, String
7
+ end
@@ -1,7 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- Fabricator(:pony) do
4
- name { Faker::Name.name }
5
- color { %w(purple pink blue yellow green white).sample }
6
- type { %w(Pegasus Earthpony Unicorn).sample }
3
+ class Pony
4
+ include Guacamole::Model
5
+
6
+ attribute :name, String
7
+ attribute :color, String
8
+ attribute :type, Array[String]
7
9
  end
@@ -0,0 +1,7 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Fabricator(:pony) do
4
+ name { Faker::Name.name }
5
+ color { %w(purple pink blue yellow green white).sample }
6
+ type { %w(Pegasus Earthpony Unicorn).sample }
7
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,12 +2,13 @@
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
 
5
- begin
6
- require 'debugger'
7
- rescue LoadError
8
- puts "Debugger is not available. Maybe you're Travis."
5
+ if ENV['CODECLIMATE_REPO_TOKEN']
6
+ require 'codeclimate-test-reporter'
7
+ CodeClimate::TestReporter.start
9
8
  end
10
9
 
10
+ require 'rspec/its'
11
+
11
12
  RSpec.configure do |config|
12
13
  config.expect_with :rspec do |c|
13
14
  c.syntax = :expect