bowline 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +1 -0
  2. data/History.txt +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/Manifest.txt +58 -0
  5. data/README.txt +136 -0
  6. data/Rakefile +25 -0
  7. data/assets/jquery.bowline.js +96 -0
  8. data/assets/jquery.chain.js +2348 -0
  9. data/assets/jquery.js +3549 -0
  10. data/bin/bowline-gen +6 -0
  11. data/bowline.gemspec +45 -0
  12. data/examples/account.rb +31 -0
  13. data/examples/example.js +24 -0
  14. data/examples/tweets.rb +28 -0
  15. data/examples/twitter.html +39 -0
  16. data/examples/users.rb +37 -0
  17. data/lib/bowline.rb +42 -0
  18. data/lib/bowline/binders.rb +177 -0
  19. data/lib/bowline/binders/collection.rb +27 -0
  20. data/lib/bowline/binders/singleton.rb +25 -0
  21. data/lib/bowline/commands/console.rb +27 -0
  22. data/lib/bowline/commands/generate.rb +1 -0
  23. data/lib/bowline/commands/run.rb +11 -0
  24. data/lib/bowline/ext/array.rb +5 -0
  25. data/lib/bowline/ext/class.rb +51 -0
  26. data/lib/bowline/ext/object.rb +12 -0
  27. data/lib/bowline/ext/string.rb +9 -0
  28. data/lib/bowline/gem_dependency.rb +42 -0
  29. data/lib/bowline/generators.rb +59 -0
  30. data/lib/bowline/generators/application.rb +58 -0
  31. data/lib/bowline/generators/binder.rb +25 -0
  32. data/lib/bowline/generators/migration.rb +51 -0
  33. data/lib/bowline/generators/model.rb +20 -0
  34. data/lib/bowline/initializer.rb +596 -0
  35. data/lib/bowline/jquery.rb +31 -0
  36. data/lib/bowline/observer.rb +43 -0
  37. data/lib/bowline/tasks/app.rake +90 -0
  38. data/lib/bowline/tasks/bowline.rb +8 -0
  39. data/lib/bowline/tasks/database.rake +167 -0
  40. data/lib/bowline/tasks/log.rake +9 -0
  41. data/lib/bowline/tasks/misk.rake +3 -0
  42. data/templates/Rakefile +7 -0
  43. data/templates/binder.rb +9 -0
  44. data/templates/config/application.yml +1 -0
  45. data/templates/config/boot.rb +13 -0
  46. data/templates/config/database.yml +4 -0
  47. data/templates/config/environment.rb +12 -0
  48. data/templates/config/manifest +18 -0
  49. data/templates/config/tiapp.xml +24 -0
  50. data/templates/gitignore +15 -0
  51. data/templates/migration.rb +7 -0
  52. data/templates/model.rb +4 -0
  53. data/templates/public/index.html +25 -0
  54. data/templates/public/javascripts/application.js +0 -0
  55. data/templates/public/stylesheets/application.css +0 -0
  56. data/templates/script/console +3 -0
  57. data/templates/script/init +18 -0
  58. data/templates/script/run +3 -0
  59. metadata +155 -0
data/bin/bowline-gen ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), *%w[.. lib bowline])
4
+ require 'bowline/generators'
5
+
6
+ Bowline::Generators.run_cli(Dir.pwd, 'bowline', Bowline::VERSION, ARGV)
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
@@ -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
@@ -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
+ // })
@@ -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 &rarr;" 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