Why Package JS Libraries as a Gem
Rails projects commonly integrate JavaScript and CSS libraries like SweetAlert, Chart.js, or Bootstrap. The cleanest approach is packaging them as a Ruby gem so your application can declare a single gem line in the Gemfile instead of manually copying assets into vendor/assets. This gem-based approach ensures versioning, dependency resolution, and straightforward updates.
Building a Gem with SweetAlert
SweetAlert is a JavaScript library that replaces the browser’s default alert() dialog with customizable modal windows. The library ships with two files: sweetalert.css and sweetalert.js. These go into the gem’s vendor/assets directory so Rails’ asset pipeline can pick them up.
Creating the Gem Scaffold
Run bundle gem to generate the standard gem directory structure:
$ bundle gem sweetalert
create sweetalert/Gemfile
create sweetalert/.gitignore
create sweetalert/lib/sweetalert.rb
create sweetalert/lib/sweetalert/version.rb
create sweetalert/sweetalert.gemspec
create sweetalert/Rakefile
create sweetalert/README.md
create sweetalert/bin/console
create sweetalert/bin/setup
create sweetalert/.travis.yml
create sweetalert/.rspec
create sweetalert/spec/spec_helper.rb
create sweetalert/spec/sweetalert_spec.rb
create sweetalert/LICENSE.txt
create sweetalert/CODE_OF_CONDUCT.md
Copy the SweetAlert assets into vendor/assets/javascripts/sweetalert.js and vendor/assets/stylesheets/sweetalert.css.
Configuring the Gemspec
Open sweetalert.gemspec and fill in the metadata: author, summary, description, and license. Add a reference to the assets directory so Bundler includes them in the packaged gem. The s.files entry should list all shipped files, and the gem version should match the library version for clarity.
Using the Gem Locally
Reference the local gem in your Rails app’s Gemfile for development:
gem 'sweetalert', path: '/data/ruby-apps/sweetalert'
Run bundle install to resolve the dependency. For production, push the gem to RubyGems.org and reference it without the path option.
Requiring Assets in the Pipeline
Add the gem’s assets to your application’s asset manifest:
// application.js
//= require sweetalert
/* application.css */
*= require sweetalert
If you use Turbolinks, wrap SweetAlert initialization in a turbolinks:load event listener to avoid issues with page navigation.
Integrating with Rails Scaffolding
Generate a scaffold to test the gem integration:
rails g scaffold articles title:string text:text
Update articles/index.html.erb to use SweetAlert for delete confirmation:
<p id="notice"><%= notice %></p>
<h1>Articles</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Text</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
<td><%= link_to 'Show', article %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article, data: { behavior: 'delete'} %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Article', new_article_path %>
Then wire up the CoffeeScript to handle the delete action with SweetAlert:
jQuery ->
$("[data-behavior='delete']").on "click", (e) ->
e.preventDefault()
swal {
title: 'Are you sure?'
text: 'You will not be able to recover this imaginary file!'
type: 'warning'
showCancelButton: true
confirmButtonColor: '#DD6B55'
confirmButtonText: 'Yes, delete it!'
cancelButtonText: 'No, cancel plx!'
closeOnConfirm: false
closeOnCancel: false
}, (confirmed) =>
if confirmed
$.ajax(
url: $(this).attr("href")
dataType: "JSON"
method: "DELETE"
success: =>
swal 'Deleted!', 'Your imaginary file has been deleted.', 'success'
$(this).parent().parent().remove()
)
else
swal 'Cancelled', 'Your imaginary file is safe :)', 'error'
return
The key detail is setting closeOnConfirm to false so the modal stays visible during the AJAX request. The user sees immediate feedback when the delete succeeds or is cancelled.
Publishing to RubyGems
Once tested locally, build and publish the gem:
gem build sweetalert.gemspec
gem push sweetalert-1.0.0.gem
After publishing, your Gemfile entry becomes a simple gem 'sweetalert' without the path option, and any developer on the team gets the same version.
Comments