buttons 0.1.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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ *.gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Clinton R. Nixon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,74 @@
1
+ = Buttons
2
+
3
+ <b>NOTE: This is a very early version of Buttons. Expect it to change rapidly.</b>
4
+
5
+ Buttons is a Rack framework for working with JavaScript-heavy applications. It
6
+ automatically creates Ajax endpoints for Ruby methods, and creates a set of
7
+ JavaScript functions to access those endpoints.
8
+
9
+ == Example
10
+
11
+ Here's an example. The Ruby class below will automatically generate the
12
+ JavaScript found beneath it. For now, we only generate code that relies on
13
+ jQuery, but that's planned to change.
14
+
15
+ Ruby code:
16
+
17
+ class ProfileButton < Buttons::Button
18
+ get :show
19
+ post :login
20
+
21
+ def login(username, password)
22
+ # The variable's set just to show that it's being returned.
23
+ token = generate_login_token(username, password)
24
+ token
25
+ end
26
+
27
+ def show(profile_id)
28
+ Profile.find(profile_id)
29
+ end
30
+ end
31
+
32
+ JavaScript code (found at /profile.js):
33
+
34
+ (function () {
35
+ this.Profile = {};
36
+
37
+ Profile.login = function (username, password, _ajaxOptions) {
38
+ var data = { 'username': username, 'password': password };
39
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
40
+ _ajaxOptions = {};
41
+ }
42
+ _ajaxOptions['type'] = "POST";
43
+ _ajaxOptions['url'] = "/profile/login";
44
+ _ajaxOptions['data'] = data;
45
+
46
+ if (_ajaxOptions['dataType'] === 'undefined') {
47
+ _ajaxOptions['dataType'] = 'json';
48
+ }
49
+
50
+ return jQuery.ajax(_ajaxOptions);
51
+ };
52
+
53
+ Profile.show = function (profileId, _ajaxOptions) {
54
+ var data = { 'profile_id': profileId };
55
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
56
+ _ajaxOptions = {};
57
+ }
58
+ _ajaxOptions['type'] = "GET";
59
+ _ajaxOptions['url'] = "/profile/show";
60
+ _ajaxOptions['data'] = data;
61
+
62
+ if (_ajaxOptions['dataType'] === 'undefined') {
63
+ _ajaxOptions['dataType'] = 'json';
64
+ }
65
+
66
+ return jQuery.ajax(_ajaxOptions);
67
+ };
68
+ })();
69
+
70
+ == How to use this
71
+
72
+ Run <tt>buttons <directory></tt> to create a new Buttons application in that
73
+ directory. There's not any helpers or generators yet, but you can look at the
74
+ generated application to figure it out for now.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ task :default => :test
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gemspec|
6
+ gemspec.name = "buttons"
7
+ gemspec.summary = "Buttons is a Rack framework for working with JavaScript-heavy applications."
8
+ gemspec.description = "Buttons is a Rack framework for working with JavaScript-heavy applications. It
9
+ automatically creates Ajax endpoints for Ruby methods, and creates a set of
10
+ JavaScript functions to access those endpoints."
11
+ gemspec.email = "crnixon@gmail.com"
12
+ gemspec.homepage = "http://github.com/crnixon/buttons"
13
+ gemspec.authors = ["Clinton R. Nixon"]
14
+
15
+ gemspec.add_dependency('get_args', '>= 1.1.1')
16
+ gemspec.add_dependency('facets')
17
+ gemspec.add_dependency('json')
18
+ gemspec.add_dependency('rack', '>= 1.0.1')
19
+ gemspec.add_dependency('bundler')
20
+ gemspec.add_dependency('rubigen')
21
+ gemspec.add_development_dependency('riot')
22
+
23
+ # if RUBY_PLATFORM != 'java' && RUBY_VERSION < "1.9"
24
+ # gemspec.add_dependency('ParseTree')
25
+ # gemspec.add_dependency('ruby2ruby')
26
+ # end
27
+ end
28
+
29
+ Jeweler::GemcutterTasks.new
30
+ rescue LoadError
31
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
32
+ end
33
+
34
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '*.rake')].each { |file| load file }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/buttons ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'rubigen'
4
+ require 'rubigen/scripts/generate'
5
+
6
+ RubiGen::Base.sources << RubiGen::PathSource.new(:buttons, File.join(File.dirname(__FILE__), %w[.. generators]))
7
+ RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'buttons_app')
@@ -0,0 +1,24 @@
1
+ class ButtonsAppGenerator < RubiGen::Base
2
+ BASEDIRS = ['app', 'app/buttons', 'public']
3
+
4
+ def initialize(args, opts = {})
5
+ super
6
+ usage if args.empty?
7
+ @destination_root = args.shift
8
+ @app_name = File.basename(File.expand_path(@destination_root))
9
+ @module_name = @app_name.camelize
10
+ end
11
+
12
+ def manifest
13
+ record do |m|
14
+ m.directory ''
15
+ BASEDIRS.each { |dir| m.directory dir }
16
+
17
+ m.file_copy_each [ 'config.ru',
18
+ 'start.rb',
19
+ 'Rakefile',
20
+ 'public/index.html',
21
+ 'app/buttons/example_button.rb' ]
22
+ end
23
+ end
24
+ end
File without changes
@@ -0,0 +1,11 @@
1
+ class ExampleButton < Buttons::Button
2
+ get :add, :multiply
3
+
4
+ def add(operand1, operand2)
5
+ operand1.to_i + operand2.to_i
6
+ end
7
+
8
+ def multiply(operand1, operand2)
9
+ operand1.to_i * operand2.to_i
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), 'start')
2
+
3
+ files = Dir.chdir('public') { Dir['**/*'].map { |file| "/#{file}" } }
4
+ app = Buttons.app do
5
+ use Rack::Static, :root => 'public', :urls => files
6
+ end
7
+
8
+ run app
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <title>Buttons Example</title>
4
+ <link rel="stylesheet" href="/example.js" />
5
+ </head>
6
+ <body>
7
+ <h1>Buttons Example</h1>
8
+ </body>
9
+ </html>
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'buttons'
3
+
4
+ Buttons.configure do |config|
5
+ config.app_root = File.dirname(__FILE__)
6
+ end
7
+
8
+ Buttons.app.start
data/lib/buttons.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'facets'
3
+
4
+ module Buttons
5
+ def self.lib_root(*paths)
6
+ File.expand_path(File.join(File.dirname(__FILE__), 'buttons', *paths))
7
+ end
8
+
9
+ def self.app(&block)
10
+ @app ||= Buttons::Application.new
11
+ @app.instance_eval(&block) unless block.nil?
12
+ @app
13
+ end
14
+
15
+ def self.configure
16
+ yield app if block_given?
17
+ end
18
+ end
19
+
20
+ require Buttons.lib_root('core_ext/string')
21
+ require Buttons.lib_root('application')
22
+ require Buttons.lib_root('javascript')
23
+ require Buttons.lib_root('button')
@@ -0,0 +1,68 @@
1
+ require Buttons.lib_root('router')
2
+ require Buttons.lib_root('config')
3
+
4
+ module Buttons
5
+ class Application
6
+ include Buttons::Config
7
+
8
+ def initialize(&block)
9
+ @router ||= Buttons::Router.new
10
+ @middlewares ||= []
11
+ end
12
+
13
+ def use(middleware, options = nil)
14
+ @middlewares << [middleware, options]
15
+ end
16
+
17
+ def start
18
+ unless app_root.nil?
19
+ Dir[app_root('app', '**', '*.rb')].each do |ruby_file|
20
+ require ruby_file
21
+ end
22
+ end
23
+ end
24
+
25
+ def add_route(http_method, path, params)
26
+ @router.add_route(http_method, path, params)
27
+ end
28
+
29
+ def call(environment)
30
+ rack_app = lambda { |env|
31
+ request = ::Rack::Request.new(env)
32
+ response = ::Rack::Response.new
33
+ route = @router.recognize(request)
34
+
35
+ if route
36
+ render(request, response, route)
37
+ else
38
+ [404, {"Content-Type" => 'text/plain'}, "not found: #{request.path}\n\n" +
39
+ "All routes: \n#{@router.print_routes}"
40
+ ]
41
+ end
42
+ }
43
+
44
+ @middlewares.each do |middleware, options|
45
+ rack_app = if options
46
+ middleware.new(rack_app, options)
47
+ else
48
+ middleware.new(rack_app)
49
+ end
50
+ end
51
+
52
+ rack_app.call environment
53
+ end
54
+
55
+ def render(request, response, params)
56
+ button_klass, method_name = params[:button], params[:method]
57
+
58
+ response['Content-Type'] = 'text/javascript'
59
+ content = button_klass.new(request).call_method(method_name)
60
+ if conversion = params.delete(:convert)
61
+ content = content.send(conversion)
62
+ end
63
+ response.write(content)
64
+
65
+ response.finish
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,119 @@
1
+ require 'get_args'
2
+
3
+ module Buttons
4
+ class Button
5
+ attr_reader :request
6
+
7
+ def initialize(request)
8
+ @request = request
9
+ end
10
+
11
+ def to_js
12
+ self.class.to_js
13
+ end
14
+
15
+ def call_method(method_name)
16
+ send(method_name, *create_method_args(method_name))
17
+ end
18
+
19
+ class << self
20
+ def inherited(base)
21
+ Buttons.app.add_route(:get, "/#{base.namespace}.js",
22
+ :button => base, :method => :to_js)
23
+ end
24
+
25
+ def method_added(name)
26
+ routes.each do |http_method, methods|
27
+ if methods.include?(name)
28
+ setup_route(http_method, instance_method(name))
29
+ end
30
+ end
31
+ end
32
+
33
+ def namespace
34
+ self.to_s.debuttonize
35
+ end
36
+
37
+ def js_functions
38
+ @js_functions ||= []
39
+ end
40
+
41
+ def argument_list
42
+ @argument_list ||= {}
43
+ end
44
+
45
+ def routes
46
+ @routes ||= { }
47
+ end
48
+
49
+ def get(*names)
50
+ names.each do |name|
51
+ add_route(:get, name)
52
+ end
53
+ end
54
+
55
+ def post(*names)
56
+ names.each do |name|
57
+ add_route(:post, name)
58
+ end
59
+ end
60
+
61
+ def to_js
62
+ Buttons::Javascript::JsGenerator.new(self).to_js
63
+ end
64
+
65
+ private
66
+
67
+ def add_route(http_method, name)
68
+ routes[http_method] ||= []
69
+ routes[http_method] << name
70
+
71
+ method = instance_method(name) rescue nil
72
+ if method
73
+ setup_route(http_method, method)
74
+ end
75
+ end
76
+
77
+ def setup_route(http_method, method)
78
+ name = method.name
79
+ route_path = "/#{namespace}/#{name}"
80
+ argument_list[name] = method.get_argument_list
81
+ js_functions << Buttons::Javascript::JsFunction.new(
82
+ name, http_method, route_path, method.get_argument_list)
83
+ Buttons.app.add_route(http_method, route_path,
84
+ :button => self, :method => name, :convert => 'to_json')
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def params
91
+ request.params
92
+ end
93
+
94
+ def create_method_args(method_name)
95
+ args = []
96
+ argument_list = self.class.argument_list[method_name]
97
+
98
+ unless argument_list.nil?
99
+ argument_list.each do |argument|
100
+ param_name = argument.name.to_s
101
+ param_name = param_name.slice(1, param_name.length) if argument.multiple?
102
+ value = params[param_name]
103
+
104
+ if value.nil? and argument.optional?
105
+ value = argument.default
106
+ end
107
+ if argument.multiple?
108
+ args += value
109
+ else
110
+ args << value
111
+ end
112
+ end
113
+ end
114
+
115
+ p args.inspect
116
+ args
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,13 @@
1
+ module Buttons
2
+ module Config
3
+ def app_root=(path)
4
+ @app_root = path
5
+ end
6
+
7
+ def app_root(*paths)
8
+ if @app_root
9
+ File.expand_path(File.join(@app_root, *paths))
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def strip_whitespace
3
+ self.strip.gsub(/[\n\s]+/, ' ')
4
+ end
5
+
6
+ def debuttonize
7
+ self.underscore.gsub(/_button$/, '')
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'json'
2
+
3
+ require Buttons.lib_root('javascript', 'js_var')
4
+ require Buttons.lib_root('javascript', 'js_arg')
5
+ require Buttons.lib_root('javascript', 'js_function')
6
+ require Buttons.lib_root('javascript', 'js_generator')
7
+
@@ -0,0 +1,30 @@
1
+ module Buttons
2
+ module Javascript
3
+ class JsArg < JsVar
4
+ attr_reader :name
5
+
6
+ def initialize(var)
7
+ @var = var
8
+ super(@var.name)
9
+ end
10
+
11
+ def method_missing(*args, &block)
12
+ @var.send(*args, &block)
13
+ end
14
+
15
+ def default
16
+ @var.default.to_json
17
+ end
18
+
19
+ def to_default(index)
20
+ if optional?
21
+ %Q[
22
+ if (#{name} === undefined) {
23
+ #{name} = #{default};
24
+ }
25
+ ]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,62 @@
1
+ module Buttons
2
+ module Javascript
3
+ class JsFunction < JsVar
4
+ attr_reader :name, :args
5
+
6
+ def initialize(name, http_method, url, args)
7
+ super(name)
8
+
9
+ @http_method = http_method
10
+ @url = url
11
+ @args = args.map { |arg| JsArg.new(arg) }
12
+ end
13
+
14
+ def to_js(namespace = 'this')
15
+ %Q[
16
+ #{namespace}.#{name} = function (#{args_to_param_list}, _ajaxOptions) {
17
+ #{args_to_defaults}
18
+ #{assign_args_to_js_object}
19
+ #{ajax_call}
20
+ };
21
+ ].strip_whitespace
22
+ end
23
+
24
+ private
25
+
26
+ def ajax_call
27
+ %Q[
28
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
29
+ _ajaxOptions = {};
30
+ }
31
+ _ajaxOptions['type'] = #{@http_method.to_s.upcase.to_json};
32
+ _ajaxOptions['url'] = #{@url.to_json};
33
+ _ajaxOptions['data'] = data;
34
+
35
+ if (_ajaxOptions['dataType'] === 'undefined') {
36
+ _ajaxOptions['dataType'] = 'json';
37
+ }
38
+
39
+ return jQuery.ajax(_ajaxOptions);
40
+ ]
41
+ end
42
+
43
+ def args_to_param_list
44
+ args.map { |arg| arg.name }.compact.join(", ")
45
+ end
46
+
47
+ def args_to_defaults
48
+ args.map_with_index { |arg, i|
49
+ arg.to_default(i)
50
+ }.compact.join("\n")
51
+ end
52
+
53
+ def assign_args_to_js_object
54
+ arg_assignments = args.map { |arg|
55
+ "'#{arg.ruby_name}#{'[]' if arg.multiple?}': #{arg.name}"
56
+ }.join(", ")
57
+
58
+ %Q[var data = { #{arg_assignments} };]
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,27 @@
1
+ require "yui/compressor"
2
+
3
+ module Buttons
4
+ module Javascript
5
+ class JsGenerator
6
+ def initialize(button)
7
+ @button = button
8
+ # @compressor = YUI::JavaScriptCompressor.new
9
+ end
10
+
11
+ def to_js
12
+ js = %Q[
13
+ (function () {
14
+ this.#{@button.namespace.capitalize} = {};
15
+
16
+ #{@button.js_functions.map { |function|
17
+ function.to_js(@button.namespace.capitalize)
18
+ }.join("\n")}
19
+ })();
20
+ ]
21
+
22
+ # @compressor.compress(js)
23
+ js.strip_whitespace
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module Buttons
2
+ module Javascript
3
+ class JsVar
4
+ attr_reader :name, :ruby_name
5
+
6
+ def initialize(name)
7
+ @ruby_name = name = name.to_s.gsub(/^\*/, '')
8
+ @name = name.camelcase
9
+ end
10
+
11
+ def to_s
12
+ @name
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ module Buttons
2
+ class Router
3
+ def initialize
4
+ @routes = {}
5
+ end
6
+
7
+ def add_route(http_method, path, params)
8
+ http_method = http_method.to_s.downcase
9
+
10
+ @routes[http_method] ||= {}
11
+ @routes[http_method][path] = params
12
+ end
13
+
14
+ def recognize(request)
15
+ request_method = request.request_method.to_s.downcase
16
+
17
+ @routes[request_method] && @routes[request_method][request.path]
18
+ end
19
+
20
+ def print_routes
21
+ @routes.map do |http_method, routes|
22
+ routes.map do |route, params|
23
+ "%8s %s %s" % [http_method.upcase, route, params.inspect]
24
+ end.join("\n")
25
+ end.join("\n")
26
+ end
27
+ end
28
+ end
data/public/index.txt ADDED
@@ -0,0 +1 @@
1
+ hi there
data/tasks/test.rake ADDED
@@ -0,0 +1,6 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new(:test) do |t|
4
+ t.test_files = FileList['tests/**/*_tests.rb']
5
+ t.libs << 'test'
6
+ end
@@ -0,0 +1,58 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+
3
+ class ProfileButton < Buttons::Button
4
+ get :show
5
+ post :login
6
+
7
+ def login(username, password)
8
+ # The variable's set just to show that it's being returned.
9
+ token = generate_login_token(username, password)
10
+ token
11
+ end
12
+
13
+ def show(profile_id)
14
+ Profile.find(profile_id)
15
+ end
16
+ end
17
+
18
+ context "ProfileButton" do
19
+ should("generate JS") {
20
+ ProfileButton.to_js
21
+ }.equals(%Q[
22
+ (function () {
23
+ this.Profile = {};
24
+
25
+ Profile.login = function (username, password, _ajaxOptions) {
26
+ var data = { 'username': username, 'password': password };
27
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
28
+ _ajaxOptions = {};
29
+ }
30
+ _ajaxOptions['type'] = "POST";
31
+ _ajaxOptions['url'] = "/profile/login";
32
+ _ajaxOptions['data'] = data;
33
+
34
+ if (_ajaxOptions['dataType'] === 'undefined') {
35
+ _ajaxOptions['dataType'] = 'json';
36
+ }
37
+
38
+ return jQuery.ajax(_ajaxOptions);
39
+ };
40
+
41
+ Profile.show = function (profileId, _ajaxOptions) {
42
+ var data = { 'profile_id': profileId };
43
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
44
+ _ajaxOptions = {};
45
+ }
46
+ _ajaxOptions['type'] = "GET";
47
+ _ajaxOptions['url'] = "/profile/show";
48
+ _ajaxOptions['data'] = data;
49
+
50
+ if (_ajaxOptions['dataType'] === 'undefined') {
51
+ _ajaxOptions['dataType'] = 'json';
52
+ }
53
+
54
+ return jQuery.ajax(_ajaxOptions);
55
+ };
56
+ })();
57
+ ].strip_whitespace)
58
+ end
data/tests/helper.rb ADDED
@@ -0,0 +1,3 @@
1
+ $:.push(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'buttons'
3
+ require 'riot'
@@ -0,0 +1,86 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+
3
+ include Buttons::Javascript
4
+
5
+ context "a JsVar" do
6
+ setup { JsVar.new(:remember_me) }
7
+
8
+ should("convert underscore syntax to JS syntax") {
9
+ topic.name
10
+ }.equals("rememberMe")
11
+
12
+ should("remember Ruby name") { topic.ruby_name }.equals("remember_me")
13
+
14
+ should("remove leading asterisk") {
15
+ JsVar.new("*names").name
16
+ }.equals("names")
17
+ end
18
+
19
+ context "a JsArg" do
20
+ setup {
21
+ arg = Struct.new(:name, :default, :optional?, :foo).new(
22
+ 'arg_name', nil, true, :bar)
23
+ JsArg.new(arg)
24
+ }
25
+
26
+ should("convert default to json") { topic.default }.equals(nil.to_json)
27
+
28
+ should("forward all missing methods to arg") { topic.foo }.equals(:bar)
29
+ end
30
+
31
+ context "a JsFunction" do
32
+ setup {
33
+ JsFunction.new(:login, :post, '/login', GetArgs::ArgumentList.new(
34
+ [ [:username], [:password], [:remember_me, true] ]
35
+ ))
36
+ }
37
+
38
+ should("emit JavaScript") {
39
+ topic.to_js
40
+ }.equals(
41
+ %Q[
42
+ this.login = function (username, password, rememberMe, _ajaxOptions) {
43
+ if (rememberMe === undefined) { rememberMe = true; }
44
+ var data = { 'username': username, 'password': password, 'remember_me': rememberMe };
45
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
46
+ _ajaxOptions = {};
47
+ }
48
+ _ajaxOptions['type'] = "POST";
49
+ _ajaxOptions['url'] = "/login";
50
+ _ajaxOptions['data'] = data;
51
+ if (_ajaxOptions['dataType'] === 'undefined') {
52
+ _ajaxOptions['dataType'] = 'json';
53
+ }
54
+ return jQuery.ajax(_ajaxOptions);
55
+ };
56
+ ].strip_whitespace
57
+ )
58
+ end
59
+
60
+ context "a JsFunction with a star argument" do
61
+ setup {
62
+ JsFunction.new(:add_users, :post, '/add_users', GetArgs::ArgumentList.new(
63
+ [ [:admin_username], [:admin_password], ["*new_users"] ]
64
+ ))
65
+ }
66
+
67
+ should("emit JavaScript") {
68
+ topic.to_js
69
+ }.equals(
70
+ %Q[
71
+ this.addUsers = function (adminUsername, adminPassword, newUsers, _ajaxOptions) {
72
+ var data = { 'admin_username': adminUsername, 'admin_password': adminPassword, 'new_users[]': newUsers };
73
+ if (_ajaxOptions === undefined || typeof(_ajaxOptions) != "object") {
74
+ _ajaxOptions = {};
75
+ }
76
+ _ajaxOptions['type'] = "POST";
77
+ _ajaxOptions['url'] = "/add_users";
78
+ _ajaxOptions['data'] = data;
79
+ if (_ajaxOptions['dataType'] === 'undefined') {
80
+ _ajaxOptions['dataType'] = 'json';
81
+ }
82
+ return jQuery.ajax(_ajaxOptions);
83
+ };
84
+ ].strip_whitespace
85
+ )
86
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: buttons
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Clinton R. Nixon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-13 00:00:00 -05:00
13
+ default_executable: buttons
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: get_args
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.1.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: facets
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: json
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: rack
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.1
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: rubigen
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ - !ruby/object:Gem::Dependency
76
+ name: riot
77
+ type: :development
78
+ version_requirement:
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ description: |-
86
+ Buttons is a Rack framework for working with JavaScript-heavy applications. It
87
+ automatically creates Ajax endpoints for Ruby methods, and creates a set of
88
+ JavaScript functions to access those endpoints.
89
+ email: crnixon@gmail.com
90
+ executables:
91
+ - buttons
92
+ extensions: []
93
+
94
+ extra_rdoc_files:
95
+ - LICENSE
96
+ - README.rdoc
97
+ files:
98
+ - .gitignore
99
+ - LICENSE
100
+ - README.rdoc
101
+ - Rakefile
102
+ - VERSION
103
+ - bin/buttons
104
+ - generators/buttons_app/buttons_app_generator.rb
105
+ - generators/buttons_app/templates/Rakefile
106
+ - generators/buttons_app/templates/app/buttons/example_button.rb
107
+ - generators/buttons_app/templates/config.ru
108
+ - generators/buttons_app/templates/public/index.html
109
+ - generators/buttons_app/templates/start.rb
110
+ - lib/buttons.rb
111
+ - lib/buttons/application.rb
112
+ - lib/buttons/button.rb
113
+ - lib/buttons/config.rb
114
+ - lib/buttons/core_ext/string.rb
115
+ - lib/buttons/javascript.rb
116
+ - lib/buttons/javascript/js_arg.rb
117
+ - lib/buttons/javascript/js_function.rb
118
+ - lib/buttons/javascript/js_generator.rb
119
+ - lib/buttons/javascript/js_var.rb
120
+ - lib/buttons/router.rb
121
+ - public/index.txt
122
+ - tasks/test.rake
123
+ - tests/button_tests.rb
124
+ - tests/helper.rb
125
+ - tests/javascript_tests.rb
126
+ has_rdoc: true
127
+ homepage: http://github.com/crnixon/buttons
128
+ licenses: []
129
+
130
+ post_install_message:
131
+ rdoc_options:
132
+ - --charset=UTF-8
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: "0"
140
+ version:
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: "0"
146
+ version:
147
+ requirements: []
148
+
149
+ rubyforge_project:
150
+ rubygems_version: 1.3.5
151
+ signing_key:
152
+ specification_version: 3
153
+ summary: Buttons is a Rack framework for working with JavaScript-heavy applications.
154
+ test_files: []
155
+