├── test_app
├── log
│ └── .gitkeep
├── .rspec
├── app
│ ├── models
│ │ └── .gitkeep
│ ├── mailers
│ │ └── .gitkeep
│ ├── helpers
│ │ ├── foo_helper.rb
│ │ ├── main_helper.rb
│ │ ├── admin
│ │ │ └── bar_helper.rb
│ │ ├── application_helper.rb
│ │ └── multiple_names_helper.rb
│ ├── views
│ │ ├── main
│ │ │ └── ajax.html.erb
│ │ └── layouts
│ │ │ └── application.html.erb
│ ├── assets
│ │ ├── images
│ │ │ └── rails.png
│ │ ├── stylesheets
│ │ │ ├── foo.css
│ │ │ ├── main.css
│ │ │ ├── admin
│ │ │ │ └── bar.css
│ │ │ ├── multiple_names.css
│ │ │ └── application.css
│ │ └── javascripts
│ │ │ ├── admin
│ │ │ └── bar.js
│ │ │ └── application.js
│ └── controllers
│ │ ├── application_controller.rb
│ │ ├── admin
│ │ └── foos_controller.rb
│ │ └── main_controller.rb
├── lib
│ ├── assets
│ │ └── .gitkeep
│ └── tasks
│ │ └── .gitkeep
├── public
│ ├── favicon.ico
│ ├── robots.txt
│ ├── 500.html
│ ├── 422.html
│ └── 404.html
├── test
│ ├── unit
│ │ └── .gitkeep
│ ├── fixtures
│ │ └── .gitkeep
│ ├── functional
│ │ └── .gitkeep
│ ├── integration
│ │ └── .gitkeep
│ ├── performance
│ │ └── browsing_test.rb
│ └── test_helper.rb
├── vendor
│ ├── plugins
│ │ └── .gitkeep
│ └── assets
│ │ ├── javascripts
│ │ └── .gitkeep
│ │ └── stylesheets
│ │ └── .gitkeep
├── Gemfile
├── config.ru
├── config
│ ├── environment.rb
│ ├── boot.rb
│ ├── initializers
│ │ ├── mime_types.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── session_store.rb
│ │ ├── secret_token.rb
│ │ ├── wrap_parameters.rb
│ │ └── inflections.rb
│ ├── locales
│ │ └── en.yml
│ ├── routes.rb
│ ├── environments
│ │ ├── development.rb
│ │ ├── test.rb
│ │ └── production.rb
│ └── application.rb
├── doc
│ └── README_FOR_APP
├── script
│ └── rails
├── db
│ └── seeds.rb
├── Rakefile
├── .gitignore
├── spec
│ ├── javascripts
│ │ ├── support
│ │ │ └── jasmine.yml
│ │ ├── controller_builder_spec.js
│ │ ├── before_callback_performer_spec.js
│ │ └── controller_class_factory_spec.js
│ ├── spec_helper.rb
│ ├── integration
│ │ ├── advanced_spec.rb
│ │ └── basic_spec.rb
│ └── units
│ │ ├── controller_spec.rb
│ │ └── utilities_spec.rb
└── README.rdoc
├── Gemfile
├── .gitignore
├── README.md
├── lib
├── paloma
│ ├── rails
│ │ └── engine.rb
│ ├── utilities.rb
│ ├── controller.rb
│ └── action_controller_extension.rb
└── paloma.rb
├── vendor
└── assets
│ └── javascripts
│ └── paloma
│ ├── base_controller.js
│ ├── index.js
│ ├── init.js
│ ├── paloma.js
│ ├── controller_builder.js
│ ├── controller_class_factory.js
│ ├── before_callback_performer.js
│ └── engine.js
├── DEVELOPMENT.md
├── app
└── views
│ └── paloma
│ └── _hook.html.erb
├── paloma.gemspec
├── MIT-LICENSE
└── CHANGELOG.md
/test_app/log/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 |
--------------------------------------------------------------------------------
/test_app/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/lib/tasks/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/test/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/test/fixtures/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/test/functional/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/vendor/plugins/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/test/integration/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/vendor/assets/javascripts/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test_app/vendor/assets/stylesheets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 | gemspec
3 |
--------------------------------------------------------------------------------
/test_app/app/helpers/foo_helper.rb:
--------------------------------------------------------------------------------
1 | module FooHelper
2 | end
3 |
--------------------------------------------------------------------------------
/test_app/app/helpers/main_helper.rb:
--------------------------------------------------------------------------------
1 | module MainHelper
2 | end
3 |
--------------------------------------------------------------------------------
/test_app/app/helpers/admin/bar_helper.rb:
--------------------------------------------------------------------------------
1 | module Admin::BarHelper
2 | end
3 |
--------------------------------------------------------------------------------
/test_app/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/test_app/app/helpers/multiple_names_helper.rb:
--------------------------------------------------------------------------------
1 | module MultipleNamesHelper
2 | end
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Gemfile.lock
2 | *.gem
3 | /tmp/*
4 | /test_app/tmp/*
5 | /test_app/spec/tmp/*
6 |
--------------------------------------------------------------------------------
/test_app/app/views/main/ajax.html.erb:
--------------------------------------------------------------------------------
1 |
Main#AJAX
2 | <%= insert_paloma_hook %>
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This fork is no longer actively maintained. Please go to https://github.com/gnclmorais/paloma
2 |
--------------------------------------------------------------------------------
/test_app/app/assets/images/rails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kbparagua/paloma/HEAD/test_app/app/assets/images/rails.png
--------------------------------------------------------------------------------
/lib/paloma/rails/engine.rb:
--------------------------------------------------------------------------------
1 | module Paloma
2 | module Rails
3 | class Engine < ::Rails::Engine
4 | end
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/test_app/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery
3 | end
4 |
--------------------------------------------------------------------------------
/test_app/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'selenium-webdriver'
4 | gem 'jquery-turbolinks'
5 | gem 'test-unit'
6 | gemspec :path => '../'
7 |
--------------------------------------------------------------------------------
/test_app/app/assets/stylesheets/foo.css:
--------------------------------------------------------------------------------
1 | /*
2 | Place all the styles related to the matching controller here.
3 | They will automatically be included in application.css.
4 | */
5 |
--------------------------------------------------------------------------------
/test_app/app/assets/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | /*
2 | Place all the styles related to the matching controller here.
3 | They will automatically be included in application.css.
4 | */
5 |
--------------------------------------------------------------------------------
/test_app/app/assets/stylesheets/admin/bar.css:
--------------------------------------------------------------------------------
1 | /*
2 | Place all the styles related to the matching controller here.
3 | They will automatically be included in application.css.
4 | */
5 |
--------------------------------------------------------------------------------
/test_app/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run TestApp::Application
5 |
--------------------------------------------------------------------------------
/test_app/app/assets/stylesheets/multiple_names.css:
--------------------------------------------------------------------------------
1 | /*
2 | Place all the styles related to the matching controller here.
3 | They will automatically be included in application.css.
4 | */
5 |
--------------------------------------------------------------------------------
/test_app/app/assets/javascripts/admin/bar.js:
--------------------------------------------------------------------------------
1 | // Place all the behaviors and hooks related to the matching controller here.
2 | // All this logic will automatically be available in application.js.
3 |
--------------------------------------------------------------------------------
/test_app/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the rails application
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the rails application
5 | TestApp::Application.initialize!
6 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/base_controller.js:
--------------------------------------------------------------------------------
1 | Paloma.BaseController = function(params){
2 | this.params = params;
3 | };
4 |
5 | Paloma.BaseController.prototype = {
6 | before: []
7 | };
8 |
9 |
--------------------------------------------------------------------------------
/test_app/config/boot.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 |
3 | # Set up gems listed in the Gemfile.
4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5 |
6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
7 |
--------------------------------------------------------------------------------
/test_app/doc/README_FOR_APP:
--------------------------------------------------------------------------------
1 | Use this README file to introduce your application and point to useful places in the API for learning more.
2 | Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
3 |
--------------------------------------------------------------------------------
/test_app/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/test_app/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/test_app/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | hello: "Hello world"
6 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/index.js:
--------------------------------------------------------------------------------
1 | //= require ./init.js
2 | //= require ./base_controller.js
3 | //= require ./controller_class_factory.js
4 | //= require ./before_callback_performer.js
5 | //= require ./controller_builder.js
6 | //= require ./engine.js
7 | //= require ./paloma.js
8 |
--------------------------------------------------------------------------------
/test_app/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/DEVELOPMENT.md:
--------------------------------------------------------------------------------
1 | # Development
2 |
3 | ## Testing
4 |
5 | 1. Go to `test_app`
6 | 1. Comment out `turbolinks.js` on `applciation.js`
7 | 1. Run `bundle exec rails s`.
8 | 1. Open your browser and visit [http://localhost:3000/specs](http://localhost:3000/specs).
9 | 1. Run `bundle exec rake spec:units`.
10 | 1. Run `bundle exec rake spec:integration`.
11 |
--------------------------------------------------------------------------------
/lib/paloma.rb:
--------------------------------------------------------------------------------
1 | module Paloma
2 | def self.root
3 | @paloma_root ||= "#{File.dirname(__FILE__)}/../"
4 | end
5 | end
6 |
7 | # TODO: Rails version checking
8 |
9 | require 'action_controller/railtie'
10 | require 'paloma/controller'
11 | require 'paloma/utilities'
12 | require 'paloma/action_controller_extension'
13 | require 'paloma/rails/engine'
14 |
--------------------------------------------------------------------------------
/test_app/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
--------------------------------------------------------------------------------
/test_app/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | if ['development', 'test'].include?(Rails.env)
8 | require 'rspec/core/rake_task'
9 | end
10 |
11 | TestApp::Application.load_tasks
12 |
--------------------------------------------------------------------------------
/test_app/test/performance/browsing_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 | require 'rails/performance_test_help'
3 |
4 | class BrowsingTest < ActionDispatch::PerformanceTest
5 | # Refer to the documentation for all available options
6 | # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]
7 | # :output => 'tmp/performance', :formats => [:flat] }
8 |
9 | def test_homepage
10 | get '/'
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test_app/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/test_app/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | TestApp::Application.config.session_store :cookie_store, key: '_test_app_session'
4 |
5 | # Use the database for sessions instead of the cookie-based default,
6 | # which shouldn't be used to store highly confidential information
7 | # (create the session table with "rails generate session_migration")
8 | # TestApp::Application.config.session_store :active_record_store
9 |
--------------------------------------------------------------------------------
/test_app/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile ~/.gitignore_global
6 |
7 | # Ignore bundler config
8 | /.bundle
9 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 |
13 | # Ignore all logfiles and tempfiles.
14 | /log/*.log
15 | /tmp
16 |
--------------------------------------------------------------------------------
/test_app/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | ENV["RAILS_ENV"] = "test"
2 | require File.expand_path('../../config/environment', __FILE__)
3 | require 'rails/test_help'
4 |
5 | class ActiveSupport::TestCase
6 | # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
7 | #
8 | # Note: You'll currently still have to declare fixtures explicitly in integration tests
9 | # -- they do not yet inherit this setting
10 | fixtures :all
11 |
12 | # Add more helper methods to be used by all tests here...
13 | end
14 |
--------------------------------------------------------------------------------
/test_app/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | TestApp::Application.config.secret_token = '0bf46521767b4f6b133f6465e3b380a8cc29cc6823770680aad8b6c34d1bce73b0aa7582d4988e2018762e90ab968e7d49477b78d197c6b7b523de6938fba964'
8 |
--------------------------------------------------------------------------------
/test_app/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 | #
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # Disable root element in JSON by default.
12 | ActiveSupport.on_load(:active_record) do
13 | self.include_root_in_json = false
14 | end
15 |
--------------------------------------------------------------------------------
/lib/paloma/utilities.rb:
--------------------------------------------------------------------------------
1 | module Paloma
2 | class Utilities
3 |
4 | def self.get_resource controller_path
5 | controller_path.split('/').map(&:titleize).join('/').gsub(' ', '')
6 | end
7 |
8 |
9 | def self.interpret_route route_string = nil
10 | raise 'Empty route cannot be interpreted' if route_string.blank?
11 |
12 | parts = route_string.split '#'
13 |
14 | resource = parts.first
15 | resource = resource.blank? ? nil : resource
16 |
17 | action = parts.length != 1 ? parts.last : nil
18 |
19 | {:resource => resource, :action => action}
20 | end
21 |
22 | end
23 | end
--------------------------------------------------------------------------------
/test_app/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format
4 | # (all these examples are active by default):
5 | # ActiveSupport::Inflector.inflections do |inflect|
6 | # inflect.plural /^(ox)$/i, '\1en'
7 | # inflect.singular /^(ox)en/i, '\1'
8 | # inflect.irregular 'person', 'people'
9 | # inflect.uncountable %w( fish sheep )
10 | # end
11 | #
12 | # These inflection rules are supported but not enabled by default:
13 | # ActiveSupport::Inflector.inflections do |inflect|
14 | # inflect.acronym 'RESTful'
15 | # end
16 |
--------------------------------------------------------------------------------
/test_app/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the top of the
9 | * compiled file, but it's generally better to create a new file per style scope.
10 | *
11 | *= require_self
12 | *= require_tree .
13 | */
14 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/init.js:
--------------------------------------------------------------------------------
1 | window.Paloma = window.Paloma || {};
2 |
3 | //
4 | // Do nothing if there is no available console.
5 | //
6 | if ( !window['console'] ){
7 | Paloma.log = Paloma.warn = function(msg){};
8 | }
9 | else {
10 | Paloma.warn = function(msg){
11 | if (Paloma.env != 'development'){ return; }
12 | console.warn(msg);
13 | };
14 |
15 | Paloma.log = function(msg){
16 | if (Paloma.env != 'development'){ return; }
17 | console.log(msg);
18 | };
19 | }
20 |
21 |
22 | if ( !window['Paloma'] ){
23 | if ( !window['console'] ){
24 | console.warn("Paloma not found. Require it in your application.js.");
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/paloma/controller.rb:
--------------------------------------------------------------------------------
1 | module Paloma
2 | class Controller
3 |
4 | attr_accessor :resource, :action, :params
5 |
6 |
7 |
8 | def initialize
9 | self.clear_request
10 | end
11 |
12 |
13 | def clear_request
14 | self.resource = nil
15 | self.action = nil
16 | self.params = {}
17 |
18 | true
19 | end
20 |
21 |
22 | def request
23 | {:resource => self.resource, :action => self.action, :params => self.params}
24 | end
25 |
26 |
27 | def has_request?
28 | self.resource.present? && self.action.present?
29 | end
30 |
31 |
32 | def has_no_request?
33 | !self.has_request?
34 | end
35 |
36 |
37 | end
38 | end
--------------------------------------------------------------------------------
/test_app/config/routes.rb:
--------------------------------------------------------------------------------
1 | TestApp::Application.routes.draw do
2 |
3 | mount JasmineRails::Engine => "/specs" if defined?(JasmineRails)
4 |
5 | root :to => 'main#index'
6 |
7 | resources :main, :controller => 'Main' do
8 | collection do
9 | get :prevent
10 | get :basic_params
11 | get :json_response
12 | get :js_response
13 | get :xml_response
14 | get :file_response
15 | get :ajax
16 | get :multiple_calls_1
17 | get :multiple_calls_2
18 | get :multiple_calls_3
19 | get :multiple_calls_4
20 | get :multiple_calls_5
21 | end
22 | end
23 |
24 |
25 | namespace :admin do
26 | resources :foos
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/test_app/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
We're sorry, but something went wrong.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/views/paloma/_hook.html.erb:
--------------------------------------------------------------------------------
1 | <% id = "#{Time.now.to_i}#{(rand * 1000).ceil}" %>
2 |
3 |
4 |
25 |
26 |
--------------------------------------------------------------------------------
/test_app/app/controllers/admin/foos_controller.rb:
--------------------------------------------------------------------------------
1 | class Admin::FoosController < ApplicationController
2 |
3 | # Default behavior
4 | def index
5 | render :inline => 'Admin/Foos#index', :layout => 'application'
6 | end
7 |
8 |
9 | # Override controller
10 | def show
11 | js 'NotAdmin/Foos', :x => 99
12 | render :inline => 'Admin/Foos#show', :layout => 'application'
13 | end
14 |
15 |
16 | # Override action
17 | def new
18 | js '#otherAction', :x => 99
19 | render :inline => 'Admin/Foos#new', :layout => 'application'
20 | end
21 |
22 |
23 | # Override controller/action
24 | def edit
25 | js 'NotAdmin/Foos#otherAction', :x => 99
26 | render :inline => 'Admin/Foos#edit', :layout => 'application'
27 | end
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/test_app/spec/javascripts/support/jasmine.yml:
--------------------------------------------------------------------------------
1 | # path to parent directory of src_files
2 | # relative path from Rails.root
3 | # defaults to app/assets/javascripts
4 | src_dir: "app/assets/javascripts"
5 | # list of file expressions to include as source files
6 | # relative path from scr_dir
7 | src_files:
8 | - "application.{js,coffee}"
9 | # path to parent directory of spec_files
10 | # relative path from Rails.root
11 | # defaults to spec/javascripts
12 | spec_dir: spec/javascripts
13 | # list of file expressions to include as helpers into spec runner
14 | # relative path from spec_dir
15 | helpers:
16 | - "helpers/**/*.{js,coffee}"
17 | # list of file expressions to include as specs into spec runner
18 | # relative path from spec_dir
19 | spec_files:
20 | - "**/*[Ss]pec.{js,coffee}"
21 |
--------------------------------------------------------------------------------
/test_app/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The change you wanted was rejected.
23 |
Maybe you tried to change something you didn't have access to.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/test_app/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The page you were looking for doesn't exist.
23 |
You may have mistyped the address or the page may have moved.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/paloma.js:
--------------------------------------------------------------------------------
1 | (function(Paloma){
2 |
3 | var classFactory = new Paloma.ControllerClassFactory(),
4 | controllerBuilder = new Paloma.ControllerBuilder(classFactory),
5 | engine = new Paloma.Engine(controllerBuilder)
6 |
7 | Paloma._controllerClassFactory = classFactory;
8 | Paloma._controllerBuilder = controllerBuilder
9 | Paloma.engine = engine;
10 |
11 | Paloma.controller = function(name, prototype){
12 | return classFactory.make(name, prototype);
13 | };
14 |
15 | Paloma._executeHook = function(){
16 | var hook = document.querySelector('.js-paloma-hook script');
17 | if (hook) eval(hook.innerHTML);
18 | };
19 |
20 | Paloma.start = function(){
21 | if ( !engine.hasRequest() ) this._executeHook();
22 | if ( engine.hasRequest() ) engine.start();
23 | };
24 |
25 | Paloma.isExecuted = function(){
26 | return engine.lastRequest().executed;
27 | };
28 |
29 | })(window.Paloma);
30 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/controller_builder.js:
--------------------------------------------------------------------------------
1 | Paloma.ControllerBuilder = function(classFactory){
2 | this.classFactory = classFactory;
3 | this.options = {};
4 | };
5 |
6 | Paloma.ControllerBuilder.prototype = {
7 |
8 | build: function(options){
9 | this.options = options;
10 |
11 | var ControllerClass = this._controllerClass();
12 | if ( !ControllerClass ) return null;
13 |
14 | var controller = new ControllerClass( this._buildParams() );
15 |
16 | controller.controller = this.options.controller;
17 | controller.action = this.options.action;
18 |
19 | return controller;
20 | },
21 |
22 | _controllerClass: function(){
23 | return this.classFactory.get( this.options.controller );
24 | },
25 |
26 | _buildParams: function(){
27 | var params = {};
28 |
29 | for (var k in this.options.params)
30 | if (this.options.params.hasOwnProperty(k))
31 | params[k] = this.options.params[k];
32 |
33 | return params;
34 | }
35 |
36 | };
37 |
--------------------------------------------------------------------------------
/paloma.gemspec:
--------------------------------------------------------------------------------
1 | Gem::Specification.new do |s|
2 | s.name = 'paloma'
3 | s.version = '5.0.0'
4 | s.summary = "Provides an easy way to execute page-specific javascript for Rails."
5 | s.description = "Page-specific javascript for Rails done right"
6 | s.authors = ['Karl Paragua']
7 | s.email = 'kb.paragua@gmail.com'
8 | s.files = `git ls-files app lib vendor`.split("\n")
9 | s.homepage = 'https://github.com/kbparagua/paloma'
10 | s.license = 'MIT'
11 |
12 | s.add_development_dependency 'jquery-rails'
13 | s.add_development_dependency 'rails', ['~> 3.2.0']
14 | s.add_development_dependency 'rake', ['>= 0']
15 | s.add_development_dependency 'rspec', ['>= 0']
16 | s.add_development_dependency 'rspec-rails', ['~> 2.0']
17 | s.add_development_dependency 'capybara', ['~> 1.0']
18 | s.add_development_dependency 'jasmine-rails', ['~> 0.4.5']
19 | s.add_development_dependency 'turbolinks', ['~> 2.2.2']
20 | s.add_development_dependency 'execjs', ['~> 2.1.0']
21 | end
22 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c) 2012 Karl Paragua
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | 'Software'), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/test_app/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | TestApp::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger
20 | config.active_support.deprecation = :log
21 |
22 | # Only use best-standards-support built into browsers
23 | config.action_dispatch.best_standards_support = :builtin
24 |
25 | # Raise exception on mass assignment protection for Active Record models
26 | # config.active_record.mass_assignment_sanitizer = :strict
27 |
28 | # Log the query plan for queries taking more than this (works
29 | # with SQLite, MySQL, and PostgreSQL)
30 | # config.active_record.auto_explain_threshold_in_seconds = 0.5
31 |
32 | # Do not compress assets
33 | config.assets.compress = false
34 |
35 | # Expands the lines which load the assets
36 | config.assets.debug = true
37 | end
38 |
--------------------------------------------------------------------------------
/test_app/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # This file is copied to spec/ when you run 'rails generate rspec:install'
2 | ENV["RAILS_ENV"] ||= 'test'
3 | require File.expand_path("../../config/environment", __FILE__)
4 | require 'rspec/rails'
5 | require 'rspec/autorun'
6 |
7 | # Requires supporting ruby files with custom matchers and macros, etc,
8 | # in spec/support/ and its subdirectories.
9 | Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
10 |
11 | RSpec.configure do |config|
12 | config.include Capybara::DSL
13 |
14 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
15 | # config.fixture_path = "#{::Rails.root}/spec/fixtures"
16 |
17 | # If you're not using ActiveRecord, or you'd prefer not to run each of your
18 | # examples within a transaction, remove the following line or assign false
19 | # instead of true.
20 | # config.use_transactional_fixtures = true
21 |
22 | # If true, the base class of anonymous controllers will be inferred
23 | # automatically. This will be the default behavior in future versions of
24 | # rspec-rails.
25 | config.infer_base_class_for_anonymous_controllers = false
26 |
27 | # Run specs in random order to surface order dependencies. If you find an
28 | # order dependency and want to debug it, you can fix the order by providing
29 | # the seed, which is printed after each run.
30 | # --seed 1234
31 | config.order = "random"
32 | end
33 |
34 |
35 | def request
36 | page.evaluate_script 'Paloma.engine.lastRequest()'
37 | end
38 |
39 | def paloma_executed?
40 | page.evaluate_script 'Paloma.isExecuted()'
41 | end
42 |
--------------------------------------------------------------------------------
/test_app/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Paloma Test App
5 | <%= stylesheet_link_tag "application", :media => "all" %>
6 | <%= javascript_include_tag "application" %>
7 | <%= csrf_meta_tags %>
8 |
9 |
10 | Paloma Test App
11 |
12 |
13 |
14 | - <%= link_to 'Main#index', main_index_path %>
15 | - <%= link_to 'Main#new', new_main_path %>
16 | - <%= link_to 'Main#show', main_path(1) %>
17 | - <%= link_to 'Main#edit', edit_main_path(1) %>
18 | - <%= link_to 'Main#prevent', prevent_main_index_path %>
19 | - <%= link_to 'Main#basic_params', basic_params_main_index_path %>
20 | - <%= link_to 'Main#multiple_calls_1', multiple_calls_1_main_index_path %>
21 | - <%= link_to 'Main#multiple_calls_2', multiple_calls_2_main_index_path %>
22 | - <%= link_to 'Main#multiple_calls_3', multiple_calls_3_main_index_path %>
23 | - <%= link_to 'Main#multiple_calls_4', multiple_calls_4_main_index_path %>
24 | - <%= link_to 'Main#multiple_calls_5', multiple_calls_5_main_index_path %>
25 | - <%= link_to 'Main#xml_response', xml_response_main_index_path %>
26 | - <%= link_to 'Main#file_response', file_response_main_index_path %>
27 | - <%= link_to 'Main#ajax', ajax_main_index_path, :id => 'js-ajax-link' %>
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | <%= yield %>
37 | <%= insert_paloma_hook %>
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/test_app/spec/integration/advanced_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | #
4 | #
5 | # All examples are using namespaces
6 | #
7 | #
8 |
9 | feature 'executing Paloma controller', :js => true do
10 |
11 |
12 | context 'default behavior' do
13 | it 'executes the same namespace/controller#action' do
14 | visit admin_foos_path
15 |
16 | expect(
17 | request['controller'] == 'Admin/Foos' &&
18 | request['action'] == 'index' &&
19 | request['params'] == {}
20 | ).to be_truthy
21 | end
22 | end
23 |
24 |
25 | context 'override default controller' do
26 | it 'executes the specified controller' do
27 | visit admin_foo_path(1)
28 |
29 | expect(
30 | request['controller'] == 'NotAdmin/Foos' &&
31 | request['action'] == 'show' &&
32 | request['params'] == {'x' => 99}
33 | ).to be_truthy
34 | end
35 | end
36 |
37 |
38 | context 'override default action' do
39 | it 'executes the specified action' do
40 | visit new_admin_foo_path
41 |
42 | expect(
43 | request['controller'] == 'Admin/Foos' &&
44 | request['action'] == 'otherAction' &&
45 | request['params'] == {'x' => 99}
46 | ).to be_truthy
47 | end
48 | end
49 |
50 |
51 | context 'override default controller/action' do
52 | it 'executes the specified controller/action' do
53 | visit edit_admin_foo_path(1)
54 |
55 | expect(
56 | request['controller'] == 'NotAdmin/Foos' &&
57 | request['action'] == 'otherAction' &&
58 | request['params'] == {'x' => 99}
59 | ).to be_truthy
60 | end
61 | end
62 |
63 |
64 | end
65 |
--------------------------------------------------------------------------------
/test_app/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | TestApp::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Raise exception on mass assignment protection for Active Record models
33 | # config.active_record.mass_assignment_sanitizer = :strict
34 |
35 | # Print deprecation notices to the stderr
36 | config.active_support.deprecation = :stderr
37 | end
38 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/controller_class_factory.js:
--------------------------------------------------------------------------------
1 | Paloma.ControllerClassFactory = function(){
2 | this._controllers = {};
3 | this._inheritanceSymbol = '<';
4 | };
5 |
6 | Paloma.ControllerClassFactory.prototype = {
7 |
8 | make: function(controllerAndParent, prototype){
9 | var parts = this._extractParts(controllerAndParent),
10 | controller = this._getOrCreate( parts.controller );
11 |
12 | this._updatePrototype(controller, prototype);
13 | this._updateParent(controller, parts.parent);
14 |
15 | return controller;
16 | },
17 |
18 | get: function(name){
19 | return this._controllers[name] || null;
20 | },
21 |
22 | _updateParent: function(controller, parent){
23 | if (!parent) return;
24 |
25 | var parentClass = this.get(parent);
26 | if (parentClass) controller.prototype.__proto__ = parentClass.prototype;
27 | },
28 |
29 | _updatePrototype: function(controller, newPrototype){
30 | for (var k in newPrototype)
31 | if (newPrototype.hasOwnProperty(k))
32 | controller.prototype[k] = newPrototype[k];
33 | },
34 |
35 | _getOrCreate: function(name){
36 | return this.get(name) || this._create(name);
37 | },
38 |
39 | _create: function(name){
40 | var controller = function(params){
41 | Paloma.BaseController.call(this, params);
42 | };
43 |
44 | controller.prototype.__proto__ = Paloma.BaseController.prototype;
45 |
46 | this._controllers[name] = controller;
47 | return controller;
48 | },
49 |
50 | _extractParts: function(controllerAndParent){
51 | var parts = controllerAndParent.split( this._inheritanceSymbol );
52 |
53 | var controller = parts[0].trim(),
54 | parent = parts[1];
55 |
56 | if (parent) parent = parent.trim();
57 |
58 | return {controller: controller, parent: parent};
59 | }
60 |
61 | };
62 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/before_callback_performer.js:
--------------------------------------------------------------------------------
1 | Paloma.BeforeCallbackPerformer = function(controller){
2 | this.controller = controller;
3 | this.entries = controller.before;
4 | this.action = null;
5 | };
6 |
7 | Paloma.BeforeCallbackPerformer.prototype = {
8 |
9 | perform: function(action){
10 | this.action = action;
11 | this._executeCallbacks();
12 | },
13 |
14 | _executeCallbacks: function(){
15 | for (var i = 0, n = this._callbacks().length; i < n; i++)
16 | this._executeCallback( this._callbacks()[i] );
17 | },
18 |
19 | _executeCallback: function(name){
20 | var callback = this.controller[name];
21 | if (callback) callback.call(this.controller);
22 | },
23 |
24 | _callbacks: function(){
25 | if (this._callbackList) return this._callbackList;
26 |
27 | this._callbackList = [];
28 |
29 | for (var i = 0, n = this.entries.length; i < n; i++){
30 | var entry = this.entries[i];
31 |
32 | this._callbackList =
33 | this._callbackList.concat( this._getCallbacksIfForAction(entry) );
34 | }
35 |
36 | return this._callbackList;
37 | },
38 |
39 | _getCallbacksIfForAction: function(entry){
40 | var parsedEntry = this._parseEntry(entry);
41 |
42 | if (
43 | this._actionIsOn(parsedEntry.actions) ||
44 | this._allIsOn(parsedEntry.actions)
45 | )
46 | return parsedEntry.callbacks;
47 |
48 | return [];
49 | },
50 |
51 | _actionIsOn: function(actions){
52 | return actions.indexOf(this.action) != -1;
53 | },
54 |
55 | _allIsOn: function(actions){
56 | return actions.indexOf('all') != -1;
57 | },
58 |
59 | _parseEntry: function(entry){
60 | var parts = entry.split('->'),
61 | data = {actions: [], callbacks: []};
62 |
63 | if (parts[0]) data.actions = parts[0].trim().split(' ');
64 | if (parts[1]) data.callbacks = parts[1].trim().split(' ');
65 |
66 | return data;
67 | }
68 |
69 | };
70 |
--------------------------------------------------------------------------------
/test_app/spec/javascripts/controller_builder_spec.js:
--------------------------------------------------------------------------------
1 | describe('Paloma.ControllerBuilder', function(){
2 |
3 | var TestController = Paloma.controller('Test');
4 |
5 |
6 | describe('#build(options)', function(){
7 |
8 | describe('when options.controller has no match', function(){
9 | var factory = {get: function(controller){ return null; }},
10 | builder = new Paloma.ControllerBuilder(factory);
11 |
12 | it('returns null', function(){
13 | var options = {controller: 'Test', action: 'show'};
14 | expect( builder.build(options) ).toBeNull();
15 | });
16 | });
17 |
18 | describe('when options.controller has a match', function(){
19 | var factory = {get: function(controller){ return TestController; }},
20 | builder = new Paloma.ControllerBuilder(factory);
21 |
22 | var options = {
23 | controller: 'Test',
24 | action: 'show',
25 | params: {a: 1, b: 2}
26 | };
27 |
28 | var controller = builder.build(options);
29 |
30 | it('returns a new instance of the controller class', function(){
31 | expect(controller instanceof TestController).toBeTruthy();
32 | });
33 |
34 | it("initializes controller instance's params property", function(){
35 | var expectedParams = {a: 1, b: 2};
36 | var correct = true;
37 |
38 | for (var k in expectedParams)
39 | if (controller.params[k] != expectedParams[k]) correct = false;
40 |
41 | for (var k in controller.params)
42 | if (expectedParams[k] != controller.params[k]) correct = false;
43 |
44 | expect(correct).toBeTruthy();
45 | });
46 |
47 | it("initializes controller instance's controller property", function(){
48 | expect(controller.controller).toEqual('Test');
49 | });
50 |
51 | it("initializes controller instance's action property", function(){
52 | expect(controller.action).toEqual('show');
53 | });
54 | });
55 |
56 | });
57 |
58 | });
59 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/paloma/engine.js:
--------------------------------------------------------------------------------
1 | Paloma.Engine = function(controllerBuilder){
2 | this.controllerBuilder = controllerBuilder;
3 | this._clearRequest();
4 | };
5 |
6 | Paloma.Engine.prototype = {
7 |
8 | setRequest: function(options){
9 | this._request = {
10 | id: options.id,
11 | controller: options.resource,
12 | action: options.action,
13 | params: options.params,
14 | executed: false
15 | };
16 | },
17 |
18 | hasRequest: function(){
19 | return this._request != null;
20 | },
21 |
22 | lastRequest: function(){
23 | return this._lastRequest = this._lastRequest || {executed: false};
24 | },
25 |
26 | start: function(){
27 | if ( this._shouldStop() ) return;
28 |
29 | this._logRequest();
30 | this._lastRequest = this._request;
31 |
32 | this._executeControllerAction();
33 | this._clearRequest();
34 | },
35 |
36 | _executeControllerAction: function(){
37 | var controller = this._buildController();
38 | if (!controller) return;
39 |
40 | var callbackPerformer = new Paloma.BeforeCallbackPerformer(controller);
41 | callbackPerformer.perform( this._request.action );
42 |
43 | var method = controller[ this._request.action ];
44 | if (method) method.call(controller);
45 |
46 | this._lastRequest.executed = true;
47 | },
48 |
49 | _buildController: function(){
50 | return this.controllerBuilder.build({
51 | controller: this._request.controller,
52 | action: this._request.action,
53 | params: this._request.params
54 | });
55 | },
56 |
57 | _shouldStop: function(){
58 | if ( !this.hasRequest() ) return true;
59 | if ( this._request.id == this.lastRequest().id ) return true;
60 |
61 | return false;
62 | },
63 |
64 | _logRequest: function(){
65 | Paloma.log(
66 | 'Paloma: ' + this._request.controller + '#' +
67 | this._request.action + ' with params:'
68 | );
69 |
70 | Paloma.log( this._request.params );
71 | },
72 |
73 | _clearRequest: function(){
74 | this._request = null;
75 | }
76 |
77 | };
78 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 5.0.0
2 | * https://github.com/kbparagua/paloma/issues/84 - Easier syntax for creating controllers.
3 | * https://github.com/kbparagua/paloma/issues/56 - Paloma should be started manually using `Paloma.start()`.
4 | * Introduced before callbacks.
5 | - https://github.com/kbparagua/paloma/issues/41
6 | - https://github.com/kbparagua/paloma/issues/30
7 | * Create `controller` and `action` property for Paloma controllers.
8 | * Remove jQuery dependency.
9 |
10 | ## 4.2.1
11 | * https://github.com/kbparagua/paloma/issues/79 - Rendering "true" string fixed.
12 | * Catch situations where `js` function is called more than once.
13 |
14 | ## 4.2.0
15 | * https://github.com/kbparagua/paloma/pull/75 - Explicitly insert hook in view.
16 |
17 | ## 4.1.2
18 | * https://github.com/kbparagua/paloma/issues/73 - Fix `js false` issue.
19 |
20 | ## 4.1.1
21 | * https://github.com/kbparagua/paloma/pull/57 - Fix Turbolinks Issues.
22 | * https://github.com/kbparagua/paloma/pull/55 - Fix issues when Paloma hook is not found.
23 |
24 | ## 4.1.0
25 | * Support for Turbolinks.
26 | * `Paloma.executeHook()` to manually run the hook from the DOM.
27 | * Paloma hook will be appended using all `render` calls, except for calls that has the following keys `[:json, :js, :xml, :file]`.
28 | * Restore `Paloma.engine.start()` to start processing queued request.
29 |
30 |
31 | ## 4.0.0
32 | * https://github.com/kbparagua/paloma/issues/26 - Paloma requests are not saved on `session`.
33 | * https://github.com/kbparagua/paloma/issues/26 - Chaining with redirect is removed.
34 | * Routing from javascript is removed.
35 | * Routing from Rails controller is added.
36 | * Ability to have a controller-wide setting.
37 | * https://github.com/kbparagua/paloma/issues/29 - Disable `console.log` and `console.warn` for non-development environments.
38 |
39 |
40 | ## 3.0.2
41 | * Bug Fix: Converting Rails controller name to singular form.
42 |
43 |
44 | ## 3.0.1
45 | * Bug Fix: Can't handle Rails controller with Multi-word name.
46 | * Bug Fix: Paloma Engine is halting when a warning is encountered.
47 | * Don't create Paloma request if rendering js, json, xml, or file.
48 |
49 |
50 | ## 3.0.0
51 | * Rewrite Initial Release
52 |
--------------------------------------------------------------------------------
/test_app/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // the compiled file.
9 | //
10 | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11 | // GO AFTER THE REQUIRES BELOW.
12 | //
13 | //= require jquery
14 | //=# require jquery.turbolinks
15 | //= require jquery_ujs
16 | //=# require turbolinks
17 | //= require paloma
18 | //= require_tree .
19 |
20 |
21 | // Uncomment if jquery.turbolinks is not used.
22 | // $(document).on('page:load', function(){ Paloma.start(); });
23 |
24 |
25 | //
26 | //
27 | // Controllers
28 | //
29 | //
30 |
31 | var blank = function(){};
32 |
33 | Paloma.controller('Application', {
34 |
35 | // before: [
36 | // 'all -> logRequest',
37 | // 'show index -> askUser changeBackground'
38 | // ],
39 |
40 | before: [
41 | 'all -> performThis',
42 | 'show -> doSomething'
43 | ],
44 |
45 | index: function(){
46 | console.log('Inherited');
47 | },
48 |
49 | doSomething: function(){
50 | console.log('Do something');
51 | },
52 |
53 | performThis: function(){
54 | console.log('Perform This!');
55 | }
56 |
57 | });
58 |
59 | Paloma.controller('Main < Application', {
60 | otherAction: blank,
61 | prevent: blank,
62 | basic_params: blank,
63 | multiple_calls_1: blank
64 | });
65 |
66 |
67 | Paloma.controller('OtherMain < Application', {
68 | show: blank,
69 | otherAction: blank,
70 | multiple_calls_2: blank
71 | });
72 |
73 | Paloma.controller('Admins/Foos', {
74 | index: blank,
75 | otherAction: blank
76 | });
77 |
78 | Paloma.controller('NotAdmin/Foos', {
79 | show: blank,
80 | otherAction: blank
81 | });
82 |
83 |
84 | $(document).ready(function(){
85 | Paloma.start();
86 |
87 | $('#js-ajax-link').on('click', function(e){
88 | e.preventDefault();
89 |
90 | $.get($(this).prop('href'), function(response){
91 | $('#js-ajax-response').html(response);
92 | Paloma.start();
93 | });
94 | });
95 | });
96 |
--------------------------------------------------------------------------------
/test_app/app/controllers/main_controller.rb:
--------------------------------------------------------------------------------
1 | class MainController < ApplicationController
2 |
3 | # Default behavior
4 | def index
5 | render :inline => 'Main#index', :layout => 'application'
6 | end
7 |
8 |
9 | # Override controller
10 | def show
11 | js 'OtherMain', :x => 1
12 | render :inline => 'Main#show', :layout => 'application'
13 | end
14 |
15 |
16 | # Override action
17 | def new
18 | js :otherAction, :x => 1
19 | render :inline => 'Main#new', :layout => 'application'
20 | end
21 |
22 |
23 | # Override controller/action
24 | def edit
25 | js 'OtherMain#otherAction', :x => 1
26 | render :inline => 'Main#edit', :layout => 'application'
27 | end
28 |
29 |
30 | def multiple_calls_1
31 | js false
32 | js :x => 70
33 | render :inline => 'Main#multiple_calls', :layout => 'application'
34 | end
35 |
36 |
37 | def multiple_calls_2
38 | js false
39 | js 'OtherMain'
40 | render :inline => 'Main#multiple_calls_2', :layout => 'application'
41 | end
42 |
43 |
44 | def multiple_calls_3
45 | js 'OtherMain'
46 | js :show
47 | render :inline => 'Main#multiple_calls_3', :layout => 'application'
48 | end
49 |
50 |
51 | def multiple_calls_4
52 | js 'OtherMain#show'
53 | js false
54 | render :inline => 'Main#multiple_calls_4', :layout => 'application'
55 | end
56 |
57 |
58 | def multiple_calls_5
59 | js false
60 | js true
61 | render :inline => 'Main#multiple_calls_5', :layout => 'application'
62 | end
63 |
64 |
65 |
66 |
67 | # Stop paloma from execution
68 | def prevent
69 | js false
70 | render :inline => 'Main#prevent', :layout => 'application'
71 | end
72 |
73 |
74 | def basic_params
75 | js :x => 1, :y => 2
76 | render :inline => 'Main#basic_params', :layout => 'application'
77 | end
78 |
79 |
80 | def ajax
81 | render :ajax, :layout => false
82 | end
83 |
84 |
85 |
86 |
87 |
88 | #
89 | # Non-HTML response
90 | #
91 |
92 | def json_response
93 | render :json => {:x => 1}
94 | end
95 |
96 |
97 | def js_response
98 | render :js => 'alert(1);'
99 | end
100 |
101 |
102 | def xml_response
103 | render :xml => 'test'
104 | end
105 |
106 |
107 | def file_response
108 | render :file => "#{Rails.root}/Gemfile", :layout => false
109 | end
110 |
111 | end
112 |
--------------------------------------------------------------------------------
/test_app/spec/units/controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 |
4 | describe Paloma::Controller do
5 |
6 | let(:controller){ Paloma::Controller.new }
7 |
8 |
9 | before do
10 | controller.resource = 'Test'
11 | controller.action = 'new'
12 | controller.params = {:x => 1, :y => 2}
13 | end
14 |
15 |
16 |
17 | shared_examples 'request is cleared' do
18 | it 'assigns nil to resource' do
19 | expect(controller.resource).to be_nil
20 | end
21 |
22 |
23 | it 'assigns nil to action' do
24 | expect(controller.action).to be_nil
25 | end
26 |
27 |
28 | it 'assigns an empty hash to params' do
29 | expect(controller.params).to be_empty
30 | end
31 |
32 |
33 | it 'returns true' do
34 | expect(@return).to be_true
35 | end
36 | end
37 |
38 |
39 |
40 | shared_examples 'request is not cleared' do
41 | it 'returns false' do
42 | expect(@return).to be_false
43 | end
44 |
45 |
46 | it 'has a request' do
47 | expect(controller.has_request?).to be_true
48 | end
49 | end
50 |
51 |
52 |
53 |
54 |
55 | describe '#clear_request' do
56 | before { @return = controller.clear_request }
57 | it_behaves_like 'request is cleared'
58 | end
59 |
60 |
61 |
62 | describe '#request' do
63 | it 'returns a hash object' do
64 | expect(controller.request).to be_an_instance_of Hash
65 | end
66 |
67 |
68 | it 'returns the current value of resource' do
69 | expect(controller.request[:resource]).to eq 'Test'
70 | end
71 |
72 |
73 | it 'returns the current value of action' do
74 | expect(controller.request[:action]).to eq 'new'
75 | end
76 |
77 |
78 | it 'returns the current value of params' do
79 | expect(controller.request[:params]).to eq ({:x => 1, :y => 2})
80 | end
81 | end
82 |
83 |
84 |
85 | describe '#has_request?' do
86 | context 'when resource is nil' do
87 | it 'returns false' do
88 | controller.resource = nil
89 | expect(controller.has_request?).to be_false
90 | end
91 | end
92 |
93 |
94 | context 'when action is nil' do
95 | it 'returns false' do
96 | controller.action = nil
97 | expect(controller.has_request?).to be_false
98 | end
99 | end
100 |
101 |
102 | context 'when resource and action is present' do
103 | it 'returns true' do
104 | expect(controller.has_request?).to be_true
105 | end
106 | end
107 | end
108 |
109 | end
110 |
--------------------------------------------------------------------------------
/test_app/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | TestApp::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = false
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = true
22 |
23 | # Defaults to nil and saved in location specified by config.assets.prefix
24 | # config.assets.manifest = YOUR_PATH
25 |
26 | # Specifies the header that your server uses for sending files
27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29 |
30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31 | # config.force_ssl = true
32 |
33 | # See everything in the log (default is :info)
34 | # config.log_level = :debug
35 |
36 | # Prepend all log lines with the following tags
37 | # config.log_tags = [ :subdomain, :uuid ]
38 |
39 | # Use a different logger for distributed setups
40 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
41 |
42 | # Use a different cache store in production
43 | # config.cache_store = :mem_cache_store
44 |
45 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
46 | # config.action_controller.asset_host = "http://assets.example.com"
47 |
48 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
49 | # config.assets.precompile += %w( search.js )
50 |
51 | # Disable delivery errors, bad email addresses will be ignored
52 | # config.action_mailer.raise_delivery_errors = false
53 |
54 | # Enable threaded mode
55 | # config.threadsafe!
56 |
57 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
58 | # the I18n.default_locale when a translation can not be found)
59 | config.i18n.fallbacks = true
60 |
61 | # Send deprecation notices to registered listeners
62 | config.active_support.deprecation = :notify
63 |
64 | # Log the query plan for queries taking more than this (works
65 | # with SQLite, MySQL, and PostgreSQL)
66 | # config.active_record.auto_explain_threshold_in_seconds = 0.5
67 | end
68 |
--------------------------------------------------------------------------------
/test_app/spec/javascripts/before_callback_performer_spec.js:
--------------------------------------------------------------------------------
1 | describe('Paloma.BeforeCallbackPerformer', function(){
2 | describe('#perform(action)', function(){
3 |
4 | var Controller = Paloma.controller('MyController', {
5 | before: [
6 | 'all -> initialize doThat',
7 | 'singleCallback unknown -> doSomething',
8 | 'multiCallback -> doSomething doAnotherThing'
9 | ],
10 |
11 | initialize: function(){
12 | this.didWhat = [];
13 | },
14 |
15 | did: function(what){ return this.didWhat.indexOf(what) >= 0; },
16 |
17 | noCallback: function(){ console.log('I have no callback.'); },
18 | singleCallback: function(){ console.log('Single callback.'); },
19 | multiCallback: function(){ console.log('Multiple callbacks.')},
20 |
21 | doThat: function(){ this.didWhat.push('that'); },
22 | doSomething: function(){ this.didWhat.push('something'); },
23 | doAnotherThing: function(){ this.didWhat.push('anotherThing') }
24 | });
25 |
26 | function itPerformsCallbackForAll(controller){
27 | it('performs callback for all', function(){
28 | expect( controller.did('that') ).toBeTruthy();
29 | });
30 | };
31 |
32 | describe('when there is no matched callback', function(){
33 | var controller = new Controller(),
34 | performer = new Paloma.BeforeCallbackPerformer(controller);
35 |
36 | performer.perform('noCallback');
37 |
38 | it('will not perform any callback', function(){
39 | expect( controller.did('something') ).toBeFalsy();
40 | });
41 |
42 | itPerformsCallbackForAll(controller);
43 | });
44 |
45 | describe('when there is one matched callback', function(){
46 | var controller = new Controller(),
47 | performer = new Paloma.BeforeCallbackPerformer(controller);
48 |
49 | performer.perform('singleCallback');
50 |
51 | it('will perform the matched callback', function(){
52 | expect( controller.did('something') ).toBeTruthy();
53 | });
54 |
55 | itPerformsCallbackForAll(controller);
56 | });
57 |
58 | describe('when there is more than one matched callbacks', function(){
59 | var controller = new Controller(),
60 | performer = new Paloma.BeforeCallbackPerformer(controller);
61 |
62 | performer.perform('multiCallback');
63 |
64 | it('will perform all the matched callbacks', function(){
65 | expect( controller.did('something') && controller.did('anotherThing') ).
66 | toBeTruthy();
67 | });
68 |
69 | it('will perform the callbacks in order of definition', function(){
70 | expect(controller.didWhat).toEqual([
71 | 'that', 'something', 'anotherThing'
72 | ]);
73 | });
74 |
75 | itPerformsCallbackForAll(controller);
76 | });
77 |
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/test_app/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | require "action_controller/railtie"
4 | require "action_mailer/railtie"
5 | require "active_resource/railtie"
6 | require "sprockets/railtie"
7 | require "rails/test_unit/railtie"
8 | require 'jquery-rails'
9 |
10 |
11 |
12 | if defined?(Bundler)
13 | # If you precompile assets before deploying to production, use this line
14 | Bundler.require(*Rails.groups(:assets => %w(development test)))
15 | # If you want your assets lazily compiled in production, use this line
16 | # Bundler.require(:default, :assets, Rails.env)
17 | end
18 |
19 | module TestApp
20 | class Application < Rails::Application
21 | # Settings in config/environments/* take precedence over those specified here.
22 | # Application configuration should go into files in config/initializers
23 | # -- all .rb files in that directory are automatically loaded.
24 |
25 | # Custom directories with classes and modules you want to be autoloadable.
26 | # config.autoload_paths += %W(#{config.root}/extras)
27 |
28 | # Only load the plugins named here, in the order given (default is alphabetical).
29 | # :all can be used as a placeholder for all plugins not explicitly named.
30 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
31 |
32 | # Activate observers that should always be running.
33 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
34 |
35 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
36 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
37 | # config.time_zone = 'Central Time (US & Canada)'
38 |
39 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
40 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
41 | # config.i18n.default_locale = :de
42 |
43 | # Configure the default encoding used in templates for Ruby 1.9.
44 | config.encoding = "utf-8"
45 |
46 | # Configure sensitive parameters which will be filtered from the log file.
47 | config.filter_parameters += [:password]
48 |
49 | # Enable escaping HTML in JSON.
50 | config.active_support.escape_html_entities_in_json = true
51 |
52 | # Use SQL instead of Active Record's schema dumper when creating the database.
53 | # This is necessary if your schema can't be completely dumped by the schema dumper,
54 | # like if you have constraints or database-specific column types
55 | # config.active_record.schema_format = :sql
56 |
57 | # Enforce whitelist mode for mass assignment.
58 | # This will create an empty whitelist of attributes available for mass-assignment for all models
59 | # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
60 | # parameters by using an attr_accessible or attr_protected declaration.
61 | #config.active_record.whitelist_attributes = true
62 |
63 | # Enable the asset pipeline
64 | config.assets.enabled = true
65 |
66 | # Version of your assets, change this if you want to expire all your assets
67 | config.assets.version = '1.0'
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/test_app/spec/units/utilities_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 |
4 | describe Paloma::Utilities do
5 |
6 | let(:utilities){ Paloma::Utilities }
7 |
8 |
9 |
10 | describe '.get_resource(path)' do
11 | context 'when path is only 1 word' do
12 | it 'returns the controller resource name' do
13 | expect(utilities.get_resource('test')).to eq 'Test'
14 | end
15 | end
16 |
17 |
18 | context 'when path is more than 1 word' do
19 | it 'returns the controller resource name' do
20 | expect(utilities.get_resource('my_super_resources')).to eq 'MySuperResources'
21 | end
22 | end
23 |
24 |
25 | context 'when path has namespace' do
26 | it 'returns "Namespace/Resource"' do
27 | expect(utilities.get_resource('admin/my_mega_test')).to eq 'Admin/MyMegaTest'
28 | end
29 | end
30 |
31 |
32 | context 'when path has 2 or more namespace' do
33 | it 'returns "Namespace1/NamespaceN/Resource' do
34 | expect(utilities.get_resource('admin/test/my_resources')).to eq 'Admin/Test/MyResources'
35 | end
36 | end
37 | end
38 |
39 |
40 |
41 |
42 |
43 | shared_examples 'resource is passed' do |resource|
44 | it 'returns its returned as the resource' do
45 | expect(route[:resource]).to eq resource
46 | end
47 | end
48 |
49 |
50 | shared_examples 'action is passed' do |action|
51 | it 'returns the action' do
52 | expect(route[:action]).to eq action
53 | end
54 | end
55 |
56 |
57 | shared_examples 'resource is not passed' do
58 | it 'returns a nil resource' do
59 | expect(route[:resource]).to be_nil
60 | end
61 | end
62 |
63 |
64 | shared_examples 'action is not passed' do
65 | it 'returns a nil action' do
66 | expect(route[:action]).to be_nil
67 | end
68 | end
69 |
70 |
71 |
72 |
73 |
74 | describe '.interpret_route(route_string)' do
75 | context 'when route_string is empty' do
76 | it 'raises an error' do
77 | expect { utilities.interpret_route }.to raise_error 'Empty route cannot be interpreted'
78 | end
79 | end
80 |
81 |
82 | context 'when route_string has a word' do
83 | let(:route){ utilities.interpret_route 'MyResources' }
84 |
85 | it_behaves_like 'resource is passed', 'MyResources'
86 | it_behaves_like 'action is not passed'
87 | end
88 |
89 |
90 | context 'when route_string has a namespace' do
91 | let(:route){ utilities.interpret_route 'Namespace/MyResource' }
92 |
93 | it_behaves_like 'resource is passed', 'Namespace/MyResource'
94 | it_behaves_like 'action is not passed'
95 | end
96 |
97 |
98 | context 'when route_string has an action' do
99 | let(:route){ utilities.interpret_route 'Namespace/MyResources#action' }
100 |
101 | it_behaves_like 'resource is passed', 'Namespace/MyResources'
102 | it_behaves_like 'action is passed', 'action'
103 | end
104 |
105 |
106 | context 'when route_string has action only' do
107 | let(:route){ utilities.interpret_route '#edit' }
108 |
109 | it_behaves_like 'resource is not passed'
110 | it_behaves_like 'action is passed', 'edit'
111 | end
112 | end
113 |
114 | end
--------------------------------------------------------------------------------
/test_app/spec/javascripts/controller_class_factory_spec.js:
--------------------------------------------------------------------------------
1 | describe('Paloma.ControllerClassFactory', function(){
2 |
3 | var _factory = null;
4 | function factory(){ return _factory; }
5 |
6 | function newFactory(){
7 | _factory = new Paloma.ControllerClassFactory();
8 | return _factory;
9 | }
10 |
11 |
12 |
13 | describe('#make(controllerAndParent, prototype)', function(){
14 | describe('when controller is not yet existing', function(){
15 | it('creates a new controller', function(){
16 | var controller = newFactory().make('MyController'),
17 | instance = new controller();
18 |
19 | expect(instance instanceof Paloma.BaseController).toBeTruthy();
20 | });
21 |
22 | describe('when prototype is present', function(){
23 | it('adds the prototype to the controller', function(){
24 | var controller = newFactory().make('MyController', {a: 100});
25 |
26 | expect(controller.prototype.a).toEqual(100);
27 | });
28 | });
29 |
30 | describe('when parent is present', function(){
31 | it('creates a subclass of that parent', function(){
32 | var parent = newFactory().make('Parent'),
33 | child = factory().make('Child < Parent');
34 |
35 | var controller = new child();
36 | expect(controller instanceof parent).toBeTruthy();
37 | });
38 | });
39 | });
40 |
41 | describe('when controller is already existing', function(){
42 | it('returns the existing controller', function(){
43 | var controller = newFactory().make('test2');
44 | expect( factory().make('test2') ).toEqual(controller);
45 | });
46 |
47 | describe('when prototype is present', function(){
48 | var controller = newFactory().make('Test', {number: 9});
49 | factory().make('Test', {number: 10});
50 |
51 | it('updates the current prototype', function(){
52 | expect(controller.prototype.number).toEqual(10);
53 | });
54 | });
55 |
56 | describe('when parent is present', function(){
57 | var oldParent = newFactory().make('OldParent'),
58 | newParent = factory().make('NewParent');
59 |
60 | describe('when no previous parent', function(){
61 | var child = factory().make('ChildA');
62 | factory().make('ChildA < NewParent');
63 |
64 | var instance = new child();
65 |
66 | it('assigns the new parent', function(){
67 | expect(instance instanceof newParent).toBeTruthy();
68 | });
69 | });
70 |
71 | describe('when has previous parent', function(){
72 | var child = factory().make('ChildB < OldParent');
73 | factory().make('ChildB < NewParent');
74 |
75 | var instance = new child();
76 |
77 | it('updates removes the oldParent', function(){
78 | expect(instance instanceof oldParent).toBeFalsy();
79 | });
80 |
81 | it('assigns the new parent', function(){
82 | expect(instance instanceof newParent).toBeTruthy();
83 | });
84 | });
85 | });
86 | });
87 | });
88 |
89 | describe('#get(name)', function(){
90 | describe('when name has no match', function(){
91 | it('returns null', function(){
92 | expect( newFactory().get('unknown') ).toBeNull();
93 | });
94 | });
95 |
96 | describe('when name has match', function(){
97 | it('returns the matched controller', function(){
98 | var controller = newFactory().make('myController');
99 | expect( factory().get('myController') ).toEqual(controller);
100 | });
101 | });
102 | });
103 |
104 | });
105 |
--------------------------------------------------------------------------------
/lib/paloma/action_controller_extension.rb:
--------------------------------------------------------------------------------
1 | module Paloma
2 |
3 |
4 | module ActionControllerExtension
5 |
6 | def self.included base
7 | base.send :include, InstanceMethods
8 | base.send :extend, ClassMethods
9 |
10 |
11 | base.module_eval do
12 | prepend_view_path "#{Paloma.root}/app/views/"
13 |
14 | before_filter :track_paloma_request
15 | helper_method :insert_paloma_hook
16 | end
17 | end
18 |
19 |
20 |
21 |
22 |
23 | module ClassMethods
24 |
25 | #
26 | # Controller wide setting for Paloma.
27 | #
28 |
29 | def js path_or_options, options = {}
30 | options ||= {}
31 |
32 | scope = {}
33 | scope[:only] = options[:only] if options[:only]
34 | scope[:except] = options[:except] if options[:except]
35 |
36 | self.before_filter(
37 | Proc.new {
38 | self.js path_or_options, options[:params]
39 | },
40 | scope)
41 | end
42 | end
43 |
44 |
45 |
46 |
47 |
48 | module InstanceMethods
49 |
50 | #
51 | #
52 | # Specify the behavior of Paloma. Call this manually to override the
53 | # default Paloma controller/action to be executed.
54 | #
55 | # Can call a different Controller or execute a different action, and
56 | # pass parameters.
57 | #
58 | # NOTE:
59 | # Calling this more than once in a single action will not clear
60 | # the previous config from the previous call.
61 | #
62 | # Example:
63 | # def new
64 | # js 'MyController#new'
65 | # js :edit
66 | # js :x => 1, :y => 2
67 | #
68 | # # Paloma will execute JS for
69 | # # MyController#edit and will pass the parameters :x => 1, :y => 2
70 | # end
71 | #
72 | # Usage:
73 | #
74 | # js 'Controller', {params}
75 | # js 'Controller#action', {params}
76 | # js 'Namespace/Controller', {params}
77 | # js 'Namespace/Controller#action', {params}
78 | # js '#action', {params}
79 | # js :action, {params}
80 | # js :param_1 => 1, :param_2 => 2
81 | # js true
82 | # js false
83 | #
84 | #
85 | def js path_or_options, params = {}
86 | return self.paloma.clear_request if !path_or_options
87 |
88 | self.paloma.params.merge! params || {}
89 |
90 | #
91 | # 'Controller'
92 | # 'Controller#action'
93 | # 'Namespace/Controller'
94 | # 'Namespace/Controller#action'
95 | # '#action'
96 | #
97 | if path_or_options.is_a? String
98 | route = ::Paloma::Utilities.interpret_route path_or_options
99 | self.paloma.resource = route[:resource] if route[:resource].present?
100 | self.paloma.action = route[:action] if route[:action].present?
101 |
102 | # :action
103 | elsif path_or_options.is_a? Symbol
104 | self.paloma.action = path_or_options
105 |
106 | # :param_1 => 1, :param_2 => 2
107 | elsif path_or_options.is_a? Hash
108 | self.paloma.params.merge! path_or_options || {}
109 |
110 | elsif path_or_options != true
111 | raise "Paloma: Invalid argument (#{path_or_options}) for js method"
112 | end
113 |
114 | self.paloma.resource ||= self.default_resource
115 | self.paloma.action ||= self.default_action
116 | end
117 |
118 |
119 | #
120 | # Executed every time a controller action is executed.
121 | #
122 | # Keeps track of what Rails controller/action is executed.
123 | #
124 | def track_paloma_request
125 | self.paloma.resource ||= self.default_resource
126 | self.paloma.action ||= self.default_action
127 | end
128 |
129 |
130 | #
131 | # Call in your view to insert Paloma's html hook.
132 | #
133 | # The html hook contains the javascript code that
134 | # will execute the tracked Paloma requests.
135 | #
136 | def insert_paloma_hook
137 | return nil if self.paloma.has_no_request?
138 |
139 | hook = view_context.render(
140 | :partial => 'paloma/hook',
141 | :locals => {:request => self.paloma.request})
142 |
143 | self.paloma.clear_request
144 | hook
145 | end
146 | end
147 |
148 |
149 |
150 |
151 |
152 | protected
153 |
154 | def paloma
155 | @paloma ||= ::Paloma::Controller.new
156 | end
157 |
158 |
159 | def default_resource
160 | ::Paloma::Utilities.get_resource self.controller_path
161 | end
162 |
163 |
164 | def default_action
165 | self.action_name
166 | end
167 |
168 | end
169 |
170 |
171 | ::ActionController::Base.send :include, ActionControllerExtension
172 | end
173 |
--------------------------------------------------------------------------------
/test_app/spec/integration/basic_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | #
4 | #
5 | # All examples are not using namespaces.
6 | #
7 | #
8 |
9 | feature 'executing Paloma controller', :js => true do
10 |
11 | #
12 | #
13 | # Basic
14 | # All except for basic_params and index action will pass :x => 1 parameter
15 | #
16 | #
17 |
18 | context 'default behavior' do
19 | it 'executes the same controller/action' do
20 | visit main_index_path
21 |
22 | expect(
23 | request['controller'] == 'Main' &&
24 | request['action'] == 'index' &&
25 | request['params'] == {}
26 | ).to be_truthy
27 | end
28 | end
29 |
30 |
31 | context 'override default controller' do
32 | it 'executes the specified controller' do
33 | visit main_path(1)
34 |
35 | expect(
36 | request['controller'] == 'OtherMain' &&
37 | request['action'] == 'show' &&
38 | request['params'] == {'x' => 1}
39 | ).to be_truthy
40 | end
41 | end
42 |
43 |
44 | context 'override default action' do
45 | it 'executes the specified action' do
46 | visit new_main_path
47 |
48 | expect(
49 | request['controller'] == 'Main' &&
50 | request['action'] == 'otherAction' &&
51 | request['params'] == {'x' => 1}
52 | ).to be_truthy
53 | end
54 | end
55 |
56 |
57 | context 'override default controller/action' do
58 | it 'executes the specified controller/action' do
59 | visit edit_main_path(1)
60 |
61 | expect(
62 | request['controller'] == 'OtherMain' &&
63 | request['action'] == 'otherAction' &&
64 | request['params'] == {'x' => 1}
65 | ).to be_truthy
66 | end
67 | end
68 |
69 |
70 | context 'parameter passed' do
71 | it 'passes the parameter' do
72 | visit basic_params_main_index_path
73 |
74 | expect(request['params']).to eq({'x' => 1, 'y' => 2})
75 | end
76 | end
77 |
78 |
79 |
80 |
81 |
82 | #
83 | #
84 | # Multiple Calls
85 | #
86 | #
87 |
88 | context 'false at first then pass a parameter' do
89 | it 'executes default controller#action plus the parameter' do
90 | visit multiple_calls_1_main_index_path
91 |
92 | expect(
93 | request['controller'] == 'Main' &&
94 | request['action'] == 'multiple_calls_1' &&
95 | request['params'] == {'x' => 70}
96 | ).to be_truthy
97 | end
98 | end
99 |
100 |
101 | context 'false at first then pass a controller string' do
102 | it 'executes passed controller and default action' do
103 | visit multiple_calls_2_main_index_path
104 |
105 | expect(
106 | request['controller'] == 'OtherMain' &&
107 | request['action'] == 'multiple_calls_2'
108 | ).to be_truthy
109 | end
110 | end
111 |
112 |
113 | context 'controller at first then action' do
114 | it 'executes the controller and action' do
115 | visit multiple_calls_3_main_index_path
116 |
117 | expect(
118 | request['controller'] == 'OtherMain' &&
119 | request['action'] == 'show'
120 | ).to be_truthy
121 | end
122 | end
123 |
124 |
125 | context 'controller#action at first then false' do
126 | it 'does not execute any js' do
127 | visit multiple_calls_4_main_index_path
128 | expect(paloma_executed?).to be_falsy
129 | end
130 | end
131 |
132 |
133 | context 'false at first then true' do
134 | it 'executes default controller#action' do
135 | visit multiple_calls_5_main_index_path
136 |
137 | expect(
138 | request['controller'] == 'Main' &&
139 | request['action'] == 'multiple_calls_5'
140 | ).to be_truthy
141 | end
142 | end
143 |
144 |
145 |
146 |
147 | #
148 | #
149 | # Prevent Paloma
150 | #
151 | #
152 |
153 | shared_examples 'no paloma' do
154 | it 'does not add paloma hook' do
155 | expect(page.has_selector?('.js-paloma-hook')).to be_falsy
156 | end
157 | end
158 |
159 |
160 | context 'js(false)' do
161 | before { visit prevent_main_index_path }
162 |
163 | include_examples 'no paloma'
164 |
165 | it 'prevents execution of Paloma controller' do
166 | expect(paloma_executed?).to be_falsy
167 | end
168 | end
169 |
170 | context 'json response' do
171 | before { visit json_response_main_index_path }
172 | include_examples 'no paloma'
173 | end
174 |
175 | context 'js response' do
176 | before { visit js_response_main_index_path }
177 | include_examples 'no paloma'
178 | end
179 |
180 | context 'xml response' do
181 | before { visit xml_response_main_index_path }
182 |
183 | it 'does not add paloma hook' do
184 | # TODO: implement this
185 | # XML is not supported by capybara.
186 | end
187 | end
188 |
189 | context 'file response' do
190 | before { visit file_response_main_index_path }
191 | include_examples 'no paloma'
192 | end
193 |
194 |
195 | end
196 |
--------------------------------------------------------------------------------
/test_app/README.rdoc:
--------------------------------------------------------------------------------
1 | == Welcome to Rails
2 |
3 | Rails is a web-application framework that includes everything needed to create
4 | database-backed web applications according to the Model-View-Control pattern.
5 |
6 | This pattern splits the view (also called the presentation) into "dumb"
7 | templates that are primarily responsible for inserting pre-built data in between
8 | HTML tags. The model contains the "smart" domain objects (such as Account,
9 | Product, Person, Post) that holds all the business logic and knows how to
10 | persist themselves to a database. The controller handles the incoming requests
11 | (such as Save New Account, Update Product, Show Post) by manipulating the model
12 | and directing data to the view.
13 |
14 | In Rails, the model is handled by what's called an object-relational mapping
15 | layer entitled Active Record. This layer allows you to present the data from
16 | database rows as objects and embellish these data objects with business logic
17 | methods. You can read more about Active Record in
18 | link:files/vendor/rails/activerecord/README.html.
19 |
20 | The controller and view are handled by the Action Pack, which handles both
21 | layers by its two parts: Action View and Action Controller. These two layers
22 | are bundled in a single package due to their heavy interdependence. This is
23 | unlike the relationship between the Active Record and Action Pack that is much
24 | more separate. Each of these packages can be used independently outside of
25 | Rails. You can read more about Action Pack in
26 | link:files/vendor/rails/actionpack/README.html.
27 |
28 |
29 | == Getting Started
30 |
31 | 1. At the command prompt, create a new Rails application:
32 | rails new myapp (where myapp is the application name)
33 |
34 | 2. Change directory to myapp and start the web server:
35 | cd myapp; rails server (run with --help for options)
36 |
37 | 3. Go to http://localhost:3000/ and you'll see:
38 | "Welcome aboard: You're riding Ruby on Rails!"
39 |
40 | 4. Follow the guidelines to start developing your application. You can find
41 | the following resources handy:
42 |
43 | * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
44 | * Ruby on Rails Tutorial Book: http://www.railstutorial.org/
45 |
46 |
47 | == Debugging Rails
48 |
49 | Sometimes your application goes wrong. Fortunately there are a lot of tools that
50 | will help you debug it and get it back on the rails.
51 |
52 | First area to check is the application log files. Have "tail -f" commands
53 | running on the server.log and development.log. Rails will automatically display
54 | debugging and runtime information to these files. Debugging info will also be
55 | shown in the browser on requests from 127.0.0.1.
56 |
57 | You can also log your own messages directly into the log file from your code
58 | using the Ruby logger class from inside your controllers. Example:
59 |
60 | class WeblogController < ActionController::Base
61 | def destroy
62 | @weblog = Weblog.find(params[:id])
63 | @weblog.destroy
64 | logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
65 | end
66 | end
67 |
68 | The result will be a message in your log file along the lines of:
69 |
70 | Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
71 |
72 | More information on how to use the logger is at http://www.ruby-doc.org/core/
73 |
74 | Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
75 | several books available online as well:
76 |
77 | * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
78 | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
79 |
80 | These two books will bring you up to speed on the Ruby language and also on
81 | programming in general.
82 |
83 |
84 | == Debugger
85 |
86 | Debugger support is available through the debugger command when you start your
87 | Mongrel or WEBrick server with --debugger. This means that you can break out of
88 | execution at any point in the code, investigate and change the model, and then,
89 | resume execution! You need to install ruby-debug to run the server in debugging
90 | mode. With gems, use sudo gem install ruby-debug. Example:
91 |
92 | class WeblogController < ActionController::Base
93 | def index
94 | @posts = Post.all
95 | debugger
96 | end
97 | end
98 |
99 | So the controller will accept the action, run the first line, then present you
100 | with a IRB prompt in the server window. Here you can do things like:
101 |
102 | >> @posts.inspect
103 | => "[#nil, "body"=>nil, "id"=>"1"}>,
105 | #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
107 | >> @posts.first.title = "hello from a debugger"
108 | => "hello from a debugger"
109 |
110 | ...and even better, you can examine how your runtime objects actually work:
111 |
112 | >> f = @posts.first
113 | => #nil, "body"=>nil, "id"=>"1"}>
114 | >> f.
115 | Display all 152 possibilities? (y or n)
116 |
117 | Finally, when you're ready to resume execution, you can enter "cont".
118 |
119 |
120 | == Console
121 |
122 | The console is a Ruby shell, which allows you to interact with your
123 | application's domain model. Here you'll have all parts of the application
124 | configured, just like it is when the application is running. You can inspect
125 | domain models, change values, and save to the database. Starting the script
126 | without arguments will launch it in the development environment.
127 |
128 | To start the console, run rails console from the application
129 | directory.
130 |
131 | Options:
132 |
133 | * Passing the -s, --sandbox argument will rollback any modifications
134 | made to the database.
135 | * Passing an environment name as an argument will load the corresponding
136 | environment. Example: rails console production.
137 |
138 | To reload your controllers and models after launching the console run
139 | reload!
140 |
141 | More information about irb can be found at:
142 | link:http://www.rubycentral.org/pickaxe/irb.html
143 |
144 |
145 | == dbconsole
146 |
147 | You can go to the command line of your database directly through rails
148 | dbconsole. You would be connected to the database with the credentials
149 | defined in database.yml. Starting the script without arguments will connect you
150 | to the development database. Passing an argument will connect you to a different
151 | database, like rails dbconsole production. Currently works for MySQL,
152 | PostgreSQL and SQLite 3.
153 |
154 | == Description of Contents
155 |
156 | The default directory structure of a generated Ruby on Rails application:
157 |
158 | |-- app
159 | | |-- assets
160 | | |-- images
161 | | |-- javascripts
162 | | `-- stylesheets
163 | | |-- controllers
164 | | |-- helpers
165 | | |-- mailers
166 | | |-- models
167 | | `-- views
168 | | `-- layouts
169 | |-- config
170 | | |-- environments
171 | | |-- initializers
172 | | `-- locales
173 | |-- db
174 | |-- doc
175 | |-- lib
176 | | `-- tasks
177 | |-- log
178 | |-- public
179 | |-- script
180 | |-- test
181 | | |-- fixtures
182 | | |-- functional
183 | | |-- integration
184 | | |-- performance
185 | | `-- unit
186 | |-- tmp
187 | | |-- cache
188 | | |-- pids
189 | | |-- sessions
190 | | `-- sockets
191 | `-- vendor
192 | |-- assets
193 | `-- stylesheets
194 | `-- plugins
195 |
196 | app
197 | Holds all the code that's specific to this particular application.
198 |
199 | app/assets
200 | Contains subdirectories for images, stylesheets, and JavaScript files.
201 |
202 | app/controllers
203 | Holds controllers that should be named like weblogs_controller.rb for
204 | automated URL mapping. All controllers should descend from
205 | ApplicationController which itself descends from ActionController::Base.
206 |
207 | app/models
208 | Holds models that should be named like post.rb. Models descend from
209 | ActiveRecord::Base by default.
210 |
211 | app/views
212 | Holds the template files for the view that should be named like
213 | weblogs/index.html.erb for the WeblogsController#index action. All views use
214 | eRuby syntax by default.
215 |
216 | app/views/layouts
217 | Holds the template files for layouts to be used with views. This models the
218 | common header/footer method of wrapping views. In your views, define a layout
219 | using the layout :default and create a file named default.html.erb.
220 | Inside default.html.erb, call <% yield %> to render the view using this
221 | layout.
222 |
223 | app/helpers
224 | Holds view helpers that should be named like weblogs_helper.rb. These are
225 | generated for you automatically when using generators for controllers.
226 | Helpers can be used to wrap functionality for your views into methods.
227 |
228 | config
229 | Configuration files for the Rails environment, the routing map, the database,
230 | and other dependencies.
231 |
232 | db
233 | Contains the database schema in schema.rb. db/migrate contains all the
234 | sequence of Migrations for your schema.
235 |
236 | doc
237 | This directory is where your application documentation will be stored when
238 | generated using rake doc:app
239 |
240 | lib
241 | Application specific libraries. Basically, any kind of custom code that
242 | doesn't belong under controllers, models, or helpers. This directory is in
243 | the load path.
244 |
245 | public
246 | The directory available for the web server. Also contains the dispatchers and the
247 | default HTML files. This should be set as the DOCUMENT_ROOT of your web
248 | server.
249 |
250 | script
251 | Helper scripts for automation and generation.
252 |
253 | test
254 | Unit and functional tests along with fixtures. When using the rails generate
255 | command, template test files will be generated for you and placed in this
256 | directory.
257 |
258 | vendor
259 | External libraries that the application depends on. Also includes the plugins
260 | subdirectory. If the app has frozen rails, those gems also go here, under
261 | vendor/rails/. This directory is in the load path.
262 |
--------------------------------------------------------------------------------