strobe 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/bin/strobe +2 -12
  2. data/lib/strobe.rb +35 -88
  3. data/lib/strobe/association.rb +86 -0
  4. data/lib/strobe/cli.rb +39 -53
  5. data/lib/strobe/cli/action.rb +131 -0
  6. data/lib/strobe/cli/actions.rb +103 -0
  7. data/lib/strobe/cli/settings.rb +62 -0
  8. data/lib/strobe/collection.rb +53 -0
  9. data/lib/strobe/connection.rb +91 -0
  10. data/lib/strobe/resource/base.rb +235 -0
  11. data/lib/strobe/resource/collection.rb +50 -0
  12. data/lib/strobe/resource/singleton.rb +18 -0
  13. data/lib/strobe/resources/account.rb +12 -0
  14. data/lib/strobe/resources/application.rb +129 -0
  15. data/lib/strobe/resources/me.rb +11 -0
  16. data/lib/strobe/resources/signup.rb +27 -0
  17. data/lib/strobe/resources/team.rb +13 -0
  18. data/lib/strobe/resources/user.rb +11 -0
  19. data/lib/strobe/validations.rb +118 -0
  20. metadata +50 -124
  21. data/.gitignore +0 -5
  22. data/Gemfile +0 -4
  23. data/Gemfile.lock +0 -69
  24. data/Rakefile +0 -36
  25. data/features/1_sign_up.feature +0 -16
  26. data/features/2_deploying.feature +0 -35
  27. data/features/3_deploying_sproutcore_apps.feature +0 -19
  28. data/features/step_definitions/cli_steps.rb +0 -8
  29. data/features/step_definitions/deploying_steps.rb +0 -58
  30. data/features/step_definitions/sign_up.rb +0 -74
  31. data/features/support/helpers.rb +0 -104
  32. data/features/support/strobe.rb +0 -57
  33. data/lib/strobe/account.rb +0 -67
  34. data/lib/strobe/deploy.rb +0 -131
  35. data/lib/strobe/errors.rb +0 -12
  36. data/lib/strobe/http.rb +0 -94
  37. data/lib/strobe/server.rb +0 -13
  38. data/lib/strobe/settings.rb +0 -56
  39. data/lib/strobe/ui.rb +0 -81
  40. data/lib/strobe/user.rb +0 -9
  41. data/lib/strobe/version.rb +0 -3
  42. data/strobe.gemspec +0 -35
