strobe 0.0.1 → 0.0.2

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 (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: []