paloma 0.0.1 → 0.0.2
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 +18 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +148 -0
- data/License +22 -0
- data/README.md +240 -0
- data/Rakefile +16 -0
- data/app/views/paloma/_callback_hook.html.erb +33 -0
- data/lib/paloma.rb +14 -0
- data/lib/paloma/action_controller_extension.rb +52 -0
- data/lib/paloma/action_controller_filters.rb +53 -0
- data/lib/paloma/paloma_generator.rb +94 -0
- data/lib/paloma/templates/_callbacks.js +2 -0
- data/lib/paloma/templates/_local.js +20 -0
- data/lib/paloma/templates/action.js +5 -0
- data/lib/paloma/templates/index.js +1 -0
- data/lib/paloma/templates/paloma.js +22 -0
- data/paloma.gemspec +23 -0
- data/spec/callback_spec.rb +65 -0
- data/spec/sample_app/app/assets/javascripts/application.js +4 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/callbacks.js +1 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/create.js +3 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/edit.js +3 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/index.js +3 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/new.js +3 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/show.js +3 -0
- data/spec/sample_app/app/assets/javascripts/paloma/articles/update.js +3 -0
- data/spec/sample_app/app/assets/javascripts/paloma/index.js +2 -0
- data/spec/sample_app/app/assets/javascripts/paloma/paloma.js +1 -0
- data/spec/sample_app/app/views/articles/index.html.erb +5 -0
- data/spec/sample_app/app/views/articles/new.html.erb +9 -0
- data/spec/sample_app/app/views/articles/show.html.erb +2 -0
- data/spec/sample_app/app/views/layouts/application.html.erb +12 -0
- data/spec/sample_app/controllers.rb +54 -0
- data/spec/sample_app/init.rb +33 -0
- data/spec/sample_app/model.rb +28 -0
- data/spec/sample_app/paloma_test +0 -0
- data/spec/spec_helper.rb +21 -0
- metadata +215 -39
@@ -0,0 +1,33 @@
|
|
1
|
+
<% callback_details_id = "#{Time.now.to_i}#{(rand * 1000).ceil}" %>
|
2
|
+
|
3
|
+
<div class="callback-details" id="callback-details-<%= callback_details_id %>">
|
4
|
+
<script type="text/javascript">
|
5
|
+
var id = "callback-details-<%= callback_details_id %>",
|
6
|
+
callbacks = [];
|
7
|
+
|
8
|
+
// Remove any callback details if any
|
9
|
+
$('.callback-details[id!=" + id + "]').remove();
|
10
|
+
|
11
|
+
|
12
|
+
// Convert callbacks to javascript variable
|
13
|
+
<% callbacks.each do |callback| %>
|
14
|
+
callbacks.push({
|
15
|
+
name: '<%= callback[:name] %>',
|
16
|
+
params: eval($('<div/>').html("(<%= callback[:params].to_json %>)").text())
|
17
|
+
});
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
|
21
|
+
// Run Callbacks
|
22
|
+
for (var i = 0, len = callbacks.length; i < len; i++){
|
23
|
+
var callback = callbacks[i],
|
24
|
+
callbackFunction = Paloma.callbacks[callback.name];
|
25
|
+
|
26
|
+
console.log("Paloma: Fetching [" + callback.name + "]");
|
27
|
+
if (callback != undefined){
|
28
|
+
console.log("Paloma: Calling [" + callback.name + "]");
|
29
|
+
callbackFunction(callback.params);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
</script>
|
33
|
+
</div>
|
data/lib/paloma.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Paloma
|
2
|
+
def self.root
|
3
|
+
@paloma_root ||= File.dirname(__FILE__) + '/../'
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'action_controller/railtie'
|
8
|
+
require 'rails/generators'
|
9
|
+
|
10
|
+
# TODO: Rails version checking
|
11
|
+
|
12
|
+
require 'paloma/paloma_generator'
|
13
|
+
require 'paloma/action_controller_filters'
|
14
|
+
require 'paloma/action_controller_extension'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Paloma
|
2
|
+
|
3
|
+
# TODO explain!
|
4
|
+
module ::ActionController::Redirecting
|
5
|
+
alias_method :original_redirect_to, :redirect_to
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
module ActionControllerExtension
|
11
|
+
def redirect_js_hook options = {}, response_status = {}
|
12
|
+
add_to_callbacks @__callback__, @__js_params__
|
13
|
+
original_redirect_to options, response_status
|
14
|
+
end
|
15
|
+
alias_method :redirect_to, :redirect_js_hook
|
16
|
+
|
17
|
+
|
18
|
+
#
|
19
|
+
# js_callback false
|
20
|
+
# js_callback :new, :params => {}
|
21
|
+
# js_callback :controller => '', :action => '', :params => {}
|
22
|
+
# js_callback :params => {}
|
23
|
+
#
|
24
|
+
def js_callback options = {}, extras = {}
|
25
|
+
default_callback = "#{controller_name}/#{action_name}"
|
26
|
+
params = {}
|
27
|
+
|
28
|
+
if options.is_a? Hash
|
29
|
+
params = options[:params]
|
30
|
+
callback = options[:controller].present? && options[:action].present? ?
|
31
|
+
"#{options[:controller]}/#{options[:action]}" :
|
32
|
+
default_callback
|
33
|
+
|
34
|
+
elsif options.is_a? Symbol
|
35
|
+
params = extras[:params]
|
36
|
+
callback = "#{controller_name}/#{options}"
|
37
|
+
|
38
|
+
elsif options.nil? || options.is_a?(TrueClass)
|
39
|
+
callback = default_callback
|
40
|
+
|
41
|
+
else # false
|
42
|
+
callback = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
@__callback__ = callback
|
46
|
+
@__js_params__ = params
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
::ActionController::Base.send :include, ActionControllerExtension
|
52
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Paloma
|
2
|
+
module ActionControllerFilters
|
3
|
+
|
4
|
+
def self.included base
|
5
|
+
base.module_eval do
|
6
|
+
prepend_view_path "#{Paloma.root}/app/views/"
|
7
|
+
before_filter :js_callback
|
8
|
+
after_filter :update_callback, :if => :html_response_from_render?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def html_response_from_render?
|
16
|
+
[nil, 'text/html'].include?(response.content_type) && self.status != 302
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def update_callback
|
21
|
+
add_to_callbacks @__callback__, @__js_params__
|
22
|
+
|
23
|
+
response_body[0] += view_context.render(
|
24
|
+
:partial => "paloma/callback_hook",
|
25
|
+
:locals => {:callbacks => session[:callbacks]})
|
26
|
+
|
27
|
+
response.body = response_body[0]
|
28
|
+
clear_callbacks
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def add_to_callbacks name, params
|
33
|
+
return true if name.nil?
|
34
|
+
session[:callbacks] ||= []
|
35
|
+
session[:callbacks].push({:name => name, :params => params})
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def get_callbacks
|
40
|
+
session[:callbacks]
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def clear_callbacks
|
45
|
+
session[:callbacks] = []
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
::ActionController::Base.send :include, ActionControllerFilters
|
51
|
+
end
|
52
|
+
|
53
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Paloma
|
2
|
+
#
|
3
|
+
# Setup:
|
4
|
+
# rails g paloma:setup
|
5
|
+
# - Generates the following:
|
6
|
+
# - 'paloma' folder under app/assets/javascripts/paloma
|
7
|
+
# - index.js and paloma.js under the 'paloma' folder
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# Usage:
|
11
|
+
# rails g paloma:add <controller_name>
|
12
|
+
# - Generates the following:
|
13
|
+
# - a folder under app/assets/javascripts/paloma named as <controller_name>
|
14
|
+
# - callbacks.js inside the folder just made
|
15
|
+
# - Updates index.js under the 'paloma' folder
|
16
|
+
# - adds a line in order to require the callbacks to be made under the recently made folder
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# rails g paloma:add <controller_name>/<action_name>
|
20
|
+
# - Generates the following:
|
21
|
+
# - <action_name>.js file inside the <controller_name> folder
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# Generated Files:
|
25
|
+
# index.js
|
26
|
+
# - contains code for requiring all callbacks of all folders
|
27
|
+
# - always updated when new folders and callback.js files are created
|
28
|
+
#
|
29
|
+
# paloma.js
|
30
|
+
# - declaration of namespace used in all callbacks
|
31
|
+
#
|
32
|
+
# <controller_name>/callbacks.js
|
33
|
+
# - contains code for requiring all callbacks under the same folder <controller_name>
|
34
|
+
#
|
35
|
+
# <controller_name>/<action_name>.js
|
36
|
+
# - actual code to be executed when callback is called
|
37
|
+
#
|
38
|
+
|
39
|
+
PARENT = 'app/assets/javascripts/paloma/'
|
40
|
+
INDEX = PARENT + 'index.js'
|
41
|
+
PALOMA = PARENT + 'paloma.js'
|
42
|
+
|
43
|
+
class SetupGenerator < ::Rails::Generators::Base
|
44
|
+
source_root File.expand_path('../templates', __FILE__)
|
45
|
+
|
46
|
+
def setup_paloma
|
47
|
+
#index.js on callbacks folder
|
48
|
+
has_index = File.exists? INDEX
|
49
|
+
copy_file 'index.js', INDEX unless has_index
|
50
|
+
|
51
|
+
has_paloma = File.exists? PALOMA
|
52
|
+
copy_file 'paloma.js', PALOMA unless has_paloma
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
class AddGenerator < ::Rails::Generators::NamedBase
|
59
|
+
source_root File.expand_path('../templates', __FILE__)
|
60
|
+
|
61
|
+
def create_callback_file
|
62
|
+
file = file_path.split('/')
|
63
|
+
controller = file[0]
|
64
|
+
action = file[1]
|
65
|
+
|
66
|
+
callbacks = PARENT + "#{controller}/_callbacks.js"
|
67
|
+
templates = "#{Paloma.root}/lib/paloma/templates/"
|
68
|
+
local = PARENT + "#{controller}/_local.js"
|
69
|
+
action_file = PARENT + "#{controller}/#{action}.js"
|
70
|
+
|
71
|
+
#_callbacks.js per folder(controller)
|
72
|
+
has_callbacks = File.exists? callbacks
|
73
|
+
unless has_callbacks
|
74
|
+
content = File.read(templates + '_callbacks.js').gsub('controller', "#{controller}")
|
75
|
+
File.open(callbacks, 'w'){ |f| f.write(content) }
|
76
|
+
File.open(INDEX, 'a+'){|f| f << "\n//= require ./" + controller + '/_callbacks' }
|
77
|
+
end
|
78
|
+
|
79
|
+
#_local.js per folder(controller)
|
80
|
+
has_local =File.exists? local
|
81
|
+
unless has_local
|
82
|
+
content = File.read(templates + '_local.js').gsub('controller', "#{controller}")
|
83
|
+
File.open(local, 'w'){ |f| f.write(content) }
|
84
|
+
end
|
85
|
+
|
86
|
+
#<action>.js on folder(controller) - code for callback
|
87
|
+
has_action = File.exists? action_file
|
88
|
+
unless (action.nil? || has_action)
|
89
|
+
content = File.read(templates + 'action.js').gsub('controller/action', "#{controller}/#{action}")
|
90
|
+
File.open(action_file, 'w'){ |f| f.write(content) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Paloma.controller = {
|
2
|
+
|
3
|
+
/*
|
4
|
+
Put here code which can be used by all callbacks
|
5
|
+
under the controller folder.
|
6
|
+
|
7
|
+
Example:
|
8
|
+
|
9
|
+
variableName: value;
|
10
|
+
|
11
|
+
functionName: function(params){
|
12
|
+
alert('Paloma');
|
13
|
+
};
|
14
|
+
|
15
|
+
To use the variable and function:
|
16
|
+
Paloma.controller.variableName
|
17
|
+
Paloma.controller.functionName(params);
|
18
|
+
*/
|
19
|
+
|
20
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require ./paloma
|
@@ -0,0 +1,22 @@
|
|
1
|
+
window.Paloma = {callbacks:{}};
|
2
|
+
|
3
|
+
Paloma.g = {
|
4
|
+
|
5
|
+
/*
|
6
|
+
Put here global code that can be used by all callbacks,
|
7
|
+
regardless which folder they're from.
|
8
|
+
|
9
|
+
Example:
|
10
|
+
|
11
|
+
variableName: value;
|
12
|
+
|
13
|
+
functionName: function(params){
|
14
|
+
alert('Paloma');
|
15
|
+
};
|
16
|
+
|
17
|
+
To use the variable and function:
|
18
|
+
Paloma.g.variableName
|
19
|
+
Paloma.g.functionName(params);
|
20
|
+
*/
|
21
|
+
|
22
|
+
};
|
data/paloma.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'paloma'
|
3
|
+
s.version = '0.0.2'
|
4
|
+
s.date = '2012-12-17'
|
5
|
+
s.summary = "Javascript Callback Manager for Rails"
|
6
|
+
s.description = "Javascript Callback Manager for Rails"
|
7
|
+
s.authors = ["Karl Paragua", "Bia Esmero"]
|
8
|
+
s.email = 'kb.paragua@gmail.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.homepage = 'https://github.com/kbparagua/paloma'
|
11
|
+
|
12
|
+
s.add_dependency 'jquery-rails'
|
13
|
+
|
14
|
+
s.add_development_dependency 'rails', ['>= 3.1.0']
|
15
|
+
s.add_development_dependency 'bundler', ['>= 1.0.0']
|
16
|
+
s.add_development_dependency 'rake', ['>= 0']
|
17
|
+
s.add_development_dependency 'sqlite3', ['>= 0']
|
18
|
+
s.add_development_dependency 'rspec', ['>= 0']
|
19
|
+
s.add_development_dependency 'rspec-rails', ['~> 2.0']
|
20
|
+
s.add_development_dependency 'capybara', ['>= 1.0']
|
21
|
+
s.add_development_dependency 'database_cleaner', ['>= 0']
|
22
|
+
s.add_development_dependency 'launchy', ['>= 0']
|
23
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'Callbacks' do
|
4
|
+
|
5
|
+
it 'should execute articles/new callback', :js => true do
|
6
|
+
visit new_article_path
|
7
|
+
page.has_selector?('#from-articles-new-callback').should == true
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
it 'should execute callbacks for articles/create and articles/show', :js => true do
|
12
|
+
visit new_article_path
|
13
|
+
|
14
|
+
fill_in 'article[title]', :with => 'sexy paloma'
|
15
|
+
fill_in 'article[body]', :with => 'sexy paloma body'
|
16
|
+
click_button 'Save'
|
17
|
+
|
18
|
+
page.has_selector?('#from-articles-create-callback').should == true
|
19
|
+
page.has_selector?('#from-articles-show-callback').should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it 'should execute "new" callback instead of "create" after failed save', :js => true do
|
24
|
+
visit new_article_path
|
25
|
+
|
26
|
+
fill_in 'article[body]', :with => 'sexy paloma body'
|
27
|
+
click_button 'Save'
|
28
|
+
|
29
|
+
page.has_selector?('#from-articles-create-callback').should == false
|
30
|
+
page.has_selector?('#from-articles-new-callback').should == true
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
it 'should have an access on the passed parameters on js_callback', :js => true do
|
35
|
+
1.upto(30) do |i|
|
36
|
+
Article.create :title => "Sexy Paloma #{i}", :body => "Sexy Body"
|
37
|
+
end
|
38
|
+
|
39
|
+
visit articles_path
|
40
|
+
page.has_selector?('#article-count-30').should == true
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
it 'should not execute articles/update callback', :js => true do
|
45
|
+
article = Article.create :title => "Sexy Paloma Baby!", :body => "OMG"
|
46
|
+
|
47
|
+
visit edit_article_path(article)
|
48
|
+
fill_in 'article[body]', :with => 'Updated Body'
|
49
|
+
click_button 'Save'
|
50
|
+
|
51
|
+
page.has_selector?('#from-articles-update-callback').should == false
|
52
|
+
page.has_selector?('#from-articles-show-callback').should == true
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
it 'should execute articles/edit callback after failed update', :js => true do
|
57
|
+
article = Article.create :title => 'Sexy Paloma Baby!', :body => 'Yeah'
|
58
|
+
|
59
|
+
visit edit_article_path(article)
|
60
|
+
fill_in 'article[title]', :with => ''
|
61
|
+
click_button 'Save'
|
62
|
+
|
63
|
+
page.has_selector?('#from-articles-edit-callback').should == true
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree .
|