@@ -0,0 +1,50 @@
1
+ module Strobe
2
+ module Resource
3
+ module Collection
4
+ extend ActiveSupport::Concern
5
+ include Base
6
+
7
+ module ClassMethods
8
+ include Enumerable
9
+
10
+ def each
11
+ collection.each { |r| yield r }
12
+ end
13
+
14
+ def singular_resource_name
15
+ base_const_name.underscore
16
+ end
17
+
18
+ def resource_name
19
+ singular_resource_name.pluralize
20
+ end
21
+
22
+ def resource_uri
23
+ uri_prefix
24
+ end
25
+
26
+ def collection
27
+ Strobe::Collection.new(self)
28
+ end
29
+
30
+ alias all collection
31
+
32
+ def get(id, opts = {})
33
+ inst = new :id => id
34
+ inst.reload unless opts[:lazy]
35
+ inst
36
+ end
37
+ end
38
+
39
+ def id
40
+ self[:id]
41
+ end
42
+
43
+ def reload
44
+ resp = Strobe.connection.get "#{self.class.resource_uri}/#{id}"
45
+ self.params = resp.body[self.class.singular_resource_name]
46
+ self
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ module Strobe
2
+ module Resource
3
+ module Singleton
4
+ extend ActiveSupport::Concern
5
+ include Base
6
+
7
+ module ClassMethods
8
+ def resource_name
9
+ base_const_name.underscore
10
+ end
11
+
12
+ alias singular_resource_name resource_name
13
+ end
14
+
15
+ # stuff
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Strobe
2
+ module Resources
3
+ class Account
4
+ include Resource::Collection
5
+
6
+ has n, :users
7
+ has n, :applications
8
+
9
+ validates "name", :presence => true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,129 @@
1
+ require 'mime/types'
2
+
3
+ module Strobe
4
+ module Resources
5
+ class Application
6
+ include Resource::Collection
7
+
8
+ has 1, :account
9
+ has n, :teams
10
+ has n, :users
11
+
12
+ filter :path
13
+
14
+ validates "account", "name", "url", :presence => true
15
+ validates "path", :presence => true, :with => :ensure_sane_application_path,
16
+ :skippable => false
17
+
18
+ private
19
+
20
+ def ensure_sane_application_path
21
+ if self[:path] && Dir["#{self[:path]}/**/*"].empty?
22
+ errors.add('path', 'is not a sane application directory')
23
+ end
24
+ end
25
+
26
+ def create
27
+ multipart = build_multipart_request
28
+ connection.post http_uri, multipart.body, multipart.headers
29
+ end
30
+
31
+ def update
32
+ multipart = build_multipart_request
33
+ connection.put http_uri, multipart.body, multipart.headers
34
+ end
35
+
36
+ def build_multipart_request
37
+ Dir.chdir self[:path] do
38
+ Multipart.new request_params do |m|
39
+ Dir["**/*"].each do |filename|
40
+ next unless File.file?(filename)
41
+
42
+ mime_type = MIME::Types.type_for(filename).first
43
+ mime_type ||= "application/octet-stream"
44
+
45
+ m.file filename, mime_type.to_s, File.read(filename)
46
+ end
47
+
48
+ picked_root_app = false
49
+
50
+ Dir["static/*"].each do |appdir|
51
+ next if File.file?(appdir)
52
+
53
+ app_name = File.basename(appdir)
54
+ index = Dir["#{appdir}/*/*/index.html"].first
55
+
56
+ next unless index && File.file?(index)
57
+
58
+ manifest = "#{File.dirname(index)}/app.manifest"
59
+ manifest = File.read(manifest) if File.file?(manifest)
60
+ content = File.read(index)
61
+
62
+ m.file "#{app_name}/index.html", "text/html", content
63
+ m.file "#{app_name}/app.manifest", "text/cache-manifest", manifest if manifest
64
+
65
+ next if picked_root_app
66
+
67
+ m.file "index.html", "text/html", content
68
+ m.file "app.manifest", "text/cache-manifest", manifest
69
+
70
+ picked_root_app = true
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ class Multipart
77
+ attr_reader :params
78
+
79
+ def initialize(params)
80
+ @params = params
81
+ @files = []
82
+
83
+ yield self if block_given?
84
+ end
85
+
86
+ def file(path, content_type, body)
87
+ @files << [path, content_type, body]
88
+ end
89
+
90
+ def headers
91
+ { "Content-Type" => %[multipart/form-data; boundary="#{boundary}"] }
92
+ end
93
+
94
+ def body
95
+ b = "--#{boundary}\r\n"
96
+ b << part("metadata", "application/json", metadata)
97
+ b << "--#{boundary}\r\n"
98
+
99
+ @files.each do |path, type, body|
100
+ b << part("files[]", type, body)
101
+ b << "--#{boundary}\r\n"
102
+ end
103
+
104
+ b
105
+ end
106
+
107
+ private
108
+
109
+ def boundary
110
+ @boundary ||= ActiveSupport::SecureRandom.hex(25)
111
+ end
112
+
113
+ def metadata
114
+ params['application']['paths'] = @files.map { |parts| parts.first }
115
+ params.to_json
116
+ end
117
+
118
+ def part(name, type, body)
119
+ b = ""
120
+ b << %[Content-Disposition: form-data; name="#{name}"; filename="array"\r\n]
121
+ b << %[Content-Type: #{type}\r\n]
122
+ b << %[\r\n]
123
+ b << body
124
+ b << %[\r\n]
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,11 @@
1
+ module Strobe
2
+ module Resources
3
+ class Me
4
+ include Resource::Singleton
5
+
6
+ has 1, :user, :include => true, :autoload => false
7
+
8
+ validates "user.password", :presence => true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ module Strobe
2
+ module Resources
3
+ class Signup
4
+ include Resource::Singleton
5
+
6
+ has 1, :user, :include => true, :autoload => false
7
+ has 1, :account, :include => true, :autoload => false
8
+
9
+ filter :password_confirmation
10
+
11
+ validates "user", "account", :presence => true
12
+ validates "user.password", :presence => true,
13
+ :length => { :minimum => 5 }, :with => :password_confirmation
14
+
15
+ private
16
+
17
+ def password_confirmation
18
+ password = self["user.password"]
19
+ confirmation = self["password_confirmation"]
20
+
21
+ unless password == confirmation
22
+ errors.add "user.password", "and confirmation do not match"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module Strobe
2
+ module Resources
3
+ class Team
4
+ include Resource::Collection
5
+
6
+ has 1, :account
7
+ has n, :users
8
+ has n, :applications
9
+
10
+ validates :name, :presence => true
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Strobe
2
+ module Resources
3
+ class User
4
+ include Resource::Collection
5
+
6
+ has n, :accounts
7
+
8
+ validates "email", :presence => true, :email => true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,118 @@
1
+ module Strobe
2
+ module ::ActiveModel
3
+ class Validator
4
+ def skippable?
5
+ !options.key?(:skippable) || options[:skippable]
6
+ end
7
+ end
8
+
9
+ class Validations::WithValidator < EachValidator
10
+ def validate_each(record, attr, val)
11
+ record.send options[:method]
12
+ end
13
+ end
14
+
15
+ class Validations::EmailValidator < EachValidator
16
+ def validate_each(record, attr, val)
17
+ return if val.blank? || val =~ /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
18
+ record.errors[attr] << "is not a valid email address"
19
+ end
20
+ end
21
+ end
22
+
23
+ module Validations
24
+ extend ActiveSupport::Concern
25
+ include ActiveModel::Validations
26
+
27
+ included do
28
+ alias valid_for_all_attributes? valid?
29
+
30
+ def valid?
31
+ return valid_for_given_attributes? if persisted?
32
+ valid_for_all_attributes?
33
+ end
34
+ end
35
+
36
+ module ClassMethods
37
+ def validates(*attrs)
38
+ attrs.map! do |key|
39
+ key = key.to_sym if key.is_a?(String)
40
+ key
41
+ end
42
+
43
+ if Hash === attrs.last
44
+ defaults = attrs.pop
45
+ options = defaults.slice!(:skippable, :if, :unless, :on, :allow_blank, :allow_nil)
46
+
47
+ if Symbol === options[:with]
48
+ options[:with] = { :method => options[:with] }
49
+ end
50
+
51
+ if defaults.key?(:skippable)
52
+ options.keys.each do |key|
53
+ value = _parse_validates_options(options[key])
54
+ options[key] = value.merge(:skippable => defaults[:skippable])
55
+ end
56
+
57
+ defaults.delete(:skippable)
58
+ end
59
+
60
+ attrs << defaults.merge(options)
61
+ end
62
+
63
+ super
64
+ end
65
+ end
66
+
67
+ def valid_for_given_attributes?
68
+ errors.clear
69
+
70
+ ran = []
71
+
72
+ _validators.each do |attr, validators|
73
+ validators.each do |v|
74
+ next if !key?(attr) && v.skippable?
75
+ next if ran.include?(v)
76
+
77
+ v.validate(self)
78
+ ran << v
79
+ end
80
+ end
81
+
82
+ errors.empty?
83
+ end
84
+
85
+ def valid_attribute?(key, clear = true)
86
+ first, rest = key.to_s.split('.', 2)
87
+
88
+ errors.clear if clear
89
+
90
+ if self.class.associations.key?(first.to_sym) && rest
91
+ if inst = send(first)
92
+ inst.valid_attribute?(rest)
93
+
94
+ inst.errors.each do |k, v|
95
+ errors.add("#{first}.#{k}", v)
96
+ end
97
+ else
98
+ valid_attribute?(first, false)
99
+ end
100
+ end
101
+
102
+ validators = self.class.validators_on(key)
103
+ validators.each do |v|
104
+ v.validate(self)
105
+ end
106
+
107
+ errors.keys.each do |k|
108
+ errors.delete(k) unless k.to_s == key.to_s
109
+ end
110
+
111
+ errors.empty?
112
+ end
113
+
114
+ def read_attribute_for_validation(key)
115
+ self[key]
116
+ end
117
+ end
118
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Yehuda Katz
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-14 00:00:00 -07:00
18
+ date: 2010-12-14 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: thor
22
+ name: activesupport
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
@@ -27,14 +27,14 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  segments:
30
+ - 3
30
31
  - 0
31
- - 14
32
- - 1
33
- version: 0.14.1
32
+ - 0
33
+ version: 3.0.0
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
37
- name: rack
37
+ name: activemodel
38
38
  prerelease: false
39
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
40
  none: false
@@ -42,14 +42,14 @@ dependencies:
42
42
  - - ~>
43
43
  - !ruby/object:Gem::Version
44
44
  segments:
45
- - 1
46
- - 2
47
- - 1
48
- version: 1.2.1
45
+ - 3
46
+ - 0
47
+ - 0
48
+ version: 3.0.0
49
49
  type: :runtime
50
50
  version_requirements: *id002
51
51
  - !ruby/object:Gem::Dependency
52
- name: highline
52
+ name: faraday
53
53
  prerelease: false
54
54
  requirement: &id003 !ruby/object:Gem::Requirement
55
55
  none: false
@@ -57,14 +57,14 @@ dependencies:
57
57
  - - ~>
58
58
  - !ruby/object:Gem::Version
59
59
  segments:
60
- - 1
61
- - 6
62
- - 1
63
- version: 1.6.1
60
+ - 0
61
+ - 5
62
+ - 0
63
+ version: 0.5.0
64
64
  type: :runtime
65
65
  version_requirements: *id003
66
66
  - !ruby/object:Gem::Dependency
67
- name: excon
67
+ name: highline
68
68
  prerelease: false
69
69
  requirement: &id004 !ruby/object:Gem::Requirement
70
70
  none: false
@@ -72,28 +72,29 @@ dependencies:
72
72
  - - ~>
73
73
  - !ruby/object:Gem::Version
74
74
  segments:
75
+ - 1
76
+ - 6
75
77
  - 0
76
- - 2
77
- - 2
78
- version: 0.2.2
78
+ version: 1.6.0
79
79
  type: :runtime
80
80
  version_requirements: *id004
81
81
  - !ruby/object:Gem::Dependency
82
- name: mime-types
82
+ name: thor
83
83
  prerelease: false
84
84
  requirement: &id005 !ruby/object:Gem::Requirement
85
85
  none: false
86
86
  requirements:
87
- - - "="
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
89
  segments:
90
- - 1
91
- - 16
92
- version: "1.16"
90
+ - 0
91
+ - 14
92
+ - 0
93
+ version: 0.14.0
93
94
  type: :runtime
94
95
  version_requirements: *id005
95
96
  - !ruby/object:Gem::Dependency
96
- name: activesupport
97
+ name: mime-types
97
98
  prerelease: false
98
99
  requirement: &id006 !ruby/object:Gem::Requirement
99
100
  none: false
@@ -101,85 +102,16 @@ dependencies:
101
102
  - - ~>
102
103
  - !ruby/object:Gem::Version
103
104
  segments:
104
- - 3
105
- - 0
105
+ - 1
106
+ - 16
106
107
  - 0
107
- version: 3.0.0
108
+ version: 1.16.0
108
109
  type: :runtime
109
110
  version_requirements: *id006
110
- - !ruby/object:Gem::Dependency
111
- name: rake
112
- prerelease: false
113
- requirement: &id007 !ruby/object:Gem::Requirement
114
- none: false
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- segments:
119
- - 0
120
- version: "0"
121
- type: :development
122
- version_requirements: *id007
123
- - !ruby/object:Gem::Dependency
124
- name: rspec
125
- prerelease: false
126
- requirement: &id008 !ruby/object:Gem::Requirement
127
- none: false
128
- requirements:
129
- - - ~>
130
- - !ruby/object:Gem::Version
131
- segments:
132
- - 2
133
- - 0
134
- - 0
135
- version: 2.0.0
136
- type: :development
137
- version_requirements: *id008
138
- - !ruby/object:Gem::Dependency
139
- name: childlabor
140
- prerelease: false
141
- requirement: &id009 !ruby/object:Gem::Requirement
142
- none: false
143
- requirements:
144
- - - "="
145
- - !ruby/object:Gem::Version
146
- segments:
147
- - 0
148
- - 0
149
- - 3
150
- version: 0.0.3
151
- type: :development
152
- version_requirements: *id009
153
- - !ruby/object:Gem::Dependency
154
- name: cucumber
155
- prerelease: false
156
- requirement: &id010 !ruby/object:Gem::Requirement
157
- none: false
158
- requirements:
159
- - - ">="
160
- - !ruby/object:Gem::Version
161
- segments:
162
- - 0
163
- version: "0"
164
- type: :development
165
- version_requirements: *id010
166
- - !ruby/object:Gem::Dependency
167
- name: prawn
168
- prerelease: false
169
- requirement: &id011 !ruby/object:Gem::Requirement
170
- none: false
171
- requirements:
172
- - - ">="
173
- - !ruby/object:Gem::Version
174
- segments:
175
- - 0
176
- version: "0"
177
- type: :development
178
- version_requirements: *id011
179
111
  description: The client library for deploying applications to Strobe's HTML5 deployment platform
180
112
  email:
181
113
  - wycats@strobecorp.com
182
- - carllerche@strobecorp.com
114
+ - carl@strobecorp.com
183
115
  executables:
184
116
  - strobe
185
117
  extensions: []
@@ -187,31 +119,25 @@ extensions: []
187
119
  extra_rdoc_files: []
188
120
 
189
121
  files:
190
- - .gitignore
191
- - Gemfile
192
- - Gemfile.lock
193
- - Rakefile
194
- - bin/strobe
195
- - features/1_sign_up.feature
196
- - features/2_deploying.feature
197
- - features/3_deploying_sproutcore_apps.feature
198
- - features/step_definitions/cli_steps.rb
199
- - features/step_definitions/deploying_steps.rb
200
- - features/step_definitions/sign_up.rb
201
- - features/support/helpers.rb
202
- - features/support/strobe.rb
203
- - lib/strobe.rb
204
- - lib/strobe/account.rb
122
+ - lib/strobe/association.rb
123
+ - lib/strobe/cli/action.rb
124
+ - lib/strobe/cli/actions.rb
125
+ - lib/strobe/cli/settings.rb
205
126
  - lib/strobe/cli.rb
206
- - lib/strobe/deploy.rb
207
- - lib/strobe/errors.rb
208
- - lib/strobe/http.rb
209
- - lib/strobe/server.rb
210
- - lib/strobe/settings.rb
211
- - lib/strobe/ui.rb
212
- - lib/strobe/user.rb
213
- - lib/strobe/version.rb
214
- - strobe.gemspec
127
+ - lib/strobe/collection.rb
128
+ - lib/strobe/connection.rb
129
+ - lib/strobe/resource/base.rb
130
+ - lib/strobe/resource/collection.rb
131
+ - lib/strobe/resource/singleton.rb
132
+ - lib/strobe/resources/account.rb
133
+ - lib/strobe/resources/application.rb
134
+ - lib/strobe/resources/me.rb
135
+ - lib/strobe/resources/signup.rb
136
+ - lib/strobe/resources/team.rb
137
+ - lib/strobe/resources/user.rb
138
+ - lib/strobe/validations.rb
139
+ - lib/strobe.rb
140
+ - bin/strobe
215
141
  has_rdoc: true
216
142
  homepage: http://rubygems.org/gems/strobe
217
143
  licenses: []