cloudfuji 0.0.37

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 (170) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +4 -0
  3. data/Gemfile +17 -0
  4. data/README.md +3 -0
  5. data/Rakefile +36 -0
  6. data/app/controllers/cloudfuji/data_controller.rb +33 -0
  7. data/app/controllers/cloudfuji/envs_controller.rb +31 -0
  8. data/app/controllers/cloudfuji/mail_controller.rb +37 -0
  9. data/bin/cloudfuji +86 -0
  10. data/cloudfuji.gemspec +26 -0
  11. data/config/routes.rb +1 -0
  12. data/lib/cloudfuji.rb +53 -0
  13. data/lib/cloudfuji/action_mailer.rb +35 -0
  14. data/lib/cloudfuji/app.rb +202 -0
  15. data/lib/cloudfuji/bar.rb +19 -0
  16. data/lib/cloudfuji/base.rb +23 -0
  17. data/lib/cloudfuji/command.rb +110 -0
  18. data/lib/cloudfuji/config.rb +12 -0
  19. data/lib/cloudfuji/data.rb +52 -0
  20. data/lib/cloudfuji/data_helper.rb +1 -0
  21. data/lib/cloudfuji/dns.rb +195 -0
  22. data/lib/cloudfuji/engine.rb +21 -0
  23. data/lib/cloudfuji/envs.rb +6 -0
  24. data/lib/cloudfuji/envs_helper.rb +1 -0
  25. data/lib/cloudfuji/event.rb +63 -0
  26. data/lib/cloudfuji/event_observer.rb +20 -0
  27. data/lib/cloudfuji/mail_helper.rb +1 -0
  28. data/lib/cloudfuji/mail_route.rb +186 -0
  29. data/lib/cloudfuji/middleware.rb +42 -0
  30. data/lib/cloudfuji/models.rb +59 -0
  31. data/lib/cloudfuji/notification.rb +0 -0
  32. data/lib/cloudfuji/orm/active_record.rb +44 -0
  33. data/lib/cloudfuji/orm/mongoid.rb +31 -0
  34. data/lib/cloudfuji/platform.rb +47 -0
  35. data/lib/cloudfuji/schema.rb +42 -0
  36. data/lib/cloudfuji/smtp.rb +24 -0
  37. data/lib/cloudfuji/user.rb +59 -0
  38. data/lib/cloudfuji/user_helper.rb +7 -0
  39. data/lib/cloudfuji/utils.rb +53 -0
  40. data/lib/cloudfuji/version.rb +4 -0
  41. data/lib/generators/active_record/cloudfuji_generator.rb +28 -0
  42. data/lib/generators/active_record/templates/migration.rb +20 -0
  43. data/lib/generators/cloudfuji/auth_migration_generator.rb +46 -0
  44. data/lib/generators/cloudfuji/cloudfuji_generator.rb +14 -0
  45. data/lib/generators/cloudfuji/hooks_generator.rb +43 -0
  46. data/lib/generators/cloudfuji/install_generator.rb +24 -0
  47. data/lib/generators/cloudfuji/mail_routes_generator.rb +45 -0
  48. data/lib/generators/cloudfuji/orm_helpers.rb +21 -0
  49. data/lib/generators/cloudfuji/routes_generator.rb +22 -0
  50. data/lib/generators/mongoid/cloudfuji_generator.rb +17 -0
  51. data/lib/generators/templates/README +5 -0
  52. data/lib/generators/templates/cloudfuji.rb +10 -0
  53. data/lib/hooks.rb +36 -0
  54. data/lib/rails/routes.rb +42 -0
  55. data/lib/tasks/cloudfuji.rake +6 -0
  56. data/spec/app_spec/controllers/envs_controller_spec.rb +25 -0
  57. data/spec/app_spec/controllers/mail_controller_spec.rb +28 -0
  58. data/spec/app_spec/integration/app_claim_spec.rb +16 -0
  59. data/spec/gem_spec/base_spec.rb +24 -0
  60. data/spec/gem_spec/command_spec.rb +181 -0
  61. data/spec/gem_spec/config_spec.rb +9 -0
  62. data/spec/gem_spec/data_spec.rb +13 -0
  63. data/spec/gem_spec/hooks_spec.rb +5 -0
  64. data/spec/gem_spec/mail_route_spec.rb +168 -0
  65. data/spec/gem_spec/platform_spec.rb +9 -0
  66. data/spec/gem_spec/user_spec.rb +45 -0
  67. data/spec/spec_helper.rb +21 -0
  68. data/spec/test_apps/rails-2.3/.gitignore +13 -0
  69. data/spec/test_apps/rails-2.3/Gemfile +13 -0
  70. data/spec/test_apps/rails-2.3/README +243 -0
  71. data/spec/test_apps/rails-2.3/Rakefile +10 -0
  72. data/spec/test_apps/rails-2.3/app/controllers/application_controller.rb +10 -0
  73. data/spec/test_apps/rails-2.3/app/helpers/application_helper.rb +3 -0
  74. data/spec/test_apps/rails-2.3/config/boot.rb +114 -0
  75. data/spec/test_apps/rails-2.3/config/environment.rb +41 -0
  76. data/spec/test_apps/rails-2.3/config/environments/development.rb +17 -0
  77. data/spec/test_apps/rails-2.3/config/environments/production.rb +28 -0
  78. data/spec/test_apps/rails-2.3/config/environments/test.rb +30 -0
  79. data/spec/test_apps/rails-2.3/config/initializers/backtrace_silencers.rb +7 -0
  80. data/spec/test_apps/rails-2.3/config/initializers/cookie_verification_secret.rb +7 -0
  81. data/spec/test_apps/rails-2.3/config/initializers/inflections.rb +10 -0
  82. data/spec/test_apps/rails-2.3/config/initializers/mime_types.rb +5 -0
  83. data/spec/test_apps/rails-2.3/config/initializers/new_rails_defaults.rb +21 -0
  84. data/spec/test_apps/rails-2.3/config/initializers/session_store.rb +15 -0
  85. data/spec/test_apps/rails-2.3/config/locales/en.yml +5 -0
  86. data/spec/test_apps/rails-2.3/config/routes.rb +43 -0
  87. data/spec/test_apps/rails-2.3/db/seeds.rb +7 -0
  88. data/spec/test_apps/rails-2.3/doc/README_FOR_APP +2 -0
  89. data/spec/test_apps/rails-2.3/lib/tasks/rspec.rake +144 -0
  90. data/spec/test_apps/rails-2.3/public/404.html +30 -0
  91. data/spec/test_apps/rails-2.3/public/422.html +30 -0
  92. data/spec/test_apps/rails-2.3/public/500.html +30 -0
  93. data/spec/test_apps/rails-2.3/public/favicon.ico +0 -0
  94. data/spec/test_apps/rails-2.3/public/images/rails.png +0 -0
  95. data/spec/test_apps/rails-2.3/public/javascripts/application.js +2 -0
  96. data/spec/test_apps/rails-2.3/public/javascripts/controls.js +963 -0
  97. data/spec/test_apps/rails-2.3/public/javascripts/dragdrop.js +973 -0
  98. data/spec/test_apps/rails-2.3/public/javascripts/effects.js +1128 -0
  99. data/spec/test_apps/rails-2.3/public/javascripts/prototype.js +4320 -0
  100. data/spec/test_apps/rails-2.3/public/robots.txt +5 -0
  101. data/spec/test_apps/rails-2.3/script/about +4 -0
  102. data/spec/test_apps/rails-2.3/script/autospec +6 -0
  103. data/spec/test_apps/rails-2.3/script/console +3 -0
  104. data/spec/test_apps/rails-2.3/script/dbconsole +3 -0
  105. data/spec/test_apps/rails-2.3/script/destroy +3 -0
  106. data/spec/test_apps/rails-2.3/script/generate +3 -0
  107. data/spec/test_apps/rails-2.3/script/performance/benchmarker +3 -0
  108. data/spec/test_apps/rails-2.3/script/performance/profiler +3 -0
  109. data/spec/test_apps/rails-2.3/script/plugin +3 -0
  110. data/spec/test_apps/rails-2.3/script/runner +3 -0
  111. data/spec/test_apps/rails-2.3/script/server +3 -0
  112. data/spec/test_apps/rails-2.3/script/spec +10 -0
  113. data/spec/test_apps/rails-2.3/spec/all_spec.rb +5 -0
  114. data/spec/test_apps/rails-2.3/spec/rcov.opts +2 -0
  115. data/spec/test_apps/rails-2.3/spec/spec.opts +4 -0
  116. data/spec/test_apps/rails-2.3/spec/spec_helper.rb +83 -0
  117. data/spec/test_apps/rails-2.3/test/performance/browsing_test.rb +9 -0
  118. data/spec/test_apps/rails-2.3/test/test_helper.rb +38 -0
  119. data/spec/test_apps/rails-3.0/.gitignore +4 -0
  120. data/spec/test_apps/rails-3.0/.rspec +2 -0
  121. data/spec/test_apps/rails-3.0/Gemfile +10 -0
  122. data/spec/test_apps/rails-3.0/README +256 -0
  123. data/spec/test_apps/rails-3.0/Rakefile +7 -0
  124. data/spec/test_apps/rails-3.0/app/controllers/application_controller.rb +3 -0
  125. data/spec/test_apps/rails-3.0/app/controllers/static_controller.rb +4 -0
  126. data/spec/test_apps/rails-3.0/app/helpers/application_helper.rb +2 -0
  127. data/spec/test_apps/rails-3.0/app/helpers/static_helper.rb +2 -0
  128. data/spec/test_apps/rails-3.0/app/views/layouts/application.html.erb +14 -0
  129. data/spec/test_apps/rails-3.0/app/views/static/home.html.erb +1 -0
  130. data/spec/test_apps/rails-3.0/config.ru +4 -0
  131. data/spec/test_apps/rails-3.0/config/application.rb +46 -0
  132. data/spec/test_apps/rails-3.0/config/boot.rb +6 -0
  133. data/spec/test_apps/rails-3.0/config/environment.rb +5 -0
  134. data/spec/test_apps/rails-3.0/config/environments/development.rb +26 -0
  135. data/spec/test_apps/rails-3.0/config/environments/production.rb +49 -0
  136. data/spec/test_apps/rails-3.0/config/environments/test.rb +35 -0
  137. data/spec/test_apps/rails-3.0/config/initializers/backtrace_silencers.rb +7 -0
  138. data/spec/test_apps/rails-3.0/config/initializers/inflections.rb +10 -0
  139. data/spec/test_apps/rails-3.0/config/initializers/mime_types.rb +5 -0
  140. data/spec/test_apps/rails-3.0/config/initializers/secret_token.rb +7 -0
  141. data/spec/test_apps/rails-3.0/config/initializers/session_store.rb +8 -0
  142. data/spec/test_apps/rails-3.0/config/locales/en.yml +5 -0
  143. data/spec/test_apps/rails-3.0/config/routes.rb +62 -0
  144. data/spec/test_apps/rails-3.0/db/schema.rb +15 -0
  145. data/spec/test_apps/rails-3.0/db/seeds.rb +7 -0
  146. data/spec/test_apps/rails-3.0/doc/README_FOR_APP +2 -0
  147. data/spec/test_apps/rails-3.0/lib/tasks/.gitkeep +0 -0
  148. data/spec/test_apps/rails-3.0/public/404.html +26 -0
  149. data/spec/test_apps/rails-3.0/public/422.html +26 -0
  150. data/spec/test_apps/rails-3.0/public/500.html +26 -0
  151. data/spec/test_apps/rails-3.0/public/favicon.ico +0 -0
  152. data/spec/test_apps/rails-3.0/public/images/rails.png +0 -0
  153. data/spec/test_apps/rails-3.0/public/index.html +239 -0
  154. data/spec/test_apps/rails-3.0/public/javascripts/application.js +2 -0
  155. data/spec/test_apps/rails-3.0/public/javascripts/controls.js +965 -0
  156. data/spec/test_apps/rails-3.0/public/javascripts/dragdrop.js +974 -0
  157. data/spec/test_apps/rails-3.0/public/javascripts/effects.js +1123 -0
  158. data/spec/test_apps/rails-3.0/public/javascripts/prototype.js +6001 -0
  159. data/spec/test_apps/rails-3.0/public/javascripts/rails.js +191 -0
  160. data/spec/test_apps/rails-3.0/public/robots.txt +5 -0
  161. data/spec/test_apps/rails-3.0/public/stylesheets/.gitkeep +0 -0
  162. data/spec/test_apps/rails-3.0/script/rails +6 -0
  163. data/spec/test_apps/rails-3.0/spec/all_spec.rb +5 -0
  164. data/spec/test_apps/rails-3.0/spec/spec_helper.rb +78 -0
  165. data/spec/test_apps/rails-3.0/test/performance/browsing_test.rb +9 -0
  166. data/spec/test_apps/rails-3.0/test/test_helper.rb +13 -0
  167. data/spec/test_apps/rails-3.0/vendor/plugins/.gitkeep +0 -0
  168. data/tasks/cover_me.rake +11 -0
  169. data/test_app/spec/views/home.html.erb_spec.rb +15 -0
  170. metadata +261 -0
