houdini-rails3 0.1.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 (56) hide show
  1. data/.document +11 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +20 -0
  5. data/Gemfile.lock +124 -0
  6. data/LICENSE +20 -0
  7. data/README.rdoc +3 -0
  8. data/Rakefile +54 -0
  9. data/VERSION +1 -0
  10. data/app/controllers/houdini/postbacks_controller.rb +12 -0
  11. data/config/routes.rb +8 -0
  12. data/houdini-rails3.gemspec +155 -0
  13. data/lib/houdini_rails/base.rb +31 -0
  14. data/lib/houdini_rails/engine.rb +4 -0
  15. data/lib/houdini_rails/model.rb +41 -0
  16. data/lib/houdini_rails/task.rb +17 -0
  17. data/lib/houdini_rails.rb +18 -0
  18. data/spec/controllers/houdini/postbacks_controller_spec.rb +0 -0
  19. data/spec/dummy/Rakefile +7 -0
  20. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  21. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  22. data/spec/dummy/app/models/post.rb +24 -0
  23. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/spec/dummy/app/views/posts/houdini_template.html.erb +6 -0
  25. data/spec/dummy/config/application.rb +51 -0
  26. data/spec/dummy/config/boot.rb +10 -0
  27. data/spec/dummy/config/database.yml +22 -0
  28. data/spec/dummy/config/environment.rb +5 -0
  29. data/spec/dummy/config/environments/development.rb +26 -0
  30. data/spec/dummy/config/environments/production.rb +49 -0
  31. data/spec/dummy/config/environments/test.rb +35 -0
  32. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/spec/dummy/config/initializers/inflections.rb +10 -0
  34. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  35. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  36. data/spec/dummy/config/initializers/session_store.rb +8 -0
  37. data/spec/dummy/config/locales/en.yml +5 -0
  38. data/spec/dummy/config/routes.rb +58 -0
  39. data/spec/dummy/config.ru +4 -0
  40. data/spec/dummy/db/migrate/001_create_posts.rb +16 -0
  41. data/spec/dummy/public/404.html +26 -0
  42. data/spec/dummy/public/422.html +26 -0
  43. data/spec/dummy/public/500.html +26 -0
  44. data/spec/dummy/public/favicon.ico +0 -0
  45. data/spec/dummy/public/javascripts/application.js +2 -0
  46. data/spec/dummy/public/javascripts/controls.js +965 -0
  47. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  48. data/spec/dummy/public/javascripts/effects.js +1123 -0
  49. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  50. data/spec/dummy/public/javascripts/rails.js +175 -0
  51. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  52. data/spec/dummy/script/rails +6 -0
  53. data/spec/houdini_rails_spec.rb +7 -0
  54. data/spec/requests/postbacks_spec.rb +17 -0
  55. data/spec/spec_helper.rb +32 -0
  56. metadata +361 -0
