Use the "paper_trail" gem to track versions of records
paper_trail
is an excellent gem to track record versions and changes.
You almost never want to reimplement something like it yourself. If you need to log some extra information, you can add them on top.
It comes with a really good README file that holds lots of examples. I'll show you only some of its features here:
-
- Setting up a model to track changes
- Just add
has_paper_trail
to it:
class User < ActiveRecord::Base
has_paper_trail
end
-
- Accessing a previous version
- Saying
user.previous_version
gi...
Updated: Remove quotes from Sass mixin arguments
When we looked at this card together a year ago, we were no longer sure if unquote
is actually useful. I now found a good example for when you need unquote
, and rewrote the card accordingly.
How to change will_paginate's "per_page" in Cucumber features
The will_paginate
gem will show a default of 30 records per page.
If you want to test pagination in a Cucumber feature, you don't want to create 31 records just for that.
Instead, you probably want to modify the number of items shown, by saying something like this:
Given we paginate after 2 users
Using the following step definition, you now can! :)
require 'cucumber/rspec/doubles'
Given /^paginate after (\d+) (.*)$/ do |per_page, model_name|
model = model_name.singularize.gsub(/...
jQuery.cssHooks – jQuery API
The $.cssHooks object provides a way to define functions for getting and setting particular CSS values. It can also be used to create new cssHooks for normalizing CSS3 features such as box shadows and gradients.
For example, some versions of Webkit-based browsers require -webkit-border-radius to set the border-radius on an element, while earlier Firefox versions require -moz-border-radius. A css hook can normalize these vendor-prefixed properties to let .css() accept a single, standard property name (border-radius, or with DOM property synt...
Updated: Capybara: Check that a page element is hidden via CSS
- The step we used in the past (
Then "foo" should not be visibile
) doesn't reliably work in Selenium features. - I overhauled the entire step so it uses Javascript to detect visibility in Selenium.
- The step has support for jQuery and Prototype projects, so it should be a drop-in replacement for all your projects.
- For Rack::Test the step no longer uses XPath so you should be able to understand it when you are not a cyborg :)
- There were some other cards detailing alternative steps to detect visibility. I deleted all these other cards s...
RubyMine: Using pinned tabs will increase your productivity
I highly recommend that you make use of RubyMine's feature to pin tabs.
When you pin all "important" files, you can follow method definitions, wildly open files from search results and have a ton of open tabs -- without the problem of finding the stuff you were working on before.
Guide
- Pin the tabs of files that are currently in the focus of your work (important models, specs, etc):
- Right-click a tab and select "Pin tab"
- Or use a shortcut (see below)
- Work as usual.
- Once you opened other tabs because you searched ...
Speed up large Cucumber test suites
Test suites usually grow over time as more and more development time is spent on a projects. Overall run-time and performance of Cucumber suites in turn increases, too.
You can use the very same way Henning suggested for speeding up RSpec some time ago.
Put the following into features/support/deferred_garbage_collection.rb
Before do
DeferredGarbageCollection.start
end
After do
DeferredGarbageCollection.reconsider
end
We...
When overriding #method_missing, remember to override #respond_to_missing? as well
When you use method_missing
to have an object return something on a method call, always make sure you also redefine respond_to_missing?
.
If you don't do it, nothing will break at a first glance, but you will run into trouble eventually.
Consider this class:
class Dog
def method_missing(method_name, *args, &block)
if method_name == :bark
'woof!'
else
super
end
end
end
This will allow you to say:
Dog.new.bark
=> "woof!"
But:
Dog.new.respond_to? :bark
=> false
```...
How to: Specify size of Selenium browser window
Applications often show or hide elements based on viewport dimensions, or may have components that behave differently (like mobile vs desktop navigation menus).
Since you want your integration tests to behave consistently, you want to set a specific size for your tests' browser windows.
Using WebDriver options / Chrome device metrics
For Google Chrome, the preferred way is setting "device metrics". This allows you to configure dimensions larger than your display and enable/disable touch behavior.
Simply use register_driver
to set up...
Run specific version of bundler
You can specify the version of bundler
to execute a command (most often you need an older version of bundler, but don't want to uninstall newer ones):
bundle _1.0.10_ -v
Bundler version 1.0.10
An example is rails 3.2, which freezes bundler
at version ~> 1.0
:
Bundler could not find compatible versions for gem "bundler":
In Gemfile: rails (~> 3.2) was resolved to 3.2.0, which depends on bundler (~> 1.0)
Current Bundler version: bundler (1.13.6)
You can solve this with:
gem install bundler -v 1....
Setup your terminal to not scroll when there is new output
When you are scrolling up to investigate a test failure it is super annoying when the terminal scrolls back down whenever the running test outputs another line. Luckily you can disable this behavior:
- Gnome terminal: *Edit -> Profile preferences -> Scrolling", uncheck Scroll on output
- Terminator: Right click on terminal screen, Preferences -> Profile -> (for each profile) -> Scrolling, uncheck Scroll on output
Updated: Test a gem in multiple versions of Rails
Updated the card with our current best practice (shared app code and specs via symlinks).
rake spec + rails_admin = weirdly failing specs
If you use rails_admin, your specs pass with the rspec
binary, but not using rake spec
(or rake parallel:spec
etc), put this at the top of your spec_helper
:
ENV['SKIP_RAILS_ADMIN_INITIALIZER'] = 'false'
Don't ask.
This is probably also true for cucumber, your env.rb
would be the right place.
RSpec claims nil to be false
RSpec's be_false
behaves unexpectedly:
nil.should be_false
# passes, as the expectation returns true
If you want to check for false
, you need to do it like this:
nil.should == false
# fails as expected
See also
Don't use Ruby 1.9.2
Ruby 1.9.2 is very slow when loading files, especially starting Rails servers or running specs takes forever.
Do yourself a favor and upgrade to 1.9.3.
Rails 2's CookieStore produces invalid cookie data, causing tests to break
Note that this seems to affect only recent Rails 2 versions.
You will not encounter this until you are writing to the cookie more than once, but when doing so, integration tests (Cucumber) may break for you with this error:
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[] (NoMethodError)
Background
The regular/short cucumber backtrace is not of any help but looking at the full trace reveals that ActionPack's `actio...
How much should I refactor?
The Rails community has been abuzz with object-oriented programming, SOLID principles, laws, design patterns, and other principles, practices, and patterns. We’ve (re)discovered new tools and techniques to separate and reuse logic, making code easier to test, understand, and maintain. Now that we’ve learned about all these new tools, when do we use them?
Beware of params with non-string values (nil, array, hash)
Recent rails security updates have shown that people make incorrect assumptions about the possible contents of the params
hash.
Just don't make any! Treat it as what it is: potentially unsafe user input. For example:
/pages/edit?foo= --> params == {:foo => ""}
/pages/edit?foo --> params == {:foo => nil}
/pages/edit?foo[] --> params == {:foo => [nil]} # at least in older rails 3 and in rails 2.x
Be especially wary about stuff like
User.find_by_password_reset_token(params[:password_reset_token])
I...
Use "overflow: hidden" to avoid floating elements from wrapping a container's text
Consider this HTML:
<div id="container">
<div id="actions">
<a href="#">Click me!</a>
</div>
<div id="content">
Hello Universe! Hello Universe! Hello Universe! Hello Universe! Hello Universe! Hello Universe!
</div>
</div>
If you want the actions
element to float on the left, you'd just say this in your CSS:
#actions { float: left; }
Unfortunately, any content of the content
's text will wrap underneath it:
:
["Schwertner", "Schöler"].sort
# => ["Schwertner", "Schöler"] # you probably expected ["Schöler", "Schwertner"]
Also numbers in strings will be sorted character by character which you probably don't want:
["1", "2", "11"].sort
# => ["1", "11", "2"] # you probably expected ["1", "2", "11"]
Also the sorting is case sensitive:
...
Fix: Capybara is very slow when filling out fields in large forms
In large forms (30+ controls) new Capybara version become [extremely slow] when filling out fields. It takes several seconds per input. The reason for this is that Capybara generates a huge slow XPath expression to find the field.
The attached code patches fill_in
with a much faster implementation. It's a dirty fix and probably does a lot less than Capybara's own fill_in
so don't use it unless you are having problems with test suites that are unusable because of this...
Rails asset pipeline: Why relative paths can work in development, but break in production
The problem
When using the asset pipeline your assets (images, javascripts, stylesheets, fonts) live in folders inside app
:
app/assets/fonts
app/assets/images
app/assets/javascripts
app/assets/stylesheets
With the asset pipeline, you can use the full power of Ruby to generate assets. E.g. you can have ERB tags in your Javascript. Or you can have an ERB template which generates Haml which generates HTML. You can chain as many preprocessors as you want.
When you deploy, Rails runs assets:precompile
...
Browser Standards progress: CSS filter property
Some progress was made by browsers on implementing CSS filters like blur, greyscale or some other effects. You might already know the legacy CSS filter attribute that old IE versions used to perform DirectX transformations. Luckily these legacy filters are removed in IE10. The good news is, newest WebKit-based browsers like Chrome (18.0+) Safari and Mozilla Firefox expe...
Linux: How to add a task bar to VNC displays
If you are using VNC to run Selenium tests, it may be hard to see what's going on since by default there is no list of open windows and Alt
+Tab
won't work.
Solving that is easy:
-
Install a panel of your choice (like lxpanel) which offers task switching:
sudo apt-get install lxpanel
(You can't use
gnome-panel
because it won't start twice -- but lxpanel does a good job) -
To have that panel appear on VNC screens by default, edit
~/.vnc/xstartup
...