@@ -0,0 +1 @@
1
+ # Automatically required by the envs_controller
@@ -0,0 +1,63 @@
1
+ module Cloudfuji
2
+ # Cloudfuji::Event lists all the events from the Cloudfuji server. All events
3
+ # are hashes with the following keys:
4
+ # * category
5
+ # * name
6
+ # * data
7
+ # Data will hold the arbitrary data for the type of event signalled
8
+ class Event
9
+ begin
10
+ @@events = JSON.parse(ENV["CLOUDFUJI_EVENTS"]) #:nodoc:
11
+ rescue
12
+ @@events = []
13
+ end
14
+
15
+ attr_reader :category, :name, :data
16
+
17
+ class << self
18
+ def events_url
19
+ "#{Cloudfuji::Platform.host}/apps/#{Cloudfuji::Platform.name}/events.json"
20
+ end
21
+
22
+ # Lists all events
23
+ def all
24
+ @@events.collect{ |e| Event.new(e) }
25
+ end
26
+
27
+ # Lists the first (oldest) event
28
+ def first
29
+ Event.new(@@events.first)
30
+ end
31
+
32
+ # Lists the last (newest) event
33
+ def last
34
+ Event.new(@@events.last)
35
+ end
36
+
37
+ # NOOP right now
38
+ def refresh
39
+ @@events = Cloudfuji::Command.get_command(events_url)
40
+ end
41
+
42
+ def publish(options={})
43
+ # Enforce standard format on client side so that any errors
44
+ # can be more quickly caught for the developer
45
+ return StandardError("Cloudfuji::Event format incorrect, please make sure you're using the correct structure for sending events") unless !options[:name].nil? && !options[:category].nil? && !options[:data].nil?
46
+
47
+ payload = {}
48
+ payload[:category] = options[:category]
49
+ payload[:name] = options[:name]
50
+ payload[:data] = options[:data]
51
+
52
+ Cloudfuji::Command.post_command(events_url, payload)
53
+ end
54
+ end
55
+
56
+ def initialize(options={})
57
+ @category = options["category"]
58
+ @name = options["name"]
59
+ @data = options["data"]
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,20 @@
1
+ module Cloudfuji
2
+ class EventObserver
3
+ attr_accessor :params
4
+
5
+ def self.inherited(klass)
6
+ if Cloudfuji::Platform.on_cloudfuji?
7
+ Cloudfuji::Data.add_observer(klass.new)
8
+ else
9
+ end
10
+ end
11
+
12
+ def initialize
13
+ @params ||= {}
14
+ end
15
+
16
+ def params
17
+ @params
18
+ end
19
+ end
20
+ end
@@ -0,0 +1 @@
1
+ # Automatically required by the mail_controller
@@ -0,0 +1,186 @@
1
+ module Cloudfuji
2
+ class Mailroute
3
+ def self.map(&block)
4
+ raise StandardError.new("Mailroute only supported in Ruby >= 1.9.1") if RUBY_VERSION < "1.9.1"
5
+
6
+ @@routes ||= self.new
7
+ yield @@routes
8
+ end
9
+
10
+ def self.routes
11
+ @@routes
12
+ end
13
+
14
+ def self.clear_routes!
15
+ @@routes = self.new
16
+ end
17
+
18
+ def self.pretty_print_routes
19
+ @@routes.routes.each_pair do |route_name, definition|
20
+ puts "#{route_name} => "
21
+ definition[:rules].each do |rule|
22
+ pretty_print_rule(rule, "\t\t")
23
+ end
24
+ definition[:constraints].each do |constraint|
25
+ pretty_print_contraint(constraint, "\t\t")
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.pretty_print_rule(rule, prefix="")
31
+ output = "#{prefix}#{rule.first} => #{string_to_regex(rule[1]).inspect}, required? #{rule.last == true}"
32
+ puts output
33
+ end
34
+
35
+ def self.pretty_print_contraint(constraint, prefix="")
36
+ output = "#{prefix}Constraint: #{constraint.inspect}"
37
+ puts output
38
+ end
39
+
40
+ # Taken from somewhere on stackoverflow, props to the author!
41
+ def self.string_to_regex(string)
42
+ return nil unless string.strip.match(/\A\/(.*)\/(.*)\Z/mx)
43
+ regexp , flags = $1 , $2
44
+ return nil if !regexp || flags =~ /[^xim]/m
45
+
46
+ x = /x/.match(flags) && Regexp::EXTENDED
47
+ i = /i/.match(flags) && Regexp::IGNORECASE
48
+ m = /m/.match(flags) && Regexp::MULTILINE
49
+
50
+ Regexp.new regexp , [x,i,m].inject(0){|a,f| f ? a+f : a }
51
+ end
52
+
53
+ def self.field_matcher(*field_names)
54
+ self.class_eval do
55
+ field_names.each do |field_name|
56
+ define_method field_name do |line, *args|
57
+ constraints = args.first || {}
58
+ required = args[1]
59
+
60
+ add_route_rule(field_name.to_s, build_matcher(line, constraints), required)
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ attr_accessor :params, :constraints, :routes, :current_target, :reply
67
+ field_matcher :from, :sender, :subject, :body
68
+
69
+ # Regex shortcuts
70
+ def ampm
71
+ /\d+[apmAPM]{2}/
72
+ end
73
+
74
+ def word
75
+ /\w+/
76
+ end
77
+
78
+ def number
79
+ /\d+/
80
+ end
81
+
82
+ def words_and_spaces
83
+ /[\w|\s]+/
84
+ end
85
+
86
+ def month
87
+ /((?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))/
88
+ end
89
+
90
+ def year
91
+ /((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3})))(?![\\d])/
92
+ end
93
+
94
+ def initialize
95
+ @routes ||= ActiveSupport::OrderedHash.new
96
+ end
97
+
98
+ def route(target, &block)
99
+ @routes[@current_target = target] = {:rules => [], :constraints => []}
100
+ yield self
101
+ end
102
+
103
+ # Maybe add_requirement is better?
104
+ # Constraint procs must return true if the mail should be allowed
105
+ def add_constraint(params_field_name, requirement_type)
106
+ checkers = {
107
+ :not_allowed => Proc.new { |params| params[params_field_name.to_s].nil? },
108
+ :required => Proc.new { |params| not params[params_field_name.to_s].nil? },
109
+ :custom => Proc.new { |params| requirement_type.call(params[params_field_name.to_s]) }
110
+ }
111
+
112
+ checker = requirement_type.is_a?(Proc) ? checkers[:custom] : checkers[requirement_type]
113
+
114
+ raise StandardError if checker.nil?
115
+
116
+ @routes[@current_target][:constraints] << checker
117
+ @routes[@current_target][:constraints].flatten! # In case we've added a nil
118
+ end
119
+
120
+ def process(mail)
121
+ @params = preprocess_mail(mail)
122
+
123
+ # Iterate through the routes and test each rule for each route against current mail
124
+ @routes.each_pair do |route_name, definition|
125
+ _matches = true
126
+
127
+ # route: {'name-of-route' => {:rules => [[:field, matcher]], :constraints => []}}
128
+ definition[:rules].each do |matcher|
129
+ result = self.class.string_to_regex(matcher[1]).match(mail[matcher.first])
130
+ if result.nil?
131
+ _matches = false
132
+ break
133
+ end
134
+
135
+ # Only Ruby 1.9 support named capture groups
136
+ result.names.each { |key| @params[key] = result[key] }
137
+ end
138
+
139
+ # Run param-based constraints
140
+ if _matches and constraints_pass?(definition[:constraints], params)
141
+ @params['mail'] = mail
142
+ puts "Firing: #{@params.inspect}, #{route_name}"
143
+ return Cloudfuji::Data.fire(params, "mail_#{route_name.gsub('.', '_')}")
144
+ break
145
+ end
146
+
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ def preprocess_mail(mail)
153
+ params = {}
154
+ # Remove Re:'s from the subject and set reply => true if present
155
+ if mail["subject"].match(/^(Re: ){1,}/i)
156
+ params['reply'] = true
157
+ until !mail["subject"].match(/^(Re: ){1,}/i)
158
+ mail["subject"] = mail["subject"][4..-1]
159
+ end
160
+ end
161
+
162
+ if from_details = mail['from'].try(:match, /^([\w|\s]*) <(.*)>/)
163
+ params['from_name'] = from_details[1]
164
+ params['from_email'] = from_details[2]
165
+ end
166
+
167
+ return params
168
+ end
169
+
170
+ def add_route_rule(field, matcher, required=true)
171
+ route = @routes[@current_target]
172
+ route[route.keys.first] << [field, matcher, required]
173
+ end
174
+
175
+ def build_matcher(line, constraints)
176
+ temp = "/#{line}/"
177
+ constraints.keys.each { |key| temp.gsub!("{:#{key}}", "(?<#{key}>#{constraints[key].inspect[1..-2]})") }
178
+ temp
179
+ end
180
+
181
+ def constraints_pass?(constraints, params)
182
+ constraints.nil? or constraints.select{ |proc| proc.call(params) != true }.empty?
183
+ end
184
+ end
185
+ end
186
+
@@ -0,0 +1,42 @@
1
+ #require 'rack/utils'
2
+
3
+ module Cloudfuji
4
+ class Middleware
5
+ include Rack::Utils
6
+
7
+ def initialize(app, opts = {})
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ if Cloudfuji::Platform.on_cloudfuji? and Cloudfuji::Bar.in_bar_display_path?(env)
13
+ status, headers, response = @app.call(env)
14
+
15
+ content = ""
16
+ response.each { |part| content += part }
17
+
18
+ # "claiming" bar + stats ?
19
+ content.gsub!(/<\/body>/i, <<-STR
20
+ <script type="text/javascript">
21
+ var _cloudfuji_app = '#{Cloudfuji::Platform.name}';
22
+ var _cloudfuji_claimed = #{Cloudfuji::Platform.claimed?.to_s};
23
+ var _cloudfuji_metrics_token = '#{Cloudfuji::Platform.metrics_token}';
24
+ (function() {
25
+ var cloudfuji = document.createElement('script'); cloudfuji.type = 'text/javascript'; cloudfuji.async = true;
26
+ cloudfuji.src = '#{Cloudfuji::Platform.cloudfuji_js_source}?t=#{::Cloudfuji::VERSION.gsub('.', '')}';
27
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(cloudfuji, s);
28
+ })();
29
+ </script>
30
+ </body>
31
+ STR
32
+ )
33
+
34
+ headers['content-length'] = bytesize(content).to_s
35
+ [status, headers, [content]]
36
+ else
37
+ @app.call(env)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,59 @@
1
+ module Cloudfuji
2
+ module Models
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ def cloudfuji_save
8
+ # It's possible we're saving an item just handed to us by Cloudfuji, so we
9
+ # don't want to re-publish it. We can detect it using the version.
10
+
11
+ puts "what"
12
+ # cloudfuji_id.nil? This is new, it's from us (otherwise cloudfuji would have given it an id), we should publish it.
13
+ # cloudfuji_version == self.find(self.id).cloudfuji_version The version hasn't changed, our data has, we should publish it
14
+ puts "new_record? #{self.new_record?}"
15
+ puts "self.id = #{self.id}"
16
+ puts "ido_id.nil? #{ido_id.nil?}"
17
+ puts "ido_version == self.class.find(self.id).ido_version ? #{ido_version == self.class.find(self.id).ido_version}" unless self.new_record?
18
+ if self.ido_id.nil? or (not self.new_record? and self.ido_version == self.class.find(self.id).ido_version)
19
+ puts "Local change, publishing to Cloudfuji databus"
20
+
21
+ data = self.to_cloudfuji
22
+
23
+ begin
24
+ response = Cloudfuji::Data.publish(self.class.class_variable_get("@@ido_model"), data)
25
+ rescue => e
26
+ puts e.inspect
27
+ # TODO: Catch specific exceptions and bubble up errors (e.g. 'cloudfuji is down', 'model is malformed', etc.)
28
+ return false
29
+ end
30
+
31
+ self.ido_version = response["ido_version"]
32
+ self.ido_id ||= response["ido_id"]
33
+
34
+ puts response.inspect
35
+ else
36
+ puts "Remote change, not publishing to Cloudfuji databus"
37
+ end
38
+
39
+ return true
40
+ end
41
+
42
+ module ClassMethods
43
+ def cloudfuji model
44
+ self.class_variable_set("@@ido_model", model)
45
+
46
+ [:create, :update, :destroy].each do |event|
47
+ puts "Hooking into #{model}.#{event}..."
48
+
49
+ Cloudfuji::Data.listen("#{model}.#{event}") do |data, hook|
50
+ puts "#{hook}.) Firing off #{model}.#{event} now with data: #{data}"
51
+ self.send("on_cloudfuji_#{event}".to_sym, self.from_cloudfuji(data))
52
+ end
53
+ end
54
+
55
+ before_save :cloudfuji_save
56
+ end
57
+ end
58
+ end
59
+ end
File without changes
@@ -0,0 +1,44 @@
1
+ require 'orm_adapter/adapters/active_record'
2
+
3
+ module Cloudfuji
4
+ module Orm
5
+ # This module contains some helpers and handle schema (migrations):
6
+ #
7
+ # create_table :accounts do |t|
8
+ # t.database_authenticatable
9
+ # t.confirmable
10
+ # t.recoverable
11
+ # t.rememberable
12
+ # t.trackable
13
+ # t.lockable
14
+ # t.timestamps
15
+ # end
16
+ #
17
+ # However this method does not add indexes. If you need them, here is the declaration:
18
+ #
19
+ # add_index "accounts", ["email"], :name => "email", :unique => true
20
+ # add_index "accounts", ["confirmation_token"], :name => "confirmation_token", :unique => true
21
+ # add_index "accounts", ["reset_password_token"], :name => "reset_password_token", :unique => true
22
+ #
23
+ module ActiveRecord
24
+ module Schema
25
+ include Cloudfuji::Schema
26
+
27
+ # Tell how to apply schema methods.
28
+ def apply_cloudfuji_schema(name, type, options={})
29
+ column name, type.to_s.downcase.to_sym, options
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ module ActiveRecord
37
+ class Base
38
+ include Cloudfuji::Models
39
+ end
40
+ end
41
+
42
+ ActiveRecord::ConnectionAdapters::Table.send :include, Cloudfuji::Orm::ActiveRecord::Schema
43
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Cloudfuji::Orm::ActiveRecord::Schema
44
+
@@ -0,0 +1,31 @@
1
+ require 'orm_adapter/adapters/mongoid'
2
+
3
+ module Cloudfuji
4
+ module Orm
5
+ module Mongoid
6
+ module Hook
7
+ def cloudfuji_modules_hook!
8
+ extend Schema
9
+ yield
10
+ return unless Devise.apply_schema
11
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
12
+ end
13
+ end
14
+
15
+ module Schema
16
+ include Cloudfuji::Schema
17
+
18
+ # Tell how to apply schema methods
19
+ def apply_cloudfuji_schema(name, type, options={})
20
+ type = Time if type == DateTime
21
+ field name, { :type => type }.merge!(options)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Mongoid::Document::ClassMethods.class_eval do
29
+ include Cloudfuji::Models
30
+ include Cloudfuji::Orm::Mongoid::Hook
31
+ end