1
0
Fork 0
mirror of https://github.com/kbparagua/paloma synced 2023-03-27 23:21:17 -04:00

Merge branch 'master' of github.com:kbparagua/paloma

This commit is contained in:
Bia Esmero 2012-12-19 18:04:58 +08:00
commit 2b23b1e43a
20 changed files with 242 additions and 64 deletions

135
README.md
View file

@ -1,55 +1,106 @@
paloma
Paloma
======
Paloma provides a sexy way to organize javascript files using Rails' asset pipeline.
It adds the capability to execute specific javascript code after rendering the controller's response.
Javascript Callback Manager for Rails 3
Advantages
-
* Javascript files are organized per controller just like app/views folder of Rails.
* Javascript file per controller's action.
* The ability to choose what specific javascript code to run on a specific action.
Quick Example
-
The javascript callback file `paloma/users/new.js`:
```javascript
Paloma.callbacks['users/new'] = function(params){
// This will only run after executing users/new action
alert('Hello New Sexy User');
};
```
The Rails controller `app/controllers/users_controller.rb`:
```ruby
def UsersController < ApplicationController
def new
@user = User.new
# No special function to call, the javascript callback will be executed automatically
end
end
```
That's it! Simply Sexy!
Minimum Requirements
-
* jQuery 1.7 or higher
* Rails 3.1 or higher
Install
-------
Add the following line to the Gemfile:
gem 'paloma'
-
Without bundler:
```
sudo gem install paloma
```
With bundler, add this to your Gemfile:
```
gem paloma
```
Setup
-
On setup, the `paloma` folder will be generated in `app/assets/javascripts/` containing its required files. Run:
```
rails g paloma:setup
```
Directory Structure
-
`paloma` folder contains the javascript callbacks.
* paloma
* [controllers]
* [action].js
* [other_action].js
* [other_controllers]
* [action].js
* [other_action].js
* [more_action].js
Usage
-----
>*On the first run of either of the two commands mentioned below, the __callbacks__ folder will be generated in __app/assets/javascripts/__. Inside the callbacks folder, __index.js__ will also be created.*
-
1. Generate a controller folder containing its required files:
```
rails g paloma:add [controllers]
```
**Example:**
```
rails g paloma:add users
```
The following are the commands which can be executed in the terminal to generate files needed for the callbacks:
rails g paloma:add <controller_name>
>*Execute the command above to generate a folder, named as __\<controller_name\>__ which will be the container of all the callbacks that will be used within that controller. Inside this folder, __callbacks.js__ will also be generated.*
rails g paloma:add <controller_name>/<action_name>
> *This command allows the user to create the file __\<action_name\>.js__ under the __\<controller_name\> folder__.*
**Generates:**
* /paloma
* /users
Generated Files
---------------
###index.js
Contains code for requiring all callbacks of all folders and is automatically updated when new folders and callback.js files are created
2. Generate a callback file for a controller's action:
```
rails g paloma:add [controllers]/[action]
```
**Example:**
```
rails g paloma:add users/new
```
# app/assets/javascripts/callbacks/index.js
window.Paloma = {callbacks:{}};
//= require ./<controller_name>/callbacks
**Generates:**
* /paloma
* /users
* new.js
###callbacks.js
Contains code for requiring all callbacks under the same folder <controller_name>
# app/assets/javascripts/callbacks/<controller_name>/callbacks.js
//= require_tree .
###\<action_name\>.js
Actual code to be executed when callback is called
# app/assets/javascripts/callbacks/<controller_name>/<action_name>.js
Paloma.callbacks['<controller_name>/<action_name>'] = function(params){
...
//put your code here
...
};
**Note:** You can directly run `rails g paloma:add [controllers]/[action]` even the controller folder is not yet
existing on `paloma` folder. It will be created automatically.

View file

@ -2,19 +2,32 @@
<div class="callback-details" id="callback-details-<%= callback_details_id %>">
<script type="text/javascript">
var id = "callback-details-<%= callback_details_id %>";
$(".callback-details[id!=" + id + "]").remove(); // Remove any callback details if any
var id = "callback-details-<%= callback_details_id %>",
callbacks = [];
// Remove any callback details if any
$('.callback-details[id!=" + id + "]').remove();
// Convert callbacks to javascript variable
<% callbacks.each do |callback| %>
var params = eval($('<div/>').html("(<%= callback[:params].to_json %>)").text()),
callbackName = "<%= callback[:name] %>",
callback = Paloma.callbacks[callbackName];
console.log("Paloma: Fetching [" + callbackName + "]");
callbacks.push({
name: '<%= callback[:name] %>',
params: eval($('<div/>').html("(<%= callback[:params].to_json %>)").text())
});
<% end %>
// Run Callbacks
for (var i = 0, len = callbacks.length; i < len; i++){
var callback = callbacks[i],
callbackFunction = Paloma.callbacks[callback.name];
console.log("Paloma: Fetching [" + callback.name + "]");
if (callback != undefined){
console.log("Paloma: Calling [" + callbackName + "]");
$(document).ready(function(e){ callback(params); });
console.log("Paloma: Calling [" + callback.name + "]");
callbackFunction(callback.params);
}
<% end %>
}
</script>
</div>

View file

