buttons 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+