bowline 0.1.6
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/.gitignore +1 -0
- data/History.txt +4 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +58 -0
- data/README.txt +136 -0
- data/Rakefile +25 -0
- data/assets/jquery.bowline.js +96 -0
- data/assets/jquery.chain.js +2348 -0
- data/assets/jquery.js +3549 -0
- data/bin/bowline-gen +6 -0
- data/bowline.gemspec +45 -0
- data/examples/account.rb +31 -0
- data/examples/example.js +24 -0
- data/examples/tweets.rb +28 -0
- data/examples/twitter.html +39 -0
- data/examples/users.rb +37 -0
- data/lib/bowline.rb +42 -0
- data/lib/bowline/binders.rb +177 -0
- data/lib/bowline/binders/collection.rb +27 -0
- data/lib/bowline/binders/singleton.rb +25 -0
- data/lib/bowline/commands/console.rb +27 -0
- data/lib/bowline/commands/generate.rb +1 -0
- data/lib/bowline/commands/run.rb +11 -0
- data/lib/bowline/ext/array.rb +5 -0
- data/lib/bowline/ext/class.rb +51 -0
- data/lib/bowline/ext/object.rb +12 -0
- data/lib/bowline/ext/string.rb +9 -0
- data/lib/bowline/gem_dependency.rb +42 -0
- data/lib/bowline/generators.rb +59 -0
- data/lib/bowline/generators/application.rb +58 -0
- data/lib/bowline/generators/binder.rb +25 -0
- data/lib/bowline/generators/migration.rb +51 -0
- data/lib/bowline/generators/model.rb +20 -0
- data/lib/bowline/initializer.rb +596 -0
- data/lib/bowline/jquery.rb +31 -0
- data/lib/bowline/observer.rb +43 -0
- data/lib/bowline/tasks/app.rake +90 -0
- data/lib/bowline/tasks/bowline.rb +8 -0
- data/lib/bowline/tasks/database.rake +167 -0
- data/lib/bowline/tasks/log.rake +9 -0
- data/lib/bowline/tasks/misk.rake +3 -0
- data/templates/Rakefile +7 -0
- data/templates/binder.rb +9 -0
- data/templates/config/application.yml +1 -0
- data/templates/config/boot.rb +13 -0
- data/templates/config/database.yml +4 -0
- data/templates/config/environment.rb +12 -0
- data/templates/config/manifest +18 -0
- data/templates/config/tiapp.xml +24 -0
- data/templates/gitignore +15 -0
- data/templates/migration.rb +7 -0
- data/templates/model.rb +4 -0
- data/templates/public/index.html +25 -0
- data/templates/public/javascripts/application.js +0 -0
- data/templates/public/stylesheets/application.css +0 -0
- data/templates/script/console +3 -0
- data/templates/script/init +18 -0
- data/templates/script/run +3 -0
- metadata +155 -0
data/bin/bowline-gen
ADDED
data/bowline.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{bowline}
|
5
|
+
s.version = "0.1.6"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Alex MacCaw"]
|
9
|
+
s.date = %q{2009-04-24}
|
10
|
+
s.default_executable = %q{bowline-gen}
|
11
|
+
s.description = %q{Ruby desktop application framework}
|
12
|
+
s.email = ["info@eribium.org"]
|
13
|
+
s.executables = ["bowline-gen"]
|
14
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
15
|
+
s.files = [".gitignore", "History.txt", "MIT-LICENSE", "Manifest.txt", "README.txt", "Rakefile", "assets/jquery.bowline.js", "assets/jquery.chain.js", "assets/jquery.js", "bin/bowline-gen", "bowline.gemspec", "examples/account.rb", "examples/example.js", "examples/twitter.html", "examples/tweets.rb", "examples/users.rb", "lib/bowline.rb", "lib/bowline/binders.rb", "lib/bowline/binders/collection.rb", "lib/bowline/binders/singleton.rb", "lib/bowline/commands/console.rb", "lib/bowline/commands/generate.rb", "lib/bowline/commands/run.rb", "lib/bowline/ext/array.rb", "lib/bowline/ext/class.rb", "lib/bowline/ext/object.rb", "lib/bowline/ext/string.rb", "lib/bowline/gem_dependency.rb", "lib/bowline/generators.rb", "lib/bowline/generators/application.rb", "lib/bowline/generators/binder.rb", "lib/bowline/generators/migration.rb", "lib/bowline/generators/model.rb", "lib/bowline/initializer.rb", "lib/bowline/jquery.rb", "lib/bowline/observer.rb", "lib/bowline/tasks/app.rake", "lib/bowline/tasks/bowline.rb", "lib/bowline/tasks/database.rake", "lib/bowline/tasks/log.rake", "lib/bowline/tasks/misk.rake", "templates/Rakefile", "templates/binder.rb", "templates/config/application.yml", "templates/config/boot.rb", "templates/config/database.yml", "templates/config/environment.rb", "templates/config/manifest", "templates/config/tiapp.xml", "templates/gitignore", "templates/migration.rb", "templates/model.rb", "templates/public/index.html", "templates/public/javascripts/application.js", "templates/public/stylesheets/application.css", "templates/script/console", "templates/script/init", "templates/script/run"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.homepage = %q{http://github.com/maccman/bowline}
|
18
|
+
s.rdoc_options = ["--main", "README.txt"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{maccman}
|
21
|
+
s.rubygems_version = %q{1.3.2}
|
22
|
+
s.summary = %q{Ruby desktop application framework}
|
23
|
+
|
24
|
+
if s.respond_to? :specification_version then
|
25
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
26
|
+
s.specification_version = 3
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
29
|
+
s.add_runtime_dependency(%q<templater>, [">= 0.3.2"])
|
30
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.3.2"])
|
31
|
+
s.add_development_dependency(%q<newgem>, [">= 1.3.0"])
|
32
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<templater>, [">= 0.3.2"])
|
35
|
+
s.add_dependency(%q<activesupport>, [">= 2.3.2"])
|
36
|
+
s.add_dependency(%q<newgem>, [">= 1.3.0"])
|
37
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
38
|
+
end
|
39
|
+
else
|
40
|
+
s.add_dependency(%q<templater>, [">= 0.3.2"])
|
41
|
+
s.add_dependency(%q<activesupport>, [">= 2.3.2"])
|
42
|
+
s.add_dependency(%q<newgem>, [">= 1.3.0"])
|
43
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
44
|
+
end
|
45
|
+
end
|
data/examples/account.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Binders
|
2
|
+
class Account < Bowline::Binders::Singleton
|
3
|
+
class << self
|
4
|
+
# self.collection is a special method
|
5
|
+
# Basically it'll update users on the client side
|
6
|
+
def index
|
7
|
+
self.item = current_account
|
8
|
+
end
|
9
|
+
|
10
|
+
def destroy
|
11
|
+
current_account.destroy
|
12
|
+
self.item = nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Everything has a js_id which is basically the lowercase classname + _ + self.id
|
17
|
+
def highlight
|
18
|
+
# Calls $(element).highlight()
|
19
|
+
self.element.highlight
|
20
|
+
end
|
21
|
+
|
22
|
+
# Overrides charge on user
|
23
|
+
def charge!
|
24
|
+
# calls charge on model (i.e. do sql commit )
|
25
|
+
self.item.charge!
|
26
|
+
# Now gui stuff
|
27
|
+
flash[:notice] = "Successfully charged"
|
28
|
+
highlight
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/examples/example.js
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$('#users').bowline('users_binder');
|
2
|
+
|
3
|
+
var user = $('#users').items(10);
|
4
|
+
user.update({name: 'Alex'}); // will automatiinvokey
|
5
|
+
user.item().errors //=> []
|
6
|
+
|
7
|
+
// Deletes item from DOM too
|
8
|
+
item.destroy()
|
9
|
+
|
10
|
+
// invoke collection method
|
11
|
+
// This will invoke UserBinder.admins and fill #users with admins
|
12
|
+
$('#users').invoke('admins');
|
13
|
+
|
14
|
+
// invoke singleton method
|
15
|
+
$('#users').items(10).invoke('charge!');
|
16
|
+
|
17
|
+
// invoke charge! on every user
|
18
|
+
$('#users').items().invoke('charge!')
|
19
|
+
|
20
|
+
// // For binding over a http connection - an async invoke
|
21
|
+
// // last argument is a function
|
22
|
+
// $('#users').items(10).invoke('charge!', function(){
|
23
|
+
//
|
24
|
+
// })
|
data/examples/tweets.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Binders
|
2
|
+
class Tweets < Bowline::Binders::Collection
|
3
|
+
class << self
|
4
|
+
def index
|
5
|
+
self.items = timeline
|
6
|
+
end
|
7
|
+
|
8
|
+
def update(status)
|
9
|
+
twitter.update(status)
|
10
|
+
index # update timeline
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
def twitter
|
15
|
+
httpauth = Twitter::HTTPAuth.new('user', 'pass')
|
16
|
+
Twitter::Base.new(httpauth)
|
17
|
+
end
|
18
|
+
|
19
|
+
def timeline
|
20
|
+
twitter.friends_timeline.collect {|t|
|
21
|
+
t.delete('user')
|
22
|
+
t.to_hash
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end # Binders
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
2
|
+
"http://www.w3.org/TR/html4/strict.dtd">
|
3
|
+
|
4
|
+
<html lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
7
|
+
<title>Twitter</title>
|
8
|
+
<!--
|
9
|
+
<script src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js" type="text/javascript"></script>
|
10
|
+
-->
|
11
|
+
<script src="javascripts/jquery.js" type="text/javascript" charset="utf-8"></script>
|
12
|
+
<script src="javascripts/jquery.chain.js" type="text/javascript" charset="utf-8"></script>
|
13
|
+
<script src="javascripts/jquery.bowline.js" type="text/javascript" charset="utf-8"></script>
|
14
|
+
<script src="../script/init" type="text/ruby" charset="utf-8"></script>
|
15
|
+
<script src="javascripts/application.js" type="text/javascript" charset="utf-8"></script>
|
16
|
+
<link rel="stylesheet" href="stylesheets/application.css" type="text/css" charset="utf-8">
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
jQuery(function($){
|
19
|
+
var tweets = $('#tweets').bowline('tweets');
|
20
|
+
tweets.invoke('index');
|
21
|
+
|
22
|
+
$('#updateSubmit').click(function(){
|
23
|
+
tweets.invoke('update', $('#updateText').val());
|
24
|
+
return false;
|
25
|
+
})
|
26
|
+
});
|
27
|
+
</script>
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div id="tweets">
|
31
|
+
<div class="item">
|
32
|
+
<span class="text"></span>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<input type="text" id="updateText">
|
37
|
+
<input type="submit" value="Update →" id="updateSubmit">
|
38
|
+
</body>
|
39
|
+
</html>
|
data/examples/users.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Binders
|
2
|
+
class Users < Bowline::Binders::Collection
|
3
|
+
class << self
|
4
|
+
# self.items is a special method
|
5
|
+
# Basically it'll update users on the client side
|
6
|
+
def index
|
7
|
+
self.items = User.all
|
8
|
+
end
|
9
|
+
|
10
|
+
def admins
|
11
|
+
self.items = User.admins.all
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def update(attrs)
|
16
|
+
if @item.update_attributes(attrs)
|
17
|
+
flash[:notice] = "Successfully updated"
|
18
|
+
else
|
19
|
+
flash[:notice] = "Errors updating users"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def highlight
|
24
|
+
# Calls $('user_1').highlight()
|
25
|
+
self.element.highlight
|
26
|
+
end
|
27
|
+
|
28
|
+
# Overrides charge on user
|
29
|
+
def charge!
|
30
|
+
# calls charge! on model (i.e. do sql commit )
|
31
|
+
self.item.charge!
|
32
|
+
# Now gui stuff
|
33
|
+
flash[:notice] = "Successfully charged"
|
34
|
+
highlight
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/bowline.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Bowline
|
2
|
+
VERSION = '0.1.6'
|
3
|
+
|
4
|
+
# The raw JavaScript window object
|
5
|
+
def self.js
|
6
|
+
if defined?($app_window)
|
7
|
+
$app_window
|
8
|
+
else
|
9
|
+
Class.new {
|
10
|
+
def self.method_missing(*a)
|
11
|
+
Bowline.logger.info "Sending to Window: #{a.inspect}"
|
12
|
+
self
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Change which page we're on
|
19
|
+
def self.show_view(name)
|
20
|
+
js.window.location = "app://public/#{name}.html"
|
21
|
+
end
|
22
|
+
|
23
|
+
class Base
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
28
|
+
|
29
|
+
require 'bowline/ext/object'
|
30
|
+
require 'bowline/ext/array'
|
31
|
+
require 'bowline/ext/class'
|
32
|
+
require 'bowline/ext/string'
|
33
|
+
|
34
|
+
require 'bowline/gem_dependency'
|
35
|
+
require 'bowline/initializer'
|
36
|
+
|
37
|
+
require 'bowline/jquery'
|
38
|
+
require 'bowline/observer'
|
39
|
+
|
40
|
+
require 'bowline/binders'
|
41
|
+
require 'bowline/binders/collection'
|
42
|
+
require 'bowline/binders/singleton'
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module Bowline
|
2
|
+
module Binders
|
3
|
+
class Base
|
4
|
+
cattr_accessor :params
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# See Bowline::js
|
8
|
+
def js
|
9
|
+
Bowline::js
|
10
|
+
end
|
11
|
+
|
12
|
+
# Equivalent of the 'jQuery' function
|
13
|
+
def jquery
|
14
|
+
@@jquery ||= JQuery.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# See the Observer class
|
18
|
+
def observer
|
19
|
+
@@observer ||= Observer.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# See Bowline::logger
|
23
|
+
def logger
|
24
|
+
Bowline::logger
|
25
|
+
end
|
26
|
+
|
27
|
+
# See Bowline::show_view
|
28
|
+
def show_view(*args)
|
29
|
+
Bowline::show_view(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def params=(p)
|
33
|
+
case p
|
34
|
+
when String
|
35
|
+
# Params comes in a string (since it's a
|
36
|
+
# serialized form) - we need to make it into
|
37
|
+
# a nestled hash.
|
38
|
+
# Stolen from Ramaze
|
39
|
+
m = proc {|_,o,n|o.merge(n,&m)}
|
40
|
+
@@params = params.inject({}) do |hash, (key, value)|
|
41
|
+
parts = key.split(/[\]\[]+/)
|
42
|
+
hash.merge(parts.reverse.inject(value) { |x, i| {i => x} }, &m)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
@@params = p
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def setup(d)
|
50
|
+
@@elements ||= []
|
51
|
+
@@elements << d
|
52
|
+
self.item_sync!
|
53
|
+
end
|
54
|
+
|
55
|
+
def instance(el)
|
56
|
+
self.new(el).method(:send)
|
57
|
+
end
|
58
|
+
|
59
|
+
# todo - flash?
|
60
|
+
|
61
|
+
def inherited(child)
|
62
|
+
return if self == Bowline::Binders::Base
|
63
|
+
return if child == Bowline::Binders::Singleton
|
64
|
+
return if child == Bowline::Binders::Collection
|
65
|
+
name = child.name.underscore
|
66
|
+
name = name.split('/').last
|
67
|
+
js.send("bowline_#{name}_setup=", child.method(:setup))
|
68
|
+
js.send("bowline_#{name}_instance=", child.method(:instance))
|
69
|
+
js.send("bowline_#{name}=", child.method(:send))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :element
|
74
|
+
attr_reader :item
|
75
|
+
|
76
|
+
# Todo
|
77
|
+
# We want initialize method to take
|
78
|
+
# no argument, and for every item in items
|
79
|
+
# to have initialize called on startup,
|
80
|
+
# so they can set up event handlers etc
|
81
|
+
def self.new(element, *args) #:nodoc:
|
82
|
+
allocate.instance_eval do
|
83
|
+
# jQuery element
|
84
|
+
@element = element
|
85
|
+
# Calling chain.js 'item' function
|
86
|
+
@item = element.item()
|
87
|
+
if @item
|
88
|
+
@item.with_indifferent_access
|
89
|
+
# If possible, find Ruby object
|
90
|
+
if @item[:id] && respond_to?(:find)
|
91
|
+
@item = find(@item[:id])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
initialize(*args)
|
96
|
+
self
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Trigger jQuery events on this element
|
101
|
+
def trigger(event, data = nil)
|
102
|
+
self.element.trigger(event, data)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Bind event to element:
|
106
|
+
# bind(:click) { puts "element clicked" }
|
107
|
+
# todo - two events with the same item/event overwrite each other
|
108
|
+
# todo - need initalize method on class - so we can set events there
|
109
|
+
def bind(event, method_name, &block)
|
110
|
+
event_name = [event, item_id].join(":")
|
111
|
+
callback = block
|
112
|
+
callback ||= begin
|
113
|
+
method_name.is_a?(Method) ?
|
114
|
+
method_name : method(method_name)
|
115
|
+
end
|
116
|
+
self.observer.append(event_name, callback)
|
117
|
+
self.element.bind(
|
118
|
+
event.to_s,
|
119
|
+
event_name,
|
120
|
+
self.observer.method(:call)
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
def click(method_name = nil, &block)
|
125
|
+
bind(:click, method, &block)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Raw DOM element
|
129
|
+
def dom
|
130
|
+
self.element[0]
|
131
|
+
end
|
132
|
+
|
133
|
+
# Shortcut methods
|
134
|
+
|
135
|
+
# See self.class.show_view
|
136
|
+
def show_view(*args)
|
137
|
+
self.class.show_view(*args)
|
138
|
+
end
|
139
|
+
|
140
|
+
# See self.class.js
|
141
|
+
def js
|
142
|
+
self.class.js
|
143
|
+
end
|
144
|
+
alias :page :js
|
145
|
+
|
146
|
+
# See self.class.jquery
|
147
|
+
def jquery
|
148
|
+
self.class.jquery
|
149
|
+
end
|
150
|
+
|
151
|
+
# See self.class.observer
|
152
|
+
def observer
|
153
|
+
self.class.observer
|
154
|
+
end
|
155
|
+
|
156
|
+
# See self.class.logger
|
157
|
+
def logger
|
158
|
+
self.class.logger
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
# This is just a unique identifier
|
163
|
+
# for the item - and isn't
|
164
|
+
# used in the dom
|
165
|
+
def item_id
|
166
|
+
if item.respond_to?(:dom_id)
|
167
|
+
item.dom_id
|
168
|
+
else
|
169
|
+
[
|
170
|
+
item.id,
|
171
|
+
self.class.name.underscore
|
172
|
+
].join("_")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bowline
|
2
|
+
module Binders
|
3
|
+
class Collection < Base
|
4
|
+
cattr_accessor :items
|
5
|
+
class << self
|
6
|
+
def items=(args)
|
7
|
+
@@items = args
|
8
|
+
self.item_sync!
|
9
|
+
@@items
|
10
|
+
end
|
11
|
+
|
12
|
+
def item_sync!
|
13
|
+
return unless @@items && @@elements
|
14
|
+
@@elements.each {|i|
|
15
|
+
i.updateCollection(@@items.to_js)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(id)
|
20
|
+
@@items.find {|item|
|
21
|
+
item.id == id if item.respond_to?(:id)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|