bowline 0.3.9 → 0.4.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/README.txt +163 -16
- data/VERSION +1 -1
- data/assets/jquery.bowline.js +51 -13
- data/bowline.gemspec +3 -9
- data/lib/bowline/binders.rb +43 -25
- data/lib/bowline/binders/collection.rb +37 -8
- data/lib/bowline/binders/singleton.rb +4 -1
- data/lib/bowline/dependencies/lib/dependencies.rb +0 -4
- data/lib/bowline/dependencies/lib/ext/rubygems.rb +7 -16
- data/lib/bowline/ext/array.rb +2 -2
- data/lib/bowline/ext/object.rb +1 -1
- data/lib/bowline/generators/application.rb +2 -0
- data/lib/bowline/tasks/app.rake +15 -12
- data/lib/bowline/tasks/gems.rake +2 -0
- data/lib/bowline/version.rb +2 -2
- data/templates/config/boot.rb +8 -2
- metadata +3 -9
- data/lib/bowline/dependencies/Rakefile +0 -10
- data/lib/bowline/dependencies/init.rb +0 -41
- data/lib/bowline/dependencies/lib/dependencies/reader.rb +0 -30
- data/lib/bowline/dependencies/lib/template/app_script.rb +0 -31
- data/lib/bowline/dependencies/spec/spec.opts +0 -4
- data/lib/bowline/dependencies/tasks/dependencies.rake +0 -164
data/README.txt
CHANGED
@@ -12,7 +12,26 @@ Ruby desktop application framework
|
|
12
12
|
* Uses Webkit
|
13
13
|
* View in HTML/JavaScript
|
14
14
|
* Binding between HTML & Ruby
|
15
|
-
*
|
15
|
+
* Cross platform (only osx atm)
|
16
|
+
|
17
|
+
= INTRODUCTION
|
18
|
+
|
19
|
+
If you've ever wished creating a desktop application was as simple
|
20
|
+
as creating a Rails website you'll be interested in Bowline.
|
21
|
+
Bowline is a Ruby GUI framework. You can design and build your
|
22
|
+
applications in an agile way, deploying them cross platform.
|
23
|
+
|
24
|
+
Bowline lets you take your existing skills and apply them to the desktop.
|
25
|
+
You can write apps in HTML/JavaScript/Ruby without having to worry about
|
26
|
+
different platforms or a complex GUI API.
|
27
|
+
|
28
|
+
Compared to existing Ruby desktop frameworks, such as Shoes, Bowline's strengths
|
29
|
+
are its adherence to MVC and use of HTML/JavaScript. We think that, although Ruby is
|
30
|
+
a great language for the backend, the view should be written in languages designed
|
31
|
+
for that purpose, HTML and JavaScript.
|
32
|
+
|
33
|
+
Bowline also takes inspiration from Flex through its binders. Bowline will bind
|
34
|
+
up Ruby and HTML - letting you concentrate on the more interesting things.
|
16
35
|
|
17
36
|
= CONTACT
|
18
37
|
|
@@ -20,34 +39,132 @@ info@eribium.org
|
|
20
39
|
http://eribium.org
|
21
40
|
http://twitter.com/maccman
|
22
41
|
|
23
|
-
=
|
42
|
+
= INSTALLATION
|
24
43
|
|
25
44
|
Install the Titanium SDK:
|
26
|
-
http://www.appcelerator.com/products/download-titanium/download/
|
45
|
+
http://www.appcelerator.com/products/download-titanium/download/
|
27
46
|
|
28
47
|
Install the gem:
|
29
48
|
>> sudo gem install maccman-bowline --source http://gems.github.com
|
30
49
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
50
|
+
= USAGE
|
51
|
+
|
52
|
+
See the Twitter example at the end of this document,
|
53
|
+
or browse the completed version here:
|
54
|
+
http://github.com/maccman/bowline-twitter
|
35
55
|
|
36
|
-
|
37
|
-
Add your Twitter credentials to tweets.rb - in this simple example they're not dynamic.
|
56
|
+
= GENERATING
|
38
57
|
|
39
|
-
|
58
|
+
Using the bowline-gen binary (installed with Bowline) you can generate the following things:
|
59
|
+
app Generates a new application.
|
60
|
+
binder Generates a new binder, either a collection one, or a singleton one.
|
61
|
+
helper Generates a new helper.
|
62
|
+
migration Generates a new database migration.
|
63
|
+
model Generates a new model.
|
64
|
+
|
65
|
+
Run 'bowline-gen --help' for more information.
|
40
66
|
|
41
|
-
|
42
|
-
>> sudo gem install twitter
|
67
|
+
= COMMANDS
|
43
68
|
|
44
|
-
|
45
|
-
|
69
|
+
App console:
|
70
|
+
>> script/console
|
46
71
|
|
47
|
-
|
72
|
+
Run application:
|
48
73
|
>> script/run
|
49
74
|
|
50
|
-
|
75
|
+
= BINDERS
|
76
|
+
|
77
|
+
Binders are the core of Bowline, they're classes that you can bind HTML to.
|
78
|
+
Binders contain data. If you modify the binder's data the HTML automatically updates.
|
79
|
+
It's a one way relationship though.
|
80
|
+
|
81
|
+
You can think of binders as similar to controllers in Rails.
|
82
|
+
|
83
|
+
There are two types of binders, singleton and collection.
|
84
|
+
Singleton binders are for a single data entity, such as the current logged in user.
|
85
|
+
And it goes without saying that collection binders are for an array of data.
|
86
|
+
|
87
|
+
You can create a collection binder like this:
|
88
|
+
>> bowline-gen binder users --type collection
|
89
|
+
|
90
|
+
Which will generate code a bit like this:
|
91
|
+
module Binders
|
92
|
+
class Users < Bowline::Collection
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Now, in the view you can bind HTML to this collection, by
|
97
|
+
using the following javascript:
|
98
|
+
$('#users').bowline('users');
|
99
|
+
|
100
|
+
You should probably become familiar with Chain.js (which bowline uses for binding): http://wiki.github.com/raid-ox/chain.js/
|
101
|
+
|
102
|
+
Suffice to say, the HTML looks a bit like this:
|
103
|
+
<div id="users">
|
104
|
+
<div class="item">
|
105
|
+
<span class="name"></span>
|
106
|
+
<span class="email"></span>
|
107
|
+
<a href="#" class="destroy">Delete</a>
|
108
|
+
</div>
|
109
|
+
</div>
|
110
|
+
|
111
|
+
Now, were you to have a user object, you could do something like
|
112
|
+
this to update the HTML.
|
113
|
+
|
114
|
+
Binders::Users.items = [User.first]
|
115
|
+
|
116
|
+
= METHODS IN BINDERS
|
117
|
+
|
118
|
+
You can call both class and instance methods of the binders.
|
119
|
+
Following on from the above example with 'users', you could call a class
|
120
|
+
method called 'admins' on the users binder like so:
|
121
|
+
|
122
|
+
$('#users').invoke('admins')
|
123
|
+
|
124
|
+
It's the same syntax for invoking instance methods, just called
|
125
|
+
on one of the individual users:
|
126
|
+
|
127
|
+
$('#users div:first').invoke('instance_method', 'arg1')
|
128
|
+
|
129
|
+
= HELPERS
|
130
|
+
|
131
|
+
Helpers are similar to helpers in Rails - they're helper methods for the view which
|
132
|
+
don't need a full blown binder to cater for.
|
133
|
+
|
134
|
+
You can call helpers with JavaScript like so:
|
135
|
+
$.bowline.helper('name', 'arg1', ['arg2'])
|
136
|
+
|
137
|
+
= MODELS
|
138
|
+
|
139
|
+
Bowline supports ActiveRecord and the Sqlite3 database.
|
140
|
+
The packaging for databases is still in development though.
|
141
|
+
|
142
|
+
= THEMES
|
143
|
+
|
144
|
+
The Cappuccino Aristo theme has been specially customized for Bowline, you can see
|
145
|
+
examples of it in the Twitter client, and find it here:
|
146
|
+
http://github.com/maccman/aristo
|
147
|
+
|
148
|
+
= TITANIUM
|
149
|
+
|
150
|
+
Bowline is built on top of Titanium, an open source cross platform framework for desktop apps.
|
151
|
+
You can use any of the Titanium api methods in Ruby and JavaScript, like this:
|
152
|
+
Titanium.UI.currentWindow.close
|
153
|
+
|
154
|
+
Site: http://www.appcelerator.com/products/titanium-desktop/
|
155
|
+
API Docs: http://www.codestrong.com/titanium/api/
|
156
|
+
|
157
|
+
= BUILDING
|
158
|
+
|
159
|
+
Once your app is complete, you should run the following command
|
160
|
+
to make sure all the gems required (including Bowline) have been vendorised:
|
161
|
+
rake gems:sync
|
162
|
+
|
163
|
+
Then, run:
|
164
|
+
rake app
|
165
|
+
|
166
|
+
You can only build distributions for your local platform, but
|
167
|
+
using the Titanium Developer app you can build on all three platforms.
|
51
168
|
|
52
169
|
= EXAMPLES
|
53
170
|
|
@@ -137,3 +254,33 @@ Usage for a collection (of users):
|
|
137
254
|
<a href="#" id="showAdmins">Show admins</a>
|
138
255
|
</body>
|
139
256
|
</html>
|
257
|
+
|
258
|
+
= Building a basic Twitter client
|
259
|
+
|
260
|
+
Install the Titanium SDK:
|
261
|
+
http://www.appcelerator.com/products/download-titanium/download/
|
262
|
+
|
263
|
+
Install the gem:
|
264
|
+
>> sudo gem install maccman-bowline --source http://gems.github.com
|
265
|
+
|
266
|
+
Run the app/binder generators:
|
267
|
+
>> bowline-gen app bowline_twitter
|
268
|
+
>> cd bowline_twitter
|
269
|
+
>> bowline-gen binder tweets
|
270
|
+
|
271
|
+
Copy tweets.rb from examples to app/binders/tweets.rb
|
272
|
+
Add your Twitter credentials to tweets.rb - in this simple example they're not dynamic.
|
273
|
+
|
274
|
+
Copy twitter.html from examples to public/index.html
|
275
|
+
|
276
|
+
Install the Twitter gem:
|
277
|
+
>> sudo gem install twitter
|
278
|
+
|
279
|
+
Add the Twitter gem to config/environment.rb:
|
280
|
+
config.gem "twitter"
|
281
|
+
|
282
|
+
run:
|
283
|
+
>> script/run
|
284
|
+
|
285
|
+
That's it. You can see a snazzed up version here:
|
286
|
+
http://github.com/maccman/bowline-twitter
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.6
|
data/assets/jquery.bowline.js
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
(function($){
|
2
2
|
var init = false;
|
3
|
+
var TI = Titanium;
|
4
|
+
var UI = TI.UI;
|
5
|
+
var mainWin = UI.mainWindow.window;
|
3
6
|
|
4
7
|
$.bowline = {
|
5
8
|
setup: function(name, el){
|
6
|
-
var rb = eval("bowline_" + name + "_setup");
|
9
|
+
var rb = mainWin.eval("bowline_" + name + "_setup");
|
7
10
|
if(!rb) throw 'Unknown class';
|
8
11
|
rb(el);
|
9
12
|
},
|
10
13
|
|
11
14
|
klass: function(name){
|
12
|
-
var rb = eval("bowline_" + name);
|
15
|
+
var rb = mainWin.eval("bowline_" + name);
|
13
16
|
if(!rb) throw 'Unknown class';
|
14
17
|
return rb;
|
15
18
|
},
|
16
19
|
|
17
20
|
instance: function(name, el){
|
18
|
-
var rb = eval("bowline_" + name + "_instance");
|
21
|
+
var rb = mainWin.eval("bowline_" + name + "_instance");
|
19
22
|
if(!rb) throw 'Unknown class';
|
20
23
|
return rb(el);
|
21
24
|
},
|
@@ -28,12 +31,43 @@
|
|
28
31
|
)
|
29
32
|
);
|
30
33
|
},
|
34
|
+
|
35
|
+
load: function(){
|
36
|
+
$(function(){
|
37
|
+
setTimeout(function(){
|
38
|
+
$(document.body).trigger('loading.bowline');
|
39
|
+
var script = $("<script />");
|
40
|
+
script.attr('type', 'text/ruby');
|
41
|
+
script.attr('src', '../script/init');
|
42
|
+
$('head').append(script);
|
43
|
+
}, 100);
|
44
|
+
});
|
45
|
+
},
|
31
46
|
|
32
47
|
ready: function(func){
|
33
48
|
if(init) return func();
|
34
49
|
$(document).bind('loaded.bowline', func);
|
35
50
|
},
|
36
51
|
|
52
|
+
dialog: function(name, options, callback){
|
53
|
+
if(!callback && typeof(options) == 'function') {
|
54
|
+
callback = options;
|
55
|
+
options = {};
|
56
|
+
}
|
57
|
+
$.extend(options, {
|
58
|
+
'url': 'app://public/' + name + '.html',
|
59
|
+
'height': 200,
|
60
|
+
'width': 350,
|
61
|
+
'transparency': 0.9,
|
62
|
+
'resizable': false,
|
63
|
+
'usingChrome': false,
|
64
|
+
'onclose': function(res){
|
65
|
+
if(callback) callback(res);
|
66
|
+
}
|
67
|
+
});
|
68
|
+
return Titanium.UI.showDialog(options);
|
69
|
+
},
|
70
|
+
|
37
71
|
setupForms: function(){
|
38
72
|
// $('form').bind('submit', function(e){
|
39
73
|
// var src = $(this).attr('src').split('.');
|
@@ -86,7 +120,16 @@
|
|
86
120
|
var name = $(this).item('root').data('bowline');
|
87
121
|
var func = $.bowline.instance(name, $(this));
|
88
122
|
}
|
89
|
-
|
123
|
+
var args = $.makeArray(arguments);
|
124
|
+
var opts = args.pop();
|
125
|
+
if(typeof(opts) == "object" && opts.async){
|
126
|
+
setTimeout(function(){
|
127
|
+
func.apply(func, args);
|
128
|
+
}, 100);
|
129
|
+
} else {
|
130
|
+
args.push(opts);
|
131
|
+
func.apply(func, args);
|
132
|
+
}
|
90
133
|
} else {
|
91
134
|
throw 'Chain not active';
|
92
135
|
}
|
@@ -106,13 +149,8 @@
|
|
106
149
|
$(this).trigger('update.bowline');
|
107
150
|
};
|
108
151
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
script.attr('type', 'text/ruby');
|
114
|
-
script.attr('src', '../script/init');
|
115
|
-
$('head').append(script);
|
116
|
-
}, 100);
|
117
|
-
})
|
152
|
+
// main window
|
153
|
+
if(UI.currentWindow.equals(UI.mainWindow)){
|
154
|
+
$.bowline.load();
|
155
|
+
}
|
118
156
|
})(jQuery)
|
data/bowline.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{bowline}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.4.6"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Alex MacCaw"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-08-05}
|
10
10
|
s.default_executable = %q{bowline-gen}
|
11
11
|
s.description = %q{Ruby/JS GUI framework}
|
12
12
|
s.email = %q{alex@leadthinking.com}
|
@@ -42,17 +42,11 @@ Gem::Specification.new do |s|
|
|
42
42
|
"lib/bowline/dependencies/FAQ.markdown",
|
43
43
|
"lib/bowline/dependencies/MIT-LICENSE",
|
44
44
|
"lib/bowline/dependencies/README.markdown",
|
45
|
-
"lib/bowline/dependencies/Rakefile",
|
46
45
|
"lib/bowline/dependencies/TODO.markdown",
|
47
|
-
"lib/bowline/dependencies/init.rb",
|
48
46
|
"lib/bowline/dependencies/lib/dependencies.rb",
|
49
47
|
"lib/bowline/dependencies/lib/dependencies/dependency.rb",
|
50
|
-
"lib/bowline/dependencies/lib/dependencies/reader.rb",
|
51
48
|
"lib/bowline/dependencies/lib/dependencies/repository.rb",
|
52
49
|
"lib/bowline/dependencies/lib/ext/rubygems.rb",
|
53
|
-
"lib/bowline/dependencies/lib/template/app_script.rb",
|
54
|
-
"lib/bowline/dependencies/spec/spec.opts",
|
55
|
-
"lib/bowline/dependencies/tasks/dependencies.rake",
|
56
50
|
"lib/bowline/ext/array.rb",
|
57
51
|
"lib/bowline/ext/class.rb",
|
58
52
|
"lib/bowline/ext/object.rb",
|
@@ -96,7 +90,7 @@ Gem::Specification.new do |s|
|
|
96
90
|
s.homepage = %q{http://github.com/maccman/bowline}
|
97
91
|
s.rdoc_options = ["--charset=UTF-8"]
|
98
92
|
s.require_paths = ["lib"]
|
99
|
-
s.rubygems_version = %q{1.3.
|
93
|
+
s.rubygems_version = %q{1.3.5}
|
100
94
|
s.summary = %q{Bowline GUI framework}
|
101
95
|
s.test_files = [
|
102
96
|
"examples/account.rb",
|
data/lib/bowline/binders.rb
CHANGED
@@ -30,8 +30,8 @@ module Bowline
|
|
30
30
|
def params
|
31
31
|
@params
|
32
32
|
end
|
33
|
-
|
34
|
-
def params=(p)
|
33
|
+
|
34
|
+
def params=(p) #:nodoc:
|
35
35
|
case p
|
36
36
|
when String
|
37
37
|
# Params comes in a string (since it's a
|
@@ -46,18 +46,35 @@ module Bowline
|
|
46
46
|
@params = p
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
50
|
-
def
|
49
|
+
|
50
|
+
def elements
|
51
|
+
@elements
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup(d) #:nodoc:
|
51
55
|
@elements ||= []
|
52
56
|
@elements << d
|
53
57
|
self.item_sync!
|
54
58
|
end
|
59
|
+
|
60
|
+
def trigger(event, data = nil)
|
61
|
+
@elements ||= []
|
62
|
+
@elements.map {|e|
|
63
|
+
e.trigger(format_event(event), data)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def loading(&block)
|
68
|
+
trigger(:loading, true)
|
69
|
+
yield
|
70
|
+
trigger(:loading, false)
|
71
|
+
end
|
55
72
|
|
56
|
-
def instance(el)
|
73
|
+
def instance(el) #:nodoc:
|
57
74
|
self.new(el).method(:send)
|
58
75
|
end
|
59
76
|
|
60
|
-
def inherited(child)
|
77
|
+
def inherited(child) #:nodoc:
|
61
78
|
return if self == Bowline::Binders::Base
|
62
79
|
return if child == Bowline::Binders::Singleton
|
63
80
|
return if child == Bowline::Binders::Collection
|
@@ -66,34 +83,35 @@ module Bowline
|
|
66
83
|
js.send("bowline_#{name}_setup=", child.method(:setup))
|
67
84
|
js.send("bowline_#{name}_instance=", child.method(:instance))
|
68
85
|
js.send("bowline_#{name}=", child.method(:send))
|
69
|
-
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def format_event(name) #:nodoc:
|
89
|
+
name.is_a?(Array) ?
|
90
|
+
name.join('.') :
|
91
|
+
name.to_s
|
92
|
+
end
|
70
93
|
end
|
71
94
|
|
72
95
|
attr_reader :element
|
73
96
|
attr_reader :item
|
74
97
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# If possible, find Ruby object
|
84
|
-
if @item[:id] && respond_to?(:find)
|
85
|
-
@item = find(@item[:id])
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
initialize(*args)
|
90
|
-
self
|
98
|
+
def initialize(element, *args) #:nodoc:
|
99
|
+
# jQuery element
|
100
|
+
@element = element
|
101
|
+
# Calling chain.js 'item' function
|
102
|
+
@item = element.item()
|
103
|
+
if @item
|
104
|
+
# If possible, find Ruby object
|
105
|
+
@item = self.class.find(@item._id.to_i)
|
91
106
|
end
|
92
|
-
end
|
107
|
+
end
|
93
108
|
|
94
109
|
# Trigger jQuery events on this element
|
95
110
|
def trigger(event, data = nil)
|
96
|
-
self.element.trigger(
|
111
|
+
self.element.trigger(
|
112
|
+
self.class.format_event(event),
|
113
|
+
data
|
114
|
+
)
|
97
115
|
end
|
98
116
|
|
99
117
|
# Raw DOM element
|
@@ -1,27 +1,56 @@
|
|
1
1
|
module Bowline
|
2
2
|
module Binders
|
3
3
|
class Collection < Base
|
4
|
+
class ItemsProxy
|
5
|
+
def initialize(&block)
|
6
|
+
@callback = block
|
7
|
+
@items = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def real
|
11
|
+
@items
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(*args, &block)
|
15
|
+
diff = @items.hash
|
16
|
+
res = @items.send(*args, &block)
|
17
|
+
if diff != @items.hash
|
18
|
+
@callback.call
|
19
|
+
end
|
20
|
+
res
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
4
24
|
class << self
|
5
25
|
def items=(args)
|
6
|
-
|
7
|
-
|
8
|
-
|
26
|
+
if args
|
27
|
+
items.replace(args)
|
28
|
+
else
|
29
|
+
items.clear
|
30
|
+
end
|
9
31
|
end
|
10
32
|
|
11
33
|
def items
|
12
|
-
@items ||=
|
34
|
+
@items ||= ItemsProxy.new {
|
35
|
+
self.item_sync!
|
36
|
+
}
|
13
37
|
end
|
14
38
|
|
15
39
|
def item_sync!
|
16
40
|
return unless @items && @elements
|
17
|
-
@
|
18
|
-
|
41
|
+
value = @items.real.map {|item|
|
42
|
+
hash = item.to_js
|
43
|
+
hash.merge!({:_id => item.__id__})
|
44
|
+
hash.stringify_keys
|
45
|
+
}
|
46
|
+
@elements.each {|i|
|
47
|
+
i.updateCollection(value)
|
19
48
|
}
|
20
49
|
end
|
21
50
|
|
22
51
|
def find(id)
|
23
|
-
@items.find {|item|
|
24
|
-
item.
|
52
|
+
@items.real.find {|item|
|
53
|
+
item.__id__ == id
|
25
54
|
}
|
26
55
|
end
|
27
56
|
end
|
@@ -13,9 +13,12 @@ module Bowline
|
|
13
13
|
|
14
14
|
def item_sync!
|
15
15
|
return unless @item && @elements
|
16
|
+
value = @item.to_js
|
17
|
+
value.merge!({:_id => @item.__id__})
|
18
|
+
value.stringify_keys!
|
16
19
|
# Call the chain.js function 'item' on elements
|
17
20
|
@elements.each {|i|
|
18
|
-
i.updateSingleton(
|
21
|
+
i.updateSingleton(value)
|
19
22
|
}
|
20
23
|
end
|
21
24
|
|
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'rubygems'
|
3
|
+
require 'rubygems/uninstaller'
|
3
4
|
require 'rubygems/dependency_installer'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
FileUtils.cp(File.join(File.dirname(__FILE__), "common.rb"),
|
9
|
-
File.join(installer.bin_dir, "common.rb"))
|
10
|
-
end
|
6
|
+
# We only require this in 'rake gems:sync' since
|
7
|
+
# it contains some advanced Gem features that aren't
|
8
|
+
# available in earlier versions, such as pre_install_hooks
|
11
9
|
|
10
|
+
Gem.pre_install_hooks.push(proc do |installer|
|
12
11
|
name = installer.spec.name
|
13
12
|
|
14
13
|
puts "+ #{name}"
|
@@ -43,7 +42,7 @@ class ::Gem::Uninstaller
|
|
43
42
|
uninstaller = Gem::Uninstaller.new(
|
44
43
|
name,
|
45
44
|
:version => "#{op} #{version}",
|
46
|
-
:install_dir => Dir.pwd
|
45
|
+
:install_dir => File.join(Dir.pwd, "vendor", "gems"),
|
47
46
|
:all => true,
|
48
47
|
:ignore => true,
|
49
48
|
:executables => true
|
@@ -103,14 +102,6 @@ class ::Gem::SpecFetcher
|
|
103
102
|
end
|
104
103
|
end
|
105
104
|
|
106
|
-
class ::Gem::Installer
|
107
|
-
def app_script_text(bin_file_name)
|
108
|
-
template = File.read(File.join(File.dirname(__FILE__), '..', 'template' , "app_script.rb"))
|
109
|
-
erb = ERB.new(template)
|
110
|
-
erb.result(binding)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
105
|
class ::Gem::Specification
|
115
106
|
def recursive_dependencies(from, index = Gem.source_index)
|
116
107
|
specs = self.runtime_dependencies.map do |dep|
|
@@ -122,4 +113,4 @@ class ::Gem::Specification
|
|
122
113
|
end
|
123
114
|
specs + specs.map {|s| s.recursive_dependencies(self, index)}.flatten.uniq
|
124
115
|
end
|
125
|
-
end
|
116
|
+
end
|
data/lib/bowline/ext/array.rb
CHANGED
data/lib/bowline/ext/object.rb
CHANGED
data/lib/bowline/tasks/app.rake
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
namespace :app do
|
3
3
|
task :configure => :environment do
|
4
|
-
|
5
|
-
|
4
|
+
config_path = File.join(APP_ROOT, 'config')
|
6
5
|
conf = Bowline.configuration
|
7
6
|
|
8
7
|
# Titanium complains about whitespace
|
@@ -66,8 +65,7 @@ tiprocess:0.4.4
|
|
66
65
|
</ti:app>
|
67
66
|
EOF
|
68
67
|
|
69
|
-
FileUtils.
|
70
|
-
FileUtils.cd(build_path) do
|
68
|
+
FileUtils.cd(config_path) do
|
71
69
|
File.open('manifest', 'w+') {|f| f.write manifest }
|
72
70
|
File.open('tiapp.xml', 'w+') {|f| f.write tiapp }
|
73
71
|
end
|
@@ -75,14 +73,19 @@ tiprocess:0.4.4
|
|
75
73
|
|
76
74
|
desc "Bundles up app into executables"
|
77
75
|
task :bundle do
|
78
|
-
build_path
|
79
|
-
app_path
|
80
|
-
|
81
|
-
tiapp = File.join(build_path, 'tiapp.xml')
|
82
|
-
manifest = File.join(build_path, 'manifest')
|
76
|
+
build_path = File.join(APP_ROOT, 'build')
|
77
|
+
app_path = File.join(build_path, 'app')
|
78
|
+
config_path = File.join(APP_ROOT, 'config')
|
83
79
|
|
84
|
-
|
80
|
+
tiapp = File.join(config_path, 'tiapp.xml')
|
81
|
+
manifest = File.join(config_path, 'manifest')
|
82
|
+
env = File.join(config_path, 'environment.rb')
|
83
|
+
|
84
|
+
if !File.exists?(tiapp) ||
|
85
|
+
!File.exists?(manifest)
|
85
86
|
Rake::Task['app:configure'].invoke
|
87
|
+
elsif File.mtime(tiapp) < File.mtime(env)
|
88
|
+
puts "You may need to run 'rake app:configure'"
|
86
89
|
end
|
87
90
|
|
88
91
|
FileUtils.rm_rf(app_path)
|
@@ -116,7 +119,7 @@ tiprocess:0.4.4
|
|
116
119
|
build_path = File.join(APP_ROOT, 'build')
|
117
120
|
app_path = File.join(build_path, 'app')
|
118
121
|
|
119
|
-
ti_path = ENV['TIPATH']
|
122
|
+
ti_path = ENV['TIPATH'] ? ENV['TIPATH'].dup : begin
|
120
123
|
if RUBY_PLATFORM =~ /darwin/
|
121
124
|
'/Library/Application Support/Titanium'
|
122
125
|
elsif RUBY_PLATFORM =~ /win/
|
@@ -140,7 +143,7 @@ tiprocess:0.4.4
|
|
140
143
|
ti_path.gsub!(' ', '\ ')
|
141
144
|
ti_lib_path.gsub!(' ', '\ ')
|
142
145
|
|
143
|
-
command = []
|
146
|
+
command = ['python']
|
144
147
|
command << File.join(ti_lib_path, "tibuild.py")
|
145
148
|
command << "-d #{build_path}"
|
146
149
|
command << "-s #{ti_path}"
|
data/lib/bowline/tasks/gems.rake
CHANGED
data/lib/bowline/version.rb
CHANGED
data/templates/config/boot.rb
CHANGED
@@ -3,8 +3,14 @@
|
|
3
3
|
|
4
4
|
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..")) unless defined?(APP_ROOT)
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
edge_path = File.join(APP_ROOT, *%w{vendor bowline lib bowline.rb})
|
7
|
+
|
8
|
+
if File.exist?(edge_path)
|
9
|
+
bowline_path = edge_path
|
10
|
+
else
|
11
|
+
gems_path = File.join(APP_ROOT, *%w{vendor gems gems})
|
12
|
+
bowline_path = Dir[File.join(gems_path, *%w{{maccman-bowline*,bowline*} lib bowline.rb})][-1]
|
13
|
+
end
|
8
14
|
|
9
15
|
if bowline_path
|
10
16
|
require bowline_path
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bowline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex MacCaw
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-05 00:00:00 +01:00
|
13
13
|
default_executable: bowline-gen
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -68,17 +68,11 @@ files:
|
|
68
68
|
- lib/bowline/dependencies/FAQ.markdown
|
69
69
|
- lib/bowline/dependencies/MIT-LICENSE
|
70
70
|
- lib/bowline/dependencies/README.markdown
|
71
|
-
- lib/bowline/dependencies/Rakefile
|
72
71
|
- lib/bowline/dependencies/TODO.markdown
|
73
|
-
- lib/bowline/dependencies/init.rb
|
74
72
|
- lib/bowline/dependencies/lib/dependencies.rb
|
75
73
|
- lib/bowline/dependencies/lib/dependencies/dependency.rb
|
76
|
-
- lib/bowline/dependencies/lib/dependencies/reader.rb
|
77
74
|
- lib/bowline/dependencies/lib/dependencies/repository.rb
|
78
75
|
- lib/bowline/dependencies/lib/ext/rubygems.rb
|
79
|
-
- lib/bowline/dependencies/lib/template/app_script.rb
|
80
|
-
- lib/bowline/dependencies/spec/spec.opts
|
81
|
-
- lib/bowline/dependencies/tasks/dependencies.rake
|
82
76
|
- lib/bowline/ext/array.rb
|
83
77
|
- lib/bowline/ext/class.rb
|
84
78
|
- lib/bowline/ext/object.rb
|
@@ -142,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
136
|
requirements: []
|
143
137
|
|
144
138
|
rubyforge_project:
|
145
|
-
rubygems_version: 1.3.
|
139
|
+
rubygems_version: 1.3.5
|
146
140
|
signing_key:
|
147
141
|
specification_version: 3
|
148
142
|
summary: Bowline GUI framework
|
@@ -1,41 +0,0 @@
|
|
1
|
-
unless $block_dependencies_plugin_init
|
2
|
-
|
3
|
-
require File.join(File.dirname(__FILE__), 'lib', 'dependencies')
|
4
|
-
|
5
|
-
Gem.clear_paths
|
6
|
-
Gem.path.unshift(File.join(Rails.root, 'gems'))
|
7
|
-
|
8
|
-
deps = ::Dependencies::Reader.read_file(File.join(Rails.root, 'config', 'dependencies.rb'))
|
9
|
-
|
10
|
-
deps.each do |dep|
|
11
|
-
current_environment = ENV['RAILS_ENV'] || 'development'
|
12
|
-
|
13
|
-
options = {
|
14
|
-
:only => [current_environment],
|
15
|
-
:except => [],
|
16
|
-
:require_as => dep.name
|
17
|
-
}.merge(dep.options)
|
18
|
-
|
19
|
-
# swap their :only and :except to an array if they used a not-Array
|
20
|
-
[ :only, :except ].each do |option|
|
21
|
-
options[option] = [options[option].to_s] unless options[option].is_a?(Array)
|
22
|
-
end
|
23
|
-
|
24
|
-
# don't run if require_as is nil or false
|
25
|
-
next if [nil, false].include?(options[:require_as])
|
26
|
-
|
27
|
-
# don't run if the dependency wants an env that is not the current one
|
28
|
-
next unless options[:only].include?(current_environment)
|
29
|
-
|
30
|
-
# don't run if the dependency does not want to load in the current env
|
31
|
-
next if options[:except].include?(current_environment)
|
32
|
-
|
33
|
-
begin
|
34
|
-
require options[:require_as]
|
35
|
-
rescue LoadError => e
|
36
|
-
puts "was unable to require #{dep.name} as '#{options[:require_as]}'
|
37
|
-
Reason: #{e.class.name} error raised with message: #{e.message}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/hash/deep_merge'
|
2
|
-
require 'active_support/option_merger'
|
3
|
-
|
4
|
-
class Dependencies::Reader
|
5
|
-
|
6
|
-
attr_reader :dependencies
|
7
|
-
|
8
|
-
def self.read(definitions)
|
9
|
-
reader = new
|
10
|
-
reader.instance_eval(definitions)
|
11
|
-
reader.dependencies
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.read_file(filename)
|
15
|
-
self.read(File.read(filename))
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@dependencies = []
|
20
|
-
end
|
21
|
-
|
22
|
-
def dependency(name, *options)
|
23
|
-
@dependencies << ::Dependencies::Dependency.new(name, *options)
|
24
|
-
end
|
25
|
-
|
26
|
-
def with_options(options)
|
27
|
-
yield ActiveSupport::OptionMerger.new(self, options)
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# This was added by Merb's bundler
|
4
|
-
|
5
|
-
require "rubygems"
|
6
|
-
require File.join(File.dirname(__FILE__), "common")
|
7
|
-
|
8
|
-
gems_dir = File.join(File.dirname(__FILE__), '..', 'gems')
|
9
|
-
|
10
|
-
if File.directory?(gems_dir)
|
11
|
-
$BUNDLE = true
|
12
|
-
Gem.clear_paths
|
13
|
-
Gem.path.replace([File.expand_path(gems_dir)])
|
14
|
-
ENV["PATH"] = "#{File.dirname(__FILE__)}:#{ENV["PATH"]}"
|
15
|
-
|
16
|
-
gem_file = File.join(gems_dir, "specifications", "<%= spec.name %>-*.gemspec")
|
17
|
-
|
18
|
-
if local_gem = Dir[gem_file].last
|
19
|
-
version = File.basename(local_gem)[/-([\.\d]+)\.gemspec$/, 1]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
version ||= "<%= Gem::Requirement.default %>"
|
24
|
-
|
25
|
-
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
26
|
-
version = $1
|
27
|
-
ARGV.shift
|
28
|
-
end
|
29
|
-
|
30
|
-
gem '<%= @spec.name %>', version
|
31
|
-
load '<%= bin_file_name %>'
|
@@ -1,164 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
require "rubygems/source_index"
|
3
|
-
require "rubygems/dependency_installer"
|
4
|
-
require "rubygems/uninstaller"
|
5
|
-
require "fileutils"
|
6
|
-
|
7
|
-
# there has got to be a better way to do this
|
8
|
-
unless ARGV.first == 'dependencies:import'
|
9
|
-
Gem.clear_paths
|
10
|
-
Gem.path.unshift(File.join(RAILS_ROOT, 'gems'))
|
11
|
-
end
|
12
|
-
|
13
|
-
namespace :dependencies do
|
14
|
-
|
15
|
-
task :setup do
|
16
|
-
# avoid requiring environment by working up from vendor/plugins/dependencies/tasks
|
17
|
-
rails_root = File.expand_path(File.join(File.dirname(__FILE__), %w(.. .. .. ..)))
|
18
|
-
|
19
|
-
# Dependencies isn't loaded when running from rake. This is a good place to load it.
|
20
|
-
require File.expand_path(File.join(File.dirname(__FILE__), %w(.. lib dependencies))) unless defined?(Dependencies)
|
21
|
-
|
22
|
-
SETTINGS = {
|
23
|
-
:dependencies_file => File.join(rails_root, 'config', 'dependencies.rb'),
|
24
|
-
:gem_dir => File.join(rails_root, 'gems')
|
25
|
-
}
|
26
|
-
FileUtils.mkdir(SETTINGS[:gem_dir]) unless File.exists?(SETTINGS[:gem_dir])
|
27
|
-
end
|
28
|
-
|
29
|
-
task :load => :setup do
|
30
|
-
SETTINGS[:dependencies] = ::Dependencies::Reader.read_file(SETTINGS[:dependencies_file])
|
31
|
-
end
|
32
|
-
|
33
|
-
namespace :transaction do
|
34
|
-
task :setup do
|
35
|
-
SETTINGS[:gem_original_dir] = SETTINGS[:gem_dir]
|
36
|
-
SETTINGS[:gem_dir] = SETTINGS[:gem_dir] + '.install'
|
37
|
-
end
|
38
|
-
|
39
|
-
task :begin => :setup do
|
40
|
-
FileUtils.rm_rf(SETTINGS[:gem_dir])
|
41
|
-
FileUtils.cp_r(SETTINGS[:gem_original_dir], SETTINGS[:gem_dir])
|
42
|
-
end
|
43
|
-
|
44
|
-
task :commit => :setup do
|
45
|
-
FileUtils.rm_rf(SETTINGS[:gem_original_dir])
|
46
|
-
FileUtils.mv(SETTINGS[:gem_dir], SETTINGS[:gem_original_dir])
|
47
|
-
end
|
48
|
-
|
49
|
-
task :rollback => :setup do
|
50
|
-
FileUtils.rm_rf(SETTINGS[:gem_dir])
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
desc 'synchronize the stuff'
|
55
|
-
task :sync => [ :setup, :load ] do
|
56
|
-
Rake::Task['dependencies:transaction:begin'].invoke
|
57
|
-
|
58
|
-
begin
|
59
|
-
repo = Dependencies::Repository.new(SETTINGS[:gem_dir])
|
60
|
-
|
61
|
-
SETTINGS[:dependencies].each do |dep|
|
62
|
-
gem = repo.gem(dep.name, dep.versions)
|
63
|
-
next unless repo.search(gem).empty?
|
64
|
-
repo.install(gem)
|
65
|
-
end
|
66
|
-
|
67
|
-
repo.reload_index!
|
68
|
-
|
69
|
-
full_list = SETTINGS[:dependencies].map do |dep|
|
70
|
-
gem = repo.gem(dep.name, dep.versions)
|
71
|
-
spec = repo.index.search(gem).last
|
72
|
-
unless spec
|
73
|
-
# Rake::Task['dependencies:transaction:rollback'].invoke # gets run on rescue below.
|
74
|
-
raise Exception.new("A required dependency #{gem} was not found")
|
75
|
-
end
|
76
|
-
deps = spec.recursive_dependencies(gem, repo.index)
|
77
|
-
[spec] + deps
|
78
|
-
end.flatten.uniq.map do |spec|
|
79
|
-
"#{spec.name}-#{spec.version}"
|
80
|
-
end
|
81
|
-
|
82
|
-
(repo.installed - full_list).each do |g|
|
83
|
-
/^(.*)\-(.*)$/ =~ g
|
84
|
-
repo.uninstall($1, $2)
|
85
|
-
end
|
86
|
-
|
87
|
-
#confirm(gems)
|
88
|
-
|
89
|
-
Rake::Task['dependencies:transaction:commit'].invoke
|
90
|
-
|
91
|
-
rescue Exception => ex
|
92
|
-
puts ex.message
|
93
|
-
puts ex.backtrace
|
94
|
-
Rake::Task['dependencies:transaction:rollback'].invoke
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
desc 'Build a dependencies.rb from old config.gem style declarations'
|
99
|
-
task :import do
|
100
|
-
|
101
|
-
# gross
|
102
|
-
$block_dependencies_plugin_init = true
|
103
|
-
$gems_rake_task = true
|
104
|
-
$gems_build_rake_task = true
|
105
|
-
|
106
|
-
Rake::Task['environment'].invoke
|
107
|
-
environments = %w( development test production )
|
108
|
-
|
109
|
-
gems = environments.inject({}) do |memo, environment|
|
110
|
-
begin
|
111
|
-
ENV['RAILS_ENV'] = environment
|
112
|
-
RAILS_ENV = environment
|
113
|
-
load File.join(RAILS_ROOT, 'config', 'environment.rb')
|
114
|
-
rescue StandardError => ex
|
115
|
-
puts "Something went wrong: #{ex.message}"
|
116
|
-
exit 1
|
117
|
-
end
|
118
|
-
|
119
|
-
Rails.configuration.gems.each do |gem|
|
120
|
-
signature = [gem.name, gem.requirement.to_s]
|
121
|
-
memo[signature] ||= {
|
122
|
-
:name => gem.name,
|
123
|
-
:version => gem.requirement.to_s,
|
124
|
-
:require_as => gem.lib,
|
125
|
-
:environments => []
|
126
|
-
}
|
127
|
-
memo[signature][:environments] << environment
|
128
|
-
end
|
129
|
-
|
130
|
-
memo
|
131
|
-
end
|
132
|
-
|
133
|
-
all_environments, some_environments = gems.values.partition do |gem|
|
134
|
-
gem[:environments].sort == environments.sort
|
135
|
-
end
|
136
|
-
|
137
|
-
all_environments.each do |gem|
|
138
|
-
puts dependency_declaration_from_hash(gem)
|
139
|
-
end
|
140
|
-
|
141
|
-
environments.each do |environment|
|
142
|
-
gems = some_environments.select do |gem|
|
143
|
-
gem[:environments].include?(environment)
|
144
|
-
end
|
145
|
-
|
146
|
-
unless gems.length.zero?
|
147
|
-
puts
|
148
|
-
puts "with_options(:only => '#{environment}') do |#{environment}|"
|
149
|
-
gems.each do |gem|
|
150
|
-
puts " #{environment}." + dependency_declaration_from_hash(gem)
|
151
|
-
end
|
152
|
-
puts 'end'
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def dependency_declaration_from_hash(gem)
|
159
|
-
declaration = []
|
160
|
-
declaration << "dependency '#{gem[:name]}'"
|
161
|
-
declaration << "'#{gem[:version]}'" unless gem[:version].blank?
|
162
|
-
declaration << ":require_as => '#{gem[:lib]}'" unless gem[:lib] == nil
|
163
|
-
declaration.join(', ')
|
164
|
-
end
|