guacamole 0.2.0 → 0.3.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.
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