@ -19,7 +19,7 @@ module Paloma
def update_callback
add_to_callbacks @__callback__, @__js_params__
response_body[0] += view_context.render(
:partial => "paloma/callback_hook",
:locals => {:callbacks => session[:callbacks]})
@ -30,6 +30,7 @@ module Paloma
def add_to_callbacks name, params
return true if name.nil?
session[:callbacks] ||= []
session[:callbacks].push({:name => name, :params => params})
end

View file

@ -1,11 +1,65 @@
require 'spec_helper'
describe "Rendering HTML response of controller's action ", :type => :feature do
feature 'Callbacks' do
it "executes the correct javascript callback" do
visit new_article_path
it 'should execute articles/new callback', :js => true do
visit new_article_path
page.has_selector?('#from-articles-new-callback').should == true
end
it 'should execute callbacks for articles/create and articles/show', :js => true do
visit new_article_path
page.has_css?('.callback-details').should == true
fill_in 'article[title]', :with => 'sexy paloma'
fill_in 'article[body]', :with => 'sexy paloma body'
click_button 'Save'
page.has_selector?('#from-articles-create-callback').should == true
page.has_selector?('#from-articles-show-callback').should == true
end
it 'should execute "new" callback instead of "create" after failed save', :js => true do
visit new_article_path
fill_in 'article[body]', :with => 'sexy paloma body'
click_button 'Save'
page.has_selector?('#from-articles-create-callback').should == false
page.has_selector?('#from-articles-new-callback').should == true
end
it 'should have an access on the passed parameters on js_callback', :js => true do
1.upto(30) do |i|
Article.create :title => "Sexy Paloma #{i}", :body => "Sexy Body"
end
visit articles_path
page.has_selector?('#article-count-30').should == true
end
it 'should not execute articles/update callback', :js => true do
article = Article.create :title => "Sexy Paloma Baby!", :body => "OMG"
visit edit_article_path(article)
fill_in 'article[body]', :with => 'Updated Body'
click_button 'Save'
page.has_selector?('#from-articles-update-callback').should == false
page.has_selector?('#from-articles-show-callback').should == true
end
it 'should execute articles/edit callback after failed update', :js => true do
article = Article.create :title => 'Sexy Paloma Baby!', :body => 'Yeah'
visit edit_article_path(article)
fill_in 'article[title]', :with => ''
click_button 'Save'
page.has_selector?('#from-articles-edit-callback').should == true
end
end

View file

@ -1,4 +1,4 @@
//
//= require jquery.js
//= require jquery_ujs.js
//= require_tree .
//= require paloma

View file

@ -0,0 +1,3 @@
Paloma.callbacks['articles/create'] = function(params){
$('body').append($("<div id='from-articles-create-callback'></div>"));
};

View file

@ -0,0 +1,3 @@
Paloma.callbacks['articles/edit'] = function(params){
$('body').append($("<div id='from-articles-edit-callback'></div>"));
};

View file

@ -0,0 +1,3 @@
Paloma.callbacks['articles/index'] = function(params){
$('body').append($("<div id='article-count-" + params['article_count'] + "'></div>"));
};

View file

@ -0,0 +1,3 @@
Paloma.callbacks['articles/show'] = function(params){
$('body').append($("<div id='from-articles-show-callback'></div>"));
};

View file

@ -0,0 +1,3 @@
Paloma.callbacks['articles/update'] = function(params){
$('body').append($("<div id='from-articles-update-callback'></div>"));
};

View file

@ -1,3 +1,2 @@
window.Paloma = {callbacks:{}};
//= require ./paloma
//= require ./articles/callbacks

View file

@ -0,0 +1 @@
window.Paloma = {callbacks:{}};

View file

@ -0,0 +1,5 @@
<% @articles.each do |article| %>
<div>
<%= article.title %>: <%= article.body %>
</div>
<% end %>

View file

@ -5,5 +5,5 @@
Body:
<%= f.text_area :body %>
<%= f.submit %>
<%= f.submit :Save %>
<% end %>

View file

@ -5,6 +5,12 @@ end
class ArticlesController < ApplicationController
def index
@articles = Article.all
js_callback :params => {:article_count => @articles.size}
end
def show
@article = Article.find params[:id]
end
@ -17,11 +23,30 @@ class ArticlesController < ApplicationController
def create
@article = Article.new params[:article]
if @article.save
redirect_to @article
else
js_callback :new
render :new
end
end
def edit
@article = Article.find params[:id]
render :new
end
def update
@article = Article.find params[:id]
if @article.update_attributes params[:article]
js_callback false
redirect_to @article
else
js_callback :controller => :articles, :action => :edit
render :new
end
end

View file

@ -1,19 +1,22 @@
# ActiveRecord Configuration
# We are not using :memory: database to handle javascript requests on controller
require 'active_record/railtie'
ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => 'paloma_test'}}
ActiveRecord::Base.establish_connection('test')
# Model
class Article < ActiveRecord::Base
attr_accessible :title, :body
validates_presence_of :title
end
# Migration
class CreateArticles < ActiveRecord::Migration
def self.up
create_table :articles do |t|
create_table :articles, :force => true do |t|
t.string :title
t.string :body
end

BIN
spec/sample_app/paloma_test Normal file

Binary file not shown.

View file

@ -8,3 +8,14 @@ require 'rspec/rails'
require 'capybara/rspec'
require 'database_cleaner'
RSpec.configure do |config|
config.before :each do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.start
end
config.after do
DatabaseCleaner.clean
end
end