I’ve been wondering recently “If I cache a file in public/ how do my integration tests access the file?”
By default, Rails’ integration stack only calls into the routes/controllers. So the following fails, ironically with a 404 error:
$ script/console
>> app.get '404.html'
=> 404
It should return 200. If I cache a file into public/ I want to be able to pull it back out during the normal course of integration testing.
In integration testing, this problem manifested when I clicked a link to a cached asset, or an action redirected to a cached asset.
Ryan Tomayko seems to also have wondered about this, and had this conversation with Pratik Naik on twitter the other day that solved the problem for me:
What worked for me was to put the following at the bottom of my config/environments/cucumber.rb file (or your …/test.rb file if you do integration testing in that environment):
config.middleware.use "Rails::Rack::Static"
Now, I can successfully load assets via the get helper, or indirectly via webrat clicking links, etc:
If you squint your eyes just right, you’ll notice that your original template folder now has an install_theme.yml file. It contains your original settings. You can imagine for yourself how the rest of the “themes can remember things” magic might work.
Templates “For Ruby on Rails”
If you are a template maker, you can now easily make your HTML template “For Ruby on Rails” by including an install_theme.yml file. Think of the children.
Major change
I changed the order of the first two arguments. In future, the path/to/template will be optional. Why? Imagine if each theme you ever used was cached in ~/.install_theme/themes and you could select a theme from a list or by --theme theme_name. That seems neat.
I don’t know if this is a good idea or not, but often I just wish I could copy and paste a cucumber feature file into the command line and have it just run the frigging scenarios without having to prefix it with “cucumber”.
Perhaps I’m a bit delirious but I think it would be fun to paste features/112_users_crud.feature into the console and it would run the scenarios:
$ features/users_crud.feature
instead of having to always do the extra key strokes:
$ cucumber features/users_crud.feature
Solution?
Two steps:
At the very top of each feature file add: #!/usr/bin/env cucumber
Run chmod +x features/*.feature
Shazam!
Hash bang me up!
To apply this to all your feature files, jump into script/console or irb and run the following code within your project:
Dir["**/*.feature"].each do |feature|
contents = File.read(feature)
File.open(feature, "w") do |f|
f << "#!/usr/bin/env cucumber\n\n"
f << contents
end
`chmod +x "#{feature}"`
end
Have you ever even bothered to Google for “rails html template”? There are millions of “Wordpress themes” you can download for free or less than $100, a thousand times more static HTML templates, but never any category of template called “Ruby on Rails theme”. 24 millions results for Googling single column html theme.
So we’re only left with HTML templates. Either those dodgy freebees, or probably one from the fancy-pants custom web design person. But how do we install them to our Rails apps?
I don’t know. It sucks. And it takes more time than it should. Here’s my idea – a tool to install any HTML template into your Rails app. To treat any HTML template as if it was a “Ruby on Rails HTML Template”.
So I’ve started to try and make any “HTML Template” into a “Ruby on Rails Template” with the helper app install_theme.
What’s it do?
Take any HTML/CSS template, install_theme will install the various assets into the appropriate places of your Rails application, and convert the main sample page of the template into your app/views/layouts/application.html.erb (or .haml). Easy peasy.
Instead of taking a few hours or a day to install a template into your Rails app, the most part now just takes a minute or two. Into either ERB or Haml. Repeatable if the original HTML/CSS template changes.
Installing a theme for fun and profit into a fresh rails app:
$ gem install install_theme
$ rails my_app
$ cd my_app
$ install_theme . path/to/theme/folder ".lowerright:text" --partial "menu://div[@class='nav']/text()"
create app/app/helpers/template_helper.rb
create app/controllers/original_template_controller.rb
create app/helpers/template_helper.rb
create app/views/layouts/_menu.html.erb
create app/views/layouts/application.html.erb
create app/views/original_template/index.html.erb
create public/images/footer.png
...
create public/stylesheets/style.css
Your theme has been installed into your app.
When you launch the app, it will be instantly themed. The section of the original template with DOM path .lowerright will be removed and replaced by your rendered actions.
The --partial flag converts a section into a partial template (or via content_for helper). More on this in a minute.
Note: the example above uses both CSS path and XPath expressions. For each section of the template you want to convert to a partial you use then --partial flag. The argument is “label:xpath” or “label:csspath”. So either --partial "header://div[@id='header']/h2" or --partial "header:#header h2".
Here are the content and partial selections using CSSpath:
Now that you’ve selected portions of the template to be dynamically changeable partials, how do you change them?
Use <% content_for :menu do %> ... <% end %> from any view template
Create a _menu.html.erb partial in your controller’s views folder, e.g. app/views/posts/_menu.html.erb
Modify the _menu.html.erb partial in the app/views/layouts folder. This is the default source.
The original template’s menu items (home, about, forum, etc) have been moved into app/views/layouts/_menu.html.erb. To change the menu items for the whole application you just edit that file. For this template, it will look like:
This is the extracted content of the .nav DOM element. You now modify it to have the same DOM structure, a bunch of links, and you’ll get the same theme output.
Let’s change the menu across the entire application. Edit app/views/layouts/_menu.html.erb: