bowline 0.5.8 → 0.6.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.
- data/README.txt +2 -2
- data/Rakefile +3 -2
- data/TODO +2 -0
- data/VERSION +1 -1
- data/assets/bowline.js +131 -68
- data/assets/bowline.test.js +86 -0
- data/bowline.gemspec +15 -17
- data/examples/tweet.rb +3 -1
- data/lib/bowline.rb +9 -5
- data/lib/bowline/app_config.rb +41 -0
- data/lib/bowline/binders.rb +70 -101
- data/lib/bowline/binders/collection.rb +37 -0
- data/lib/bowline/binders/observer.rb +30 -0
- data/lib/bowline/binders/singleton.rb +43 -0
- data/lib/bowline/commands/run.rb +1 -0
- data/lib/bowline/desktop/bridge.rb +4 -4
- data/lib/bowline/desktop/js.rb +7 -3
- data/lib/bowline/desktop/runtime.rb +29 -0
- data/lib/bowline/desktop/window.rb +9 -1
- data/lib/bowline/desktop/window_methods.rb +1 -1
- data/lib/bowline/generators/application.rb +1 -0
- data/lib/bowline/generators/binder.rb +7 -2
- data/lib/bowline/generators/model.rb +1 -1
- data/lib/bowline/helpers.rb +2 -0
- data/lib/bowline/initializer.rb +39 -87
- data/lib/bowline/library.rb +1 -7
- data/lib/bowline/tasks/app.rake +1 -53
- data/lib/bowline/tasks/libs.rake +4 -17
- data/lib/bowline/version.rb +2 -2
- data/lib/bowline/watcher.rb +50 -23
- data/templates/Gemfile +10 -0
- data/templates/config/boot.rb +11 -8
- data/templates/main_window.rb +1 -0
- metadata +20 -15
- data/lib/bowline/dependencies/FAQ.markdown +0 -6
- data/lib/bowline/dependencies/MIT-LICENSE +0 -20
- data/lib/bowline/dependencies/README.markdown +0 -51
- data/lib/bowline/dependencies/TODO.markdown +0 -4
- data/lib/bowline/dependencies/lib/dependencies.rb +0 -6
- data/lib/bowline/dependencies/lib/dependencies/dependency.rb +0 -12
- data/lib/bowline/dependencies/lib/dependencies/repository.rb +0 -64
- data/lib/bowline/dependencies/lib/ext/rubygems.rb +0 -116
- data/lib/bowline/ext/class.rb +0 -51
- data/lib/bowline/ext/string.rb +0 -9
- data/lib/bowline/local_model.rb +0 -142
- data/lib/bowline/tasks/gems.rake +0 -36
data/examples/tweet.rb
CHANGED
data/lib/bowline.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/dependencies'
|
3
|
+
require 'active_support/core_ext/string/access'
|
4
|
+
|
1
5
|
Thread.abort_on_exception = true
|
2
6
|
|
3
7
|
module Bowline
|
@@ -24,12 +28,9 @@ require 'bowline/version'
|
|
24
28
|
|
25
29
|
require 'bowline/ext/object'
|
26
30
|
require 'bowline/ext/array'
|
27
|
-
require 'bowline/ext/class'
|
28
|
-
require 'bowline/ext/string'
|
29
31
|
|
30
32
|
require 'bowline/logging'
|
31
33
|
require 'bowline/watcher'
|
32
|
-
require 'bowline/local_model'
|
33
34
|
|
34
35
|
require 'bowline/platform'
|
35
36
|
require 'bowline/library'
|
@@ -52,7 +53,10 @@ require 'bowline/desktop/bridge'
|
|
52
53
|
require 'bowline/desktop/window_manager.rb'
|
53
54
|
|
54
55
|
require 'bowline/helpers'
|
55
|
-
require 'bowline/
|
56
|
+
require 'bowline/app_config'
|
56
57
|
require 'bowline/initializer'
|
57
58
|
|
58
|
-
require 'bowline/binders'
|
59
|
+
require 'bowline/binders'
|
60
|
+
require 'bowline/binders/observer'
|
61
|
+
require 'bowline/binders/collection'
|
62
|
+
require 'bowline/binders/singleton'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bowline
|
2
|
+
class AppConfig
|
3
|
+
attr_reader :keys, :path
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
@keys = {}
|
7
|
+
load!
|
8
|
+
end
|
9
|
+
|
10
|
+
def load!
|
11
|
+
return unless File.exist?(path)
|
12
|
+
@keys = YAML::load(File.read(path))
|
13
|
+
end
|
14
|
+
|
15
|
+
def dump!
|
16
|
+
File.open(path, "w+") {|f| f.write(YAML::dump(keys)) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(key)
|
20
|
+
@keys.delete(key)
|
21
|
+
dump!
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(sym, *args)
|
25
|
+
method_name = sym.to_s
|
26
|
+
|
27
|
+
if method_name =~ /(=|\?)$/
|
28
|
+
case $1
|
29
|
+
when "="
|
30
|
+
keys[$`] = args.first
|
31
|
+
dump!
|
32
|
+
when "?"
|
33
|
+
keys[$`]
|
34
|
+
end
|
35
|
+
else
|
36
|
+
return keys[method_name] if keys.include?(method_name)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/bowline/binders.rb
CHANGED
@@ -65,11 +65,13 @@ module Bowline
|
|
65
65
|
def windows
|
66
66
|
@windows ||= []
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def setup(window) #:nodoc:
|
70
70
|
self.windows << window
|
71
|
-
|
72
|
-
|
71
|
+
if initial_items = initial
|
72
|
+
self.items = initial_items
|
73
|
+
end
|
74
|
+
Hash.new # Empty options
|
73
75
|
end
|
74
76
|
|
75
77
|
# Called by a window's JavaScript whenever that window is bound to this Binder.
|
@@ -80,7 +82,6 @@ module Bowline
|
|
80
82
|
# klass.all(:limit => 10)
|
81
83
|
# end
|
82
84
|
def initial
|
83
|
-
klass.all
|
84
85
|
end
|
85
86
|
|
86
87
|
def js_invoke(window, method, *args) #:nodoc:
|
@@ -104,7 +105,7 @@ module Bowline
|
|
104
105
|
|
105
106
|
# Set the binder's items. This will replace all items, and update the HTML.
|
106
107
|
def items=(items)
|
107
|
-
bowline.
|
108
|
+
bowline.replace(name, items.to_js).call
|
108
109
|
end
|
109
110
|
|
110
111
|
# Add a new item to the binder, updating the HTML.
|
@@ -138,103 +139,71 @@ module Bowline
|
|
138
139
|
item.id
|
139
140
|
).call
|
140
141
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# bind Post
|
147
|
-
#
|
148
|
-
# When the bound class is created/updated/deleted
|
149
|
-
# the binder's callbacks are executed and the view
|
150
|
-
# updated accordingly.
|
151
|
-
#
|
152
|
-
# Classes inheriting fromActiveRecord and Bowline::LocalModel are
|
153
|
-
# automatically compatable, but if you're using your own custom model
|
154
|
-
# you need to make sure it responds to the following methods:
|
155
|
-
# * all - return all records
|
156
|
-
# * find(id) - find record by id
|
157
|
-
# * after_create(method) - after_create callback
|
158
|
-
# * after_update(method) - after_update callback
|
159
|
-
# * after_destroy(method) - after_destroy callback
|
160
|
-
#
|
161
|
-
# The klass' instance needs to respond to:
|
162
|
-
# * id - returns record id
|
163
|
-
# * to_js - return record's attribute hash
|
164
|
-
#
|
165
|
-
# You can override the to_js method on the model instance
|
166
|
-
# in order to return specific attributes for the view.
|
167
|
-
def bind(klass)
|
168
|
-
@klass = klass
|
169
|
-
@klass.after_create(method(:created))
|
170
|
-
@klass.after_update(method(:updated))
|
171
|
-
@klass.after_destroy(method(:removed))
|
172
|
-
end
|
173
|
-
|
174
|
-
# Returns class set by the 'bind' method
|
175
|
-
def klass
|
176
|
-
@klass || raise("klass not set - see bind method")
|
177
|
-
end
|
178
|
-
|
179
|
-
# JavaScript proxy to the page.
|
180
|
-
# See Bowline::Desktop::Proxy for more information.
|
181
|
-
# Example:
|
182
|
-
# page.myFunc(1,2,3).call
|
183
|
-
def page
|
184
|
-
Bowline::Desktop::Proxy.new(
|
185
|
-
windows.length == 1 ? windows.first : windows
|
186
|
-
)
|
187
|
-
end
|
188
|
-
|
189
|
-
# JavaScript proxy to the Bowline object.
|
190
|
-
# See Bowline::Desktop::Proxy for more information.
|
191
|
-
# Example:
|
192
|
-
# bowline.log("msg").call
|
193
|
-
def bowline
|
194
|
-
page.Bowline
|
195
|
-
end
|
142
|
+
|
143
|
+
# Returns class set by the 'bind' method
|
144
|
+
def klass
|
145
|
+
@klass || raise("klass not set - see bind method")
|
146
|
+
end
|
196
147
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
name
|
235
|
-
|
236
|
-
|
237
|
-
|
148
|
+
# JavaScript proxy to the page.
|
149
|
+
# See Bowline::Desktop::Proxy for more information.
|
150
|
+
# Example:
|
151
|
+
# page.myFunc(1,2,3).call
|
152
|
+
def page
|
153
|
+
Bowline::Desktop::Proxy.new(
|
154
|
+
windows.length == 1 ? windows.first : windows
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
# JavaScript proxy to the Bowline object.
|
159
|
+
# See Bowline::Desktop::Proxy for more information.
|
160
|
+
# Example:
|
161
|
+
# bowline.log("msg").call
|
162
|
+
def bowline
|
163
|
+
page.Bowline
|
164
|
+
end
|
165
|
+
|
166
|
+
# Javascript proxy to jQuery.
|
167
|
+
# See Bowline::Desktop::Proxy for more information.
|
168
|
+
# Example:
|
169
|
+
# jquery.getJSON("http://example.com").call
|
170
|
+
def jquery
|
171
|
+
page.jQuery
|
172
|
+
end
|
173
|
+
|
174
|
+
# See Bowline::logger
|
175
|
+
def logger
|
176
|
+
Bowline::logger
|
177
|
+
end
|
178
|
+
|
179
|
+
# Trigger events on all elements
|
180
|
+
# bound to this binder.
|
181
|
+
# Example:
|
182
|
+
# trigger(:reload, {:key => :value})
|
183
|
+
def trigger(event, data = nil)
|
184
|
+
bowline.trigger(
|
185
|
+
name,
|
186
|
+
format_event(event),
|
187
|
+
data
|
188
|
+
).call
|
189
|
+
end
|
190
|
+
|
191
|
+
# Helper method to trigger a loading
|
192
|
+
# event either side of a block:
|
193
|
+
# loading {
|
194
|
+
# # Slow code, e.g. http call
|
195
|
+
# }
|
196
|
+
def loading(&block)
|
197
|
+
trigger(:loading, true)
|
198
|
+
yield
|
199
|
+
trigger(:loading, false)
|
200
|
+
end
|
201
|
+
|
202
|
+
def format_event(name) #:nodoc:
|
203
|
+
name.is_a?(Array) ?
|
204
|
+
name.join('.') :
|
205
|
+
name.to_s
|
206
|
+
end
|
238
207
|
end
|
239
208
|
|
240
209
|
# jQuery element object
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bowline
|
2
|
+
module Binders
|
3
|
+
class Collection < Base
|
4
|
+
class << self
|
5
|
+
# Associate the binder with a model to setup callbacks so
|
6
|
+
# changes to the model are automatically reflected in the view.
|
7
|
+
# Example:
|
8
|
+
# bind Post
|
9
|
+
#
|
10
|
+
# When the bound class is created/updated/deleted
|
11
|
+
# the binder's callbacks are executed and the view
|
12
|
+
# updated accordingly.
|
13
|
+
#
|
14
|
+
# Classes inheriting from ActiveRecord and SuperModel are
|
15
|
+
# automatically compatible, but if you're using your own custom model
|
16
|
+
# you need to make sure it responds to the following methods:
|
17
|
+
# * all - return all records
|
18
|
+
# * find(id) - find record by id
|
19
|
+
# * after_create(method) - after_create callback
|
20
|
+
# * after_update(method) - after_update callback
|
21
|
+
# * after_destroy(method) - after_destroy callback
|
22
|
+
#
|
23
|
+
# The klass' instance needs to respond to:
|
24
|
+
# * id - returns record id
|
25
|
+
# * to_js - return record's attribute hash
|
26
|
+
#
|
27
|
+
# You can override the to_js method on the model instance
|
28
|
+
# in order to return specific attributes for the view.
|
29
|
+
def bind(klass)
|
30
|
+
@klass = klass
|
31
|
+
observer = Observer.new(self)
|
32
|
+
@klass.add_observer(observer)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Bowline
|
2
|
+
module Binders
|
3
|
+
class Observer
|
4
|
+
attr_reader :binder
|
5
|
+
def initialize(binder)
|
6
|
+
@binder = binder
|
7
|
+
end
|
8
|
+
|
9
|
+
def after_create(rec)
|
10
|
+
binder.created(rec)
|
11
|
+
end
|
12
|
+
|
13
|
+
def after_update(rec)
|
14
|
+
binder.updated(rec)
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_destroy(rec)
|
18
|
+
binder.removed(rec)
|
19
|
+
end
|
20
|
+
|
21
|
+
def update(observed_method, object) #:nodoc:
|
22
|
+
send(observed_method, object) if respond_to?(observed_method)
|
23
|
+
end
|
24
|
+
|
25
|
+
def observed_class_inherited(subclass) #:nodoc:
|
26
|
+
subclass.add_observer(self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Bowline
|
2
|
+
module Binders
|
3
|
+
class Singleton < Base
|
4
|
+
class << self
|
5
|
+
def setup(*args) #:nodoc
|
6
|
+
super(*args)
|
7
|
+
{:singleton => true}
|
8
|
+
end
|
9
|
+
|
10
|
+
alias :item= :items=
|
11
|
+
|
12
|
+
# Associate the binder with a model to setup callbacks so
|
13
|
+
# changes to the model are automatically reflected in the view.
|
14
|
+
# Example:
|
15
|
+
# bind Post
|
16
|
+
#
|
17
|
+
# When the bound class is updated/deleted
|
18
|
+
# the binder's callbacks are executed and the view
|
19
|
+
# updated accordingly.
|
20
|
+
#
|
21
|
+
# Classes inheriting from ActiveRecord and SuperModel are
|
22
|
+
# automatically compatable, but if you're using your own custom model
|
23
|
+
# you need to make sure it responds to the following methods:
|
24
|
+
# * all - return all records
|
25
|
+
# * find(id) - find record by id
|
26
|
+
# * after_update(method) - after_update callback
|
27
|
+
# * after_destroy(method) - after_destroy callback
|
28
|
+
#
|
29
|
+
# The klass' instance needs to respond to:
|
30
|
+
# * id - returns record id
|
31
|
+
# * to_js - return record's attribute hash
|
32
|
+
#
|
33
|
+
# You can override the to_js method on the model instance
|
34
|
+
# in order to return specific attributes for the view.
|
35
|
+
def bind(klass)
|
36
|
+
@klass = klass
|
37
|
+
observer = Observer.new(self)
|
38
|
+
@klass.add_observer(observer)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/bowline/commands/run.rb
CHANGED
@@ -24,7 +24,7 @@ module Bowline
|
|
24
24
|
# TODO - implement options,
|
25
25
|
# like :except and :only
|
26
26
|
instance_eval <<-RUBY
|
27
|
-
def js_exposed?
|
27
|
+
def js_exposed?(meth)
|
28
28
|
true
|
29
29
|
end
|
30
30
|
|
@@ -61,10 +61,10 @@ module Bowline
|
|
61
61
|
object = klass.constantize
|
62
62
|
end
|
63
63
|
trace "JS invoking: #{klass}.#{method}(#{args.join(',')})"
|
64
|
-
if object.respond_to?(:js_exposed?) && object.js_exposed?
|
64
|
+
if object.respond_to?(:js_exposed?) && object.js_exposed?(method)
|
65
65
|
result = object.js_invoke(window, method, *args)
|
66
66
|
if callback?
|
67
|
-
proxy
|
67
|
+
proxy = Proxy.new(window)
|
68
68
|
proxy.Bowline.invokeCallback(id, result.to_js.to_json)
|
69
69
|
window.run_script(proxy.to_s)
|
70
70
|
end
|
@@ -80,7 +80,7 @@ module Bowline
|
|
80
80
|
result = JSON.parse(str)
|
81
81
|
Message.new(window, result).invoke
|
82
82
|
rescue => e
|
83
|
-
Bowline::Logging.log_error
|
83
|
+
Bowline::Logging.log_error e
|
84
84
|
end
|
85
85
|
module_function :call
|
86
86
|
end
|
data/lib/bowline/desktop/js.rb
CHANGED
@@ -41,15 +41,18 @@ module Bowline
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def parse(str)
|
44
|
+
return if str.blank?
|
44
45
|
# This is crazy! The JSON
|
45
46
|
# lib can't parse booleans
|
46
47
|
case str
|
47
48
|
when "true" then true
|
48
49
|
when "false" then false
|
49
|
-
when nil then nil
|
50
50
|
else
|
51
51
|
JSON.parse(str)
|
52
52
|
end
|
53
|
+
rescue => e
|
54
|
+
trace "Parsing: #{str}"
|
55
|
+
raise e
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
@@ -59,7 +62,7 @@ module Bowline
|
|
59
62
|
module_function :poll
|
60
63
|
|
61
64
|
def setup
|
62
|
-
Desktop.
|
65
|
+
Desktop.on_idle(method(:poll))
|
63
66
|
end
|
64
67
|
module_function :setup
|
65
68
|
|
@@ -76,8 +79,9 @@ module Bowline
|
|
76
79
|
private
|
77
80
|
def run_scripts
|
78
81
|
ready_scripts = scripts.select(&:ready?)
|
79
|
-
|
82
|
+
ready_scripts.each do |script|
|
80
83
|
script.call
|
84
|
+
scripts.delete(script)
|
81
85
|
end
|
82
86
|
end
|
83
87
|
module_function :run_scripts
|