Inherit without Single-Table-Inheritance (STI) in ActiveRecord
You have multiple options:
- Just don't have a
type
column. All STI magic will be disabled automatically. - If you have a
type
column but want to use it for something else (WAT?), you can setself.inheritance_column = :_non_existing_column
in the class definition - (Untested) In the parent class, set
self.abstract_class = true
This technique is useful to implement form models / presenters, where you want all the goodness of Ac...
How to find out if you are in Cucumber or in RSpec
Sometimes you need a piece of code to do something different for specs than for features. If you don't have separate environments, you can't check your Rails.env
.
I managed to distinguish between specs and features by asking Capybara
.
Note that this only works when you do not use Capybara in specs.
if defined?(Capybara) and Capybara.respond_to?(:current_driver)
# you're in a Cucumber scenario
else
# you're probably in a spec
end
You could omit the defined?(Capybara)
condition, if you are sure that Capybara
...
Git: How to show only filenames for a diff
When you want to do a git diff
but do not care about the full diff and just want to know which files changed, use the --name-only
switch:
$ git diff --name-only
app/controllers/sessions_controller.rb
app/models/user.rb
features/sign_in.feature
To include some brief information about changed lines, use the --stat
switch:
$ git diff --stat
app/controllers/sessions_controller.rb | 8 +-
app/models/user.rb | 30 ++++
features/sign_in.feature | 136 +++++++++++++++++
T...
Ruby: What extend and include do
All Rubyists should be familiar with the common definitions for include and extend. You include a module to add instance methods to a class and extend to add class methods. Unfortunately, this common definition isn’t entirely accurate. It fails to explain why we use instance.extend(Module) to add methods to an instance. Shouldn’t it be instance.include(Module)? To figure this out we’re going to start by discussing where methods are stored.
- include: Adds methods from the provided Module to the object
- extend: Calls include on the single...
parallel_tests: Disable parallel run for tagged scenarios
Note: This technique is confusing and slows down your test suite.
Copy the attached code to features/support
. This gets you a new Cucumber tag @no_parallel
which ensures that the tagged scenario does not run in parallel with other scenarios that are tagged with @no_parallel
. Other scenarios not tagged will @no_parallel
can still run in parallel with the tagged test. Please read the previous sentence again.
This can help when multiple test processes that access a single resource that is hard to shar...
YAML syntax compared with Ruby syntax
yaml4r is a juxtaposition of yaml documents and their Ruby couterpart. Thus, it does a great job as YAML-doc, e.g. when writing Rails locale files. Did you know that ...
-
<<
is a merge key (similar to&
in SASS) - there are variables, called aliases. Definition:
&alias Some content
, usage:*alias
.
Caveats
Specifying a key twice does not merge the sub keys, but override the first definition, e.g.
de:
car: # overridden
door: Tür
...
How to set the user agent in tests
The User-Agent
HTTP header identifies the client and is sent by "regular" browsers, search engine crawlers, or other web client software.
Cucumber
In Rack::Test
, you can set your user agent like this on Capybara:
Given /^my user agent is "(.+)"$/ do |agent|
page.driver.browser.header('User-Agent', agent)
# Or, for older Capybaras:
# page.driver.header('User-Agent', agent)
end
For Selenium tests with Firefox, it seems you can set the general.useragent.override
profile setting to your preferred value. [See StackOver...
def vs. define_method
Ever wondered about the difference between def
and define_method
? Turns out there are three implicit contexts in Ruby. def
and define_method
differ in which one they use.
def
- Ruby keyword, starts a method definition
- Opens a new, isolated scope. Variables defined outside are not accessible inside and vice versa.
- Defines an instance method on the receiver (specified before the method name, e.g.
def object.foo
); implicit receiver is the default definee
The default definee is not self
and...
Test redirects to an external URL with Cucumber/Capybara
When a controller action redirects to an external URL (like http://somehost.com/some/path
) you will find that this is hard to test with Cucumber and Capybara:
- A non-Javascript Rack::Test scenario will just ignore the host and try to open
/some/path
in your local application - A Selenium test will actually follow the redirect, which you probably don't want either
There are two workarounds for this. You can use either, or a combination of both.
- Write a controller spec
Controller specs can test if a resp...
How to disable cookies in cucumber tests
Unfortunately, Capybara does not offer a switch to disable cookies in your test browser. However, you can work around that by using a tiny Rack middleware -- it works for both Selenium and non-Selenium tests.
Wouldn't it be nice to say something like this?
Given cookies are disabled
When I try to sign in
Then I should see "Can't sign you in. Please enable cookies."
You can! Put the code below into some place like lib/rack/cookie_stripper.rb
.
module Rack
class CookieStripper
ENABLED = false
...
Cucumber step to set cookies in your Capybara session
To set a cookie in your test browser for cucumber tests, you need to know which driver you are using. Use the step below according to your driver.
Rack::Test
Given /^I have a "([^\"]+)" cookie set to "([^\"]+)"$/ do |key, value|
headers = {}
Rack::Utils.set_cookie_header!(headers, key, value)
cookie_string = headers['Set-Cookie']
Capybara.current_session.driver.browser.set_cookie(cookie_string)
end
Note that Rack::Utils
is only used to find out the correct cookie header string (you don't want to generate it yours...
Capybara 0.3.9 Bug: Chaining .find to scope doesn't work
The following code doesn't work like expected:
page.find(css_selector).find(other_css_selector)
The second .find will search the whole dom instead of a scope.
Rumor has it this is fixed in Capybara 0.4.1.
Selenium: How to close another tab (popup)
If you open a pop-up window [1] in your Selenium tests and you want to close it, you can do this:
# Find our target window
handle = page.driver.find_window("My window title")
# Close it
page.driver.browser.switch_to.window(handle)
page.driver.browser.close
# Have the Selenium driver point to another window
last_handle = page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(last_handle)
Mind these:
-
find_window
returns a window handle, which is something like `"{485fa8bd-fa99-...
Capturing signatures on a touch device
If you need to capture signatures on an IPad or similar device, you can use Thomas J Bradley's excellent Signature Pad plugin for jQuery.
To implement, just follow the steps on the Github page.
The form
If you have a model Signature
with name: string, signature: text
, you can use it with regular rails form like this:
- form_for @signature, :html => { :class => 'signature_form' } do |form|
%dl
%dt
= form...
Using CSS counters - CSS | MDN
Counters are an awesome CSS feature you didn't know about. It is supported in all browsers and IE8+.
CSS counters are an implementation of Automatic counters and numbering in CSS 2.1. The value of a counter is manipulated through the use of counter-reset and counter-increment and is displayed on a page using the counter() or counters() function of the content property.
lang/unicode_utils · GitHub
UnicodeUtils implements Unicode algorithms for case conversion, normalization, text segmentation and more in pure Ruby code.
If you don't need the ton of features that UnicodeUtils offers, try stringex.
Useful methods to process tables in Cucumber step definitions
When you accept a table in your Cucumber step definition, that table object will have the cryptic type Cucumber::Ast::Table
. Don't immediately call table.raw
to convert it into an array of arrays! Cucumber::Ast::Table
has a lot of useful methods for tasks such as:
table.raw
-
Turn the table into an array of arrays
table.hashes
-
Convert the table to an array of hashes, where the keys are the table headers from the first row
`table.header...
Test that a form field is visible with Cucumber/Capybara
Spreewald now comes with a step that tests if a form field is visible:
Then the "Due date" field should be visible
But the "Author" field should not be visible
The step works by looking up the field for the given label, then checks if that field is hidden via CSS (or Javascript).
It is not currently tested if the label is visible or hidden. For this see: [Check that an element is visible or hidden via CSS with Cucumber/Capybara](https://makandracards.com/makandra/1049-check-that-an-elem...
Memcache: Your cache node may degenerate over time, check your settings
We recently had a problem on a Memcache cluster, where one of the servers showed a significantly worse cache hit rate and a lot more evictions.
It turned out that the only reason was that the server was running for a few months longer than the others. Some investigation showed this to be a known problem with Memcache: Once your cache gets full, it might be "hardwired" for your specific usage patterns. If those change (and you for example start to store larger values), memory is no longer allocated optimally, in extreme cases Memcache might ...
Behave.js
Behave.js is a lightweight library for adding IDE style behaviors to plain text areas, making it much more enjoyable to write code in. Features include:
- Custom Code/Behavior Fencing
- Hard and Soft Tabs
- Auto Open/Close Parenthesis, Brackets, Braces, Double and Single Quotes
- Auto delete a paired character
- Overwrite a paired character
- Multi-line Indentation/Unindentation
- Automatic Indentation
How to update a single gem conservatively
The problem
Calling bundle update GEMNAME
will update a lot more gems than you think. E.g. when you do this:
bundle update cucumber-rails
... you might think this will only update cucumber-rails
. But it actually updates cucumber-rails and all of its dependencies. This will explode in your face when one of these dependencies release a new version with breaking API changes. Which is all the time.
In the example above updating cucumber-rails
will give you Capybara 2.0 (because capybara
is a dependency of `cucumber-rail...
Running "bundle update" without arguments might break your application
Calling bundle update
(without arguments) updates all your gems at once. Given that many gems don't care about stable APIs, this might break your application in a million ways.
To stay sane, update your gems using the applicable way below:
Projects in active development
Update the entire bundle regularily (e.g. once a week). This ensures that your libraries are up-to-date while it's easy to spot major version bumps which may break the app.
Projects that have not been updated in a while
- [Update a single gem conservatively](htt...
Phusion Passenger 4 Technology Preview: Out-Of-Band Work – Phusion Corporate BlogPhusion Corporate Blog
The Out-of-Band Work feature allows one to perform arbitrary long-running work outside the request/response cycle without blocking HTTP clients. The primary use case is to run the garbage collector in between cycles so that your requests will finish faster because they will not be interrupted by the garbage collector.
randym/axlsx · GitHub
Axlsx is an incredible gem to generate "Office Open XML" spreadsheet files (XLSX). Does not break on large spreadsheets and supports a ton of features like graphs.
API looks mature and existing code is easy to migrate when coming from the spreadsheet
gem.
The documentation of some methods is a bit out of date, but you'll find your way around the gem's code.
No support for reading files, however. :( If you want to open XLSX spreadsheets (for example to confirm your output in tests), you can use [roo
](h...