Padrino

Adding Components

JavaScript Engine

Contributing an additional JavaScript library to Padrino is actually quite straightforward. For this guide, let's assume we want to add extcore as a JavaScript component integrated into Padrino.

Generators

First, let's define the actual integration of the javascript into the generator in padrino-gen/generators/components/scripts/extcore.rb:

# padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb

def setup_script
  begin
    get('https://raw.github.com/padrino/padrino-static/master/js/ext.js',  destination_root("/public/javascripts/ext.js"))
  rescue
    copy_file('templates/static/js/ext.js',  destination_root("/public/javascripts/ext.js"))
  end
  create_file(destination_root('/public/javascripts/application.js'), "// Put your application scripts here")
end

This will copy the script into the public/javascripts folder of a newly generated project and construct the application.js file. Next, let's copy the latest version of the javascript library to the templates folder:

// padrino-gen/lib/padrino-gen/generators/templates/scripts/ext-core.js

// ...truncated javascript library code here...

Tests

Let's also add a test to ensure the new JavaScript component generates as expected in padrino-gen/test/test_project_generator.rb:

# padrino-gen/test/test_project_generator.rb

it 'should properly generate for ext-core' do
  out, err = capture_io { generate(:project, 'sample_project', "--root=#{@apptmp}", '--script=extcore') }
  assert_match(/applying.*?extcore.*?script/, out)
  assert_file_exists("#{@apptmp}/sample_project/public/javascripts/ext.js")
  assert_file_exists("#{@apptmp}/sample_project/public/javascripts/ext-ujs.js")
  assert_file_exists("#{@apptmp}/sample_project/public/javascripts/application.js")
end

README

Finally, let's update the README for padrino-gen to reflect the new component in padrino-gen/README.rdoc:

# padrino-gen/README.rdoc
script:: none  (default), jquery, prototype, mootools, extcore, dojo

Unobtrusive JavaScript Adapter

Although optional, you can also provide a unobtrusive JavaScript (UJS) adapter which provides 'remote' and 'method' support to a project using a particular JavaScript framework. For more information about UJS, check out the UJS Helpers guide.

To support UJS in a given JavaScript framework, simply create a new file such as 'jquery-ujs' in your padrino-static fork and then follow the UJS adapter template used by the existing implementation.

// ujs/jquery-ujs.js

/* Remote Form Support
 * form_for @user, '/user', :remote => true
**/
$("form[data-remote=true]").live('submit', function(e) {
  // ...
});
/* Confirmation Support
 * link_to 'sign out', '/logout', :confirm => "Log out?"
 * Link Remote Support
 * link_to 'add item', '/create', :remote => true
 * Link Method Support
 * link_to 'delete item', '/destroy', :method => :delete
**/

/* JSAdapter */
var JSAdapter = {
  // Sends an xhr request to the specified url with given verb and params
  // JSAdapter.sendRequest(element, { verb: 'put', url : '...', params: {} });
  sendRequest : function(element, options) {
    // ...
  },
  // Triggers a particular method verb to be triggered in a form posting to the url
  // JSAdapter.sendMethod(element);
  sendMethod : function(element) {
    // ...
  }
};

Generally the only changes need to be made in the JSAdapter JavaScript module specifically to implement the sendRequest and sendMethod functions that are used by all the events to power the UJS functionality.

Once that unobtrusive adapter has been implemented, you can finish by adding the UJS file to the generator in Padrino:

# padrino-gen/lib/padrino-gen/generators/components/scripts/extcore.rb
def setup_script
  begin
    get('https://raw.github.com/padrino/padrino-static/master/ujs/ext.js', destination_root("/public/javascripts/ext-ujs.js"))
  rescue
    copy_file('templates/static/ujs/ext.js', destination_root("/public/javascripts/ext-ujs.js"))
  end
  create_file(destination_root('/public/javascripts/application.js'), "// Put your application scripts here")
end

and update the tests:

# padrino-gen/test/test_project_generator.rb
describe "the generator for script component" do
   it 'should properly generate for jquery' do
     out, err = capture_io { generate(:project, 'sample_project', "--root=#{@apptmp}", '--script=jquery') }
     assert_match(/applying.*?jquery.*?script/, out)
     assert_file_exists("#{@apptmp}/sample_project/public/javascripts/jquery.js")
     assert_file_exists("#{@apptmp}/sample_project/public/javascripts/jquery-ujs.js")
     assert_file_exists("#{@apptmp}/sample_project/public/javascripts/application.js")
   end
   ...
end

Contribute to Padrino

This completes the full integration of a JavaScript library into Padrino. Once all of this has been finished in your GitHub fork, send us a pull request and assuming you followed these instructions properly and the library actually works when generated, we will include the component into the next Padrino version crediting you for the contribution!

An example of the actual commit of the extcore JavaScript library is a great example of how to contribute to Padrino.

last updated: 2022-02-22

comments powered by Disqus