@@ -0,0 +1,175 @@
1
+ (function() {
2
+ // Technique from Juriy Zaytsev
3
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
+ function isEventSupported(eventName) {
5
+ var el = document.createElement('div');
6
+ eventName = 'on' + eventName;
7
+ var isSupported = (eventName in el);
8
+ if (!isSupported) {
9
+ el.setAttribute(eventName, 'return;');
10
+ isSupported = typeof el[eventName] == 'function';
11
+ }
12
+ el = null;
13
+ return isSupported;
14
+ }
15
+
16
+ function isForm(element) {
17
+ return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
+ }
19
+
20
+ function isInput(element) {
21
+ if (Object.isElement(element)) {
22
+ var name = element.nodeName.toUpperCase()
23
+ return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
+ }
25
+ else return false
26
+ }
27
+
28
+ var submitBubbles = isEventSupported('submit'),
29
+ changeBubbles = isEventSupported('change')
30
+
31
+ if (!submitBubbles || !changeBubbles) {
32
+ // augment the Event.Handler class to observe custom events when needed
33
+ Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
+ function(init, element, eventName, selector, callback) {
35
+ init(element, eventName, selector, callback)
36
+ // is the handler being attached to an element that doesn't support this event?
37
+ if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
+ (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
+ // "submit" => "emulated:submit"
40
+ this.eventName = 'emulated:' + this.eventName
41
+ }
42
+ }
43
+ )
44
+ }
45
+
46
+ if (!submitBubbles) {
47
+ // discover forms on the page by observing focus events which always bubble
48
+ document.on('focusin', 'form', function(focusEvent, form) {
49
+ // special handler for the real "submit" event (one-time operation)
50
+ if (!form.retrieve('emulated:submit')) {
51
+ form.on('submit', function(submitEvent) {
52
+ var emulated = form.fire('emulated:submit', submitEvent, true)
53
+ // if custom event received preventDefault, cancel the real one too
54
+ if (emulated.returnValue === false) submitEvent.preventDefault()
55
+ })
56
+ form.store('emulated:submit', true)
57
+ }
58
+ })
59
+ }
60
+
61
+ if (!changeBubbles) {
62
+ // discover form inputs on the page
63
+ document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
+ // special handler for real "change" events
65
+ if (!input.retrieve('emulated:change')) {
66
+ input.on('change', function(changeEvent) {
67
+ input.fire('emulated:change', changeEvent, true)
68
+ })
69
+ input.store('emulated:change', true)
70
+ }
71
+ })
72
+ }
73
+
74
+ function handleRemote(element) {
75
+ var method, url, params;
76
+
77
+ var event = element.fire("ajax:before");
78
+ if (event.stopped) return false;
79
+
80
+ if (element.tagName.toLowerCase() === 'form') {
81
+ method = element.readAttribute('method') || 'post';
82
+ url = element.readAttribute('action');
83
+ params = element.serialize();
84
+ } else {
85
+ method = element.readAttribute('data-method') || 'get';
86
+ url = element.readAttribute('href');
87
+ params = {};
88
+ }
89
+
90
+ new Ajax.Request(url, {
91
+ method: method,
92
+ parameters: params,
93
+ evalScripts: true,
94
+
95
+ onComplete: function(request) { element.fire("ajax:complete", request); },
96
+ onSuccess: function(request) { element.fire("ajax:success", request); },
97
+ onFailure: function(request) { element.fire("ajax:failure", request); }
98
+ });
99
+
100
+ element.fire("ajax:after");
101
+ }
102
+
103
+ function handleMethod(element) {
104
+ var method = element.readAttribute('data-method'),
105
+ url = element.readAttribute('href'),
106
+ csrf_param = $$('meta[name=csrf-param]')[0],
107
+ csrf_token = $$('meta[name=csrf-token]')[0];
108
+
109
+ var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
+ element.parentNode.insert(form);
111
+
112
+ if (method !== 'post') {
113
+ var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
+ form.insert(field);
115
+ }
116
+
117
+ if (csrf_param) {
118
+ var param = csrf_param.readAttribute('content'),
119
+ token = csrf_token.readAttribute('content'),
120
+ field = new Element('input', { type: 'hidden', name: param, value: token });
121
+ form.insert(field);
122
+ }
123
+
124
+ form.submit();
125
+ }
126
+
127
+
128
+ document.on("click", "*[data-confirm]", function(event, element) {
129
+ var message = element.readAttribute('data-confirm');
130
+ if (!confirm(message)) event.stop();
131
+ });
132
+
133
+ document.on("click", "a[data-remote]", function(event, element) {
134
+ if (event.stopped) return;
135
+ handleRemote(element);
136
+ event.stop();
137
+ });
138
+
139
+ document.on("click", "a[data-method]", function(event, element) {
140
+ if (event.stopped) return;
141
+ handleMethod(element);
142
+ event.stop();
143
+ });
144
+
145
+ document.on("submit", function(event) {
146
+ var element = event.findElement(),
147
+ message = element.readAttribute('data-confirm');
148
+ if (message && !confirm(message)) {
149
+ event.stop();
150
+ return false;
151
+ }
152
+
153
+ var inputs = element.select("input[type=submit][data-disable-with]");
154
+ inputs.each(function(input) {
155
+ input.disabled = true;
156
+ input.writeAttribute('data-original-value', input.value);
157
+ input.value = input.readAttribute('data-disable-with');
158
+ });
159
+
160
+ var element = event.findElement("form[data-remote]");
161
+ if (element) {
162
+ handleRemote(element);
163
+ event.stop();
164
+ }
165
+ });
166
+
167
+ document.on("ajax:after", "form", function(event, element) {
168
+ var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
+ inputs.each(function(input) {
170
+ input.value = input.readAttribute('data-original-value');
171
+ input.removeAttribute('data-original-value');
172
+ input.disabled = false;
173
+ });
174
+ });
175
+ })();
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Houdini do
4
+ it "should be valid" do
5
+ Houdini.should be_a(Module)
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Postbacks" do
4
+ before do
5
+ Post.delete_all
6
+ end
7
+
8
+ it "should receive postback" do
9
+ p = Post.create(:image_url => 'http://google.com', :flagged => nil)
10
+ post "houdini/post/#{p.id}/review_image/postbacks", :flagged => "yes"
11
+
12
+ p.reload
13
+
14
+ p.should be_flagged
15
+ p.houdini_request_sent_at.to_date.should == Time.now.to_date
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ # Configure Rails Envinronment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+ require "rspec/rails"
6
+
7
+ ActionMailer::Base.delivery_method = :test
8
+ ActionMailer::Base.perform_deliveries = true
9
+ ActionMailer::Base.default_url_options[:host] = "test.com"
10
+
11
+ Rails.backtrace_cleaner.remove_silencers!
12
+
13
+ # Configure capybara for integration testing
14
+ require "capybara/rails"
15
+ Capybara.default_driver = :rack_test
16
+ Capybara.default_selector = :css
17
+
18
+ # Run any available migration
19
+ ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
20
+
21
+ # Load support files
22
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
23
+
24
+ Rspec.configure do |config|
25
+ # Remove this line if you don't want Rspec's should and should_not
26
+ # methods or matchers
27
+ require 'rspec/expectations'
28
+ config.include Rspec::Matchers
29
+
30
+ # == Mock Framework
31
+ config.mock_with :rspec
32
+ end
metadata ADDED
@@ -0,0 +1,361 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: houdini-rails3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Chris Conley
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-08 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: rails
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - "="
29
+ - !ruby/object:Gem::Version
30
+ hash: 7
31
+ segments:
32
+ - 3
33
+ - 0
34
+ - 0
35
+ version: 3.0.0
36
+ requirement: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ type: :runtime
39
+ prerelease: false
40
+ name: capybara
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 1
47
+ segments:
48
+ - 0
49
+ - 3
50
+ - 9
51
+ version: 0.3.9
52
+ requirement: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ type: :runtime
55
+ prerelease: false
56
+ name: sqlite3-ruby
57
+ version_requirements: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirement: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ type: :runtime
69
+ prerelease: false
70
+ name: tilt
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ hash: 13
77
+ segments:
78
+ - 1
79
+ - 1
80
+ version: "1.1"
81
+ requirement: *id004
82
+ - !ruby/object:Gem::Dependency
83
+ type: :runtime
84
+ prerelease: false
85
+ name: ruby-debug
86
+ version_requirements: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 49
92
+ segments:
93
+ - 0
94
+ - 10
95
+ - 3
96
+ version: 0.10.3
97
+ requirement: *id005
98
+ - !ruby/object:Gem::Dependency
99
+ type: :runtime
100
+ prerelease: false
101
+ name: rspec-rails
102
+ version_requirements: &id006 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 31098209
108
+ segments:
109
+ - 2
110
+ - 0
111
+ - 0
112
+ - beta
113
+ version: 2.0.0.beta
114
+ requirement: *id006
115
+ - !ruby/object:Gem::Dependency
116
+ type: :development
117
+ prerelease: false
118
+ name: bundler
119
+ version_requirements: &id007 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ hash: 23
125
+ segments:
126
+ - 1
127
+ - 0
128
+ - 0
129
+ version: 1.0.0
130
+ requirement: *id007
131
+ - !ruby/object:Gem::Dependency
132
+ type: :development
133
+ prerelease: false
134
+ name: jeweler
135
+ version_requirements: &id008 !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ~>
139
+ - !ruby/object:Gem::Version
140
+ hash: -1876988218
141
+ segments:
142
+ - 1
143
+ - 5
144
+ - 0
145
+ - pre3
146
+ version: 1.5.0.pre3
147
+ requirement: *id008
148
+ - !ruby/object:Gem::Dependency
149
+ type: :development
150
+ prerelease: false
151
+ name: rcov
152
+ version_requirements: &id009 !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ hash: 3
158
+ segments:
159
+ - 0
160
+ version: "0"
161
+ requirement: *id009
162
+ - !ruby/object:Gem::Dependency
163
+ type: :runtime
164
+ prerelease: false
165
+ name: tilt
166
+ version_requirements: &id010 !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ~>
170
+ - !ruby/object:Gem::Version
171
+ hash: 13
172
+ segments:
173
+ - 1
174
+ - 1
175
+ version: "1.1"
176
+ requirement: *id010
177
+ - !ruby/object:Gem::Dependency
178
+ type: :development
179
+ prerelease: false
180
+ name: rspec
181
+ version_requirements: &id011 !ruby/object:Gem::Requirement
182
+ none: false
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ hash: 62196421
187
+ segments:
188
+ - 2
189
+ - 0
190
+ - 0
191
+ - beta
192
+ - 19
193
+ version: 2.0.0.beta.19
194
+ requirement: *id011
195
+ - !ruby/object:Gem::Dependency
196
+ type: :development
197
+ prerelease: false
198
+ name: bundler
199
+ version_requirements: &id012 !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ~>
203
+ - !ruby/object:Gem::Version
204
+ hash: 23
205
+ segments:
206
+ - 1
207
+ - 0
208
+ - 0
209
+ version: 1.0.0
210
+ requirement: *id012
211
+ - !ruby/object:Gem::Dependency
212
+ type: :development
213
+ prerelease: false
214
+ name: jeweler
215
+ version_requirements: &id013 !ruby/object:Gem::Requirement
216
+ none: false
217
+ requirements:
218
+ - - ~>
219
+ - !ruby/object:Gem::Version
220
+ hash: -1876988218
221
+ segments:
222
+ - 1
223
+ - 5
224
+ - 0
225
+ - pre3
226
+ version: 1.5.0.pre3
227
+ requirement: *id013
228
+ - !ruby/object:Gem::Dependency
229
+ type: :development
230
+ prerelease: false
231
+ name: rcov
232
+ version_requirements: &id014 !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ">="
236
+ - !ruby/object:Gem::Version
237
+ hash: 3
238
+ segments:
239
+ - 0
240
+ version: "0"
241
+ requirement: *id014
242
+ description: Rails 3 Engine for using the Houdini Mechanical Turk API
243
+ email: chris@chrisconley.me
244
+ executables: []
245
+
246
+ extensions: []
247
+
248
+ extra_rdoc_files:
249
+ - LICENSE
250
+ - README.rdoc
251
+ files:
252
+ - .document
253
+ - .gitignore
254
+ - .rspec
255
+ - Gemfile
256
+ - Gemfile.lock
257
+ - LICENSE
258
+ - README.rdoc
259
+ - Rakefile
260
+ - VERSION
261
+ - app/controllers/houdini/postbacks_controller.rb
262
+ - config/routes.rb
263
+ - houdini-rails3.gemspec
264
+ - lib/houdini_rails.rb
265
+ - lib/houdini_rails/base.rb
266
+ - lib/houdini_rails/engine.rb
267
+ - lib/houdini_rails/model.rb
268
+ - lib/houdini_rails/task.rb
269
+ - spec/controllers/houdini/postbacks_controller_spec.rb
270
+ - spec/dummy/Rakefile
271
+ - spec/dummy/app/controllers/application_controller.rb
272
+ - spec/dummy/app/helpers/application_helper.rb
273
+ - spec/dummy/app/models/post.rb
274
+ - spec/dummy/app/views/layouts/application.html.erb
275
+ - spec/dummy/app/views/posts/houdini_template.html.erb
276
+ - spec/dummy/config.ru
277
+ - spec/dummy/config/application.rb
278
+ - spec/dummy/config/boot.rb
279
+ - spec/dummy/config/database.yml
280
+ - spec/dummy/config/environment.rb
281
+ - spec/dummy/config/environments/development.rb
282
+ - spec/dummy/config/environments/production.rb
283
+ - spec/dummy/config/environments/test.rb
284
+ - spec/dummy/config/initializers/backtrace_silencers.rb
285
+ - spec/dummy/config/initializers/inflections.rb
286
+ - spec/dummy/config/initializers/mime_types.rb
287
+ - spec/dummy/config/initializers/secret_token.rb
288
+ - spec/dummy/config/initializers/session_store.rb
289
+ - spec/dummy/config/locales/en.yml
290
+ - spec/dummy/config/routes.rb
291
+ - spec/dummy/db/migrate/001_create_posts.rb
292
+ - spec/dummy/public/404.html
293
+ - spec/dummy/public/422.html
294
+ - spec/dummy/public/500.html
295
+ - spec/dummy/public/favicon.ico
296
+ - spec/dummy/public/javascripts/application.js
297
+ - spec/dummy/public/javascripts/controls.js
298
+ - spec/dummy/public/javascripts/dragdrop.js
299
+ - spec/dummy/public/javascripts/effects.js
300
+ - spec/dummy/public/javascripts/prototype.js
301
+ - spec/dummy/public/javascripts/rails.js
302
+ - spec/dummy/public/stylesheets/.gitkeep
303
+ - spec/dummy/script/rails
304
+ - spec/houdini_rails_spec.rb
305
+ - spec/requests/postbacks_spec.rb
306
+ - spec/spec_helper.rb
307
+ has_rdoc: true
308
+ homepage: http://github.com/chrisconley/houdini-rails3
309
+ licenses: []
310
+
311
+ post_install_message:
312
+ rdoc_options: []
313
+
314
+ require_paths:
315
+ - lib
316
+ required_ruby_version: !ruby/object:Gem::Requirement
317
+ none: false
318
+ requirements:
319
+ - - ">="
320
+ - !ruby/object:Gem::Version
321
+ hash: 3
322
+ segments:
323
+ - 0
324
+ version: "0"
325
+ required_rubygems_version: !ruby/object:Gem::Requirement
326
+ none: false
327
+ requirements:
328
+ - - ">="
329
+ - !ruby/object:Gem::Version
330
+ hash: 3
331
+ segments:
332
+ - 0
333
+ version: "0"
334
+ requirements: []
335
+
336
+ rubyforge_project:
337
+ rubygems_version: 1.3.7
338
+ signing_key:
339
+ specification_version: 3
340
+ summary: Rails 3 Engine for using the Houdini Mechanical Turk API
341
+ test_files:
342
+ - spec/controllers/houdini/postbacks_controller_spec.rb
343
+ - spec/dummy/app/controllers/application_controller.rb
344
+ - spec/dummy/app/helpers/application_helper.rb
345
+ - spec/dummy/app/models/post.rb
346
+ - spec/dummy/config/application.rb
347
+ - spec/dummy/config/boot.rb
348
+ - spec/dummy/config/environment.rb
349
+ - spec/dummy/config/environments/development.rb
350
+ - spec/dummy/config/environments/production.rb
351
+ - spec/dummy/config/environments/test.rb
352
+ - spec/dummy/config/initializers/backtrace_silencers.rb
353
+ - spec/dummy/config/initializers/inflections.rb
354
+ - spec/dummy/config/initializers/mime_types.rb
355
+ - spec/dummy/config/initializers/secret_token.rb
356
+ - spec/dummy/config/initializers/session_store.rb
357
+ - spec/dummy/config/routes.rb
358
+ - spec/dummy/db/migrate/001_create_posts.rb
359
+ - spec/houdini_rails_spec.rb
360
+ - spec/requests/postbacks_spec.rb
361
+ - spec/spec_helper.rb