Intro
This describes how to create a gem which can be used with Rails from the Yellow Pencil Wharton theme.
Required materials
- The Yellow Pencil theme, available in
assets/WWWv1.0 - Ruby 1.9.2-p290 or compatible
- Rails 3.2.3 or compatible
Steps
Let’s create a project folder called conversion-project and cd into it.
mkdir conversion-project cd conversion-project
Next, create a Rails app which we’ll use to test things out.
rails new dummy
Next, create the plugin gem, which we’ll call wharton-theme.
rails plugin new wharton-theme
This will create a directory containing the gem files in the current directory. Let’s add this gem to the test project. We’ll tell the app to look for the gem in a child of its parent directory called wharton-themeby appending a line to the dummy project’s Gemfile.
echo -e "gem 'wharton-theme', :path => '../wharton-theme'\n" >> dummy/Gemfile
Let’s make sure everything is working by installing the gem.
cd dummy bundle install cd ..
We should now be in the conversion-project directory.
Let’s assume we have the assets/WWWv1.0 directory stored in the shell variable $wwwsrc. Let’s take a quick look at the contents of this directory.
- css
- index.html
- interface
- javascript
This is fairly straightforward. Let’s first worry about the layout. We’ll copy it into our directory and see how it looks.
cp $wwwsrc/index.html dummy/app/views/layouts/application.html.erb
Let’s see how it looks. We’ll want a resource that we can take a look at.
cd dummy rails generate scaffold items name description:text rake db:migrate rails server
Navigate to http://localhost:3000/items. You should see links and broken images. Notice there is content text on the page. Let’s make sure we show the appropriate content there. There is a line in the layout at dummy/app/views/layouts/application.html.erb that looks like:
<p>content</p>
We want to tell Rails that it should put the appropriate content there. We’ll replace it with the following:
<%= yield %>
Which tells Rails to put the results of evaluting the appropriate view at that position. Open a terminal to the parent conversion-project directory and run this command which adds the yield statement in the appropriate location.
sed -i"bak" "s#<p>content</p>#<%= yield %>#g" dummy/app/views/layouts/application.html.erb
Refresh your running browser and you should see the text below instead of “content”.
Listing items
Name Description
New Item
So, we have a working layout (we haven’t gemified this, but we will), and now we should fix the images, scripts, and css. Let’s take care of the css first.
If you take a look at the source, you will notice that there are links to css that look like:
<link href="css/default.css" rel="stylesheet" type="text/css" />
but the URL http://localhost:3000/css/default.css doesn’t exist! We can fix this by copying the stylesheets from $wwwsrc into the gem into the vendor/assets directory.
mkdir -p wharton-theme/vendor/assets
cp -r $wwwsrc/css wharton-theme/vendor/assets/stylesheets
Note that we rename the css directory to stylesheets due to convention. While we’re at it, let’s create the javascripts and images directories as well. Note that we also rename these directories to match convention.
cp -r $wwwsrc/javascript wharton-theme/vendor/assets/javascripts
cp -r $wwwsrc/interface wharton-theme/vendor/assets/images
We’ll edit the wharton-theme/lib/wharton-theme.rb file, which is typically used to require other gem files. (This is convention.) Enter the following contents:
require 'wharton-theme/version' require 'wharton-theme/engine'
Or use this command:
echo -e "require 'wharton-theme/version'\nrequire'wharton-theme/engine'\n" > wharton-theme/lib/wharton-theme.rb
The wharton-theme/lib/wharton-theme/engine.rb file referenced above doesn’t exist yet! Create it with the following contents:
module WhartonTheme class Engine < ::Rails::Engine end end
Or use this command:
echo -e "module WhartonTheme\n class Engine < ::Rails::Engine\nend\nend" > wharton-theme/lib/wharton-theme/engine.rb
This empty class tells the Rails engine that it should look at the gem for asset paths. This is great, because it allows us to modularize our layout’s assets. In Rails, all of the assets are available as children of the assets/ path.
Navigate to http://localhost:3000/assets/default.css, which should now return some results.
Let’s fix our layout to reflect this new path. We’ll replace paths that reference the old css, javascript, and interface directories with absolute references to /assets.
sed -i"bak" -e "s#css/#/assets/#g" -e "s#javascript/#/assets/#g" -e "s#interface/#/assets/#g" dummy/app/views/layouts/application.html.erb
We must restart the Rails server in order for it to detect the new asset paths. Issue the command:
rails server
Reload your browser and the site should look much better. Still, there are missing images. Notice that inline images are present, but that background-images referenced in stylesheets are not. Let’s fix that. Remember that stylesheet references are relative to the location of the file itself. If we look atdefault.css, we’ll see references to images such as ../interface/*. We’ll change these to be absolute references to /assets.
sed -i"bak" -e "s#../interface#/assets#g" wharton-theme/vendor/assets/stylesheets/*.css
Refresh your browser. There’s nothing obviously missing now.
Creating a generator
The final thing to do is to package this layout as part of our gem. We’ll do this by creating a generator which we can expose to Rails developers.
Rails exposes a generator for creating generators. We’ll need to be relative to the dummy application to use it.
cd dummy rails generate generator wharton/layout mkdir -p ../wharton-theme/lib/generators mv lib/generators/wharton ../wharton-theme/lib/generators cd ..
We should be back in the parent directory. We’ll copy the layout we created into the templates director of the generator.
cp dummy/app/views/layouts/application.html.erb wharton-theme/lib/generators/wharton/layout/templates/
Next, we’ll alter the template to prevent evaluating Ruby code.
sed -i"bak" "s#<%#<%%#g" wharton-theme/lib/generators/wharton/layout/templates/application.html.erb
Now, we need to modify the layout_generator.rb file we generated to copy this file into applications. It should have these contents:
module Wharton
class LayoutGenerator < Rails::Generators::Base
source_root File.expand_path("../templates", __FILE__)
desc "This generator generates layout file with navigation."
def generate_layout
template "application.html.erb", "app/views/layouts/application.html.erb"
end
end
end
Alternatively, use this command:
echo -e 'module Wharton\nclass LayoutGenerator < Rails::Generators::Base\n source_root File.expand_path("../templates", __FILE__)\n\n desc "This generator generates layout file with navigation."\n def generate_layout\n template "application.html.erb", "app/views/layouts/application.html.erb"\n end\nend\nend\n\n' > wharton-theme/lib/generators/wharton/layout/layout_generator.rb
Let’s test the generator.
cd dummy rails generate wharton:layout
You should get a message that the layout is identical. Now, commit your work to share it.
git add . git commit -m "A meaningful message please" git tag -a "v0.1.0" -m "first version" git push origin master && git push --tags
Let’s assume the remote url is: git@wharton.unfuddle.com:wharton/wharton-theme.git. One can use this gem by adding the following to their Gemfile:
gem 'wharton-theme', :git => 'git@wharton.unfuddle.com:wharton/wharton-theme.git', :tag => 'v0.1.0'