How DECIMAL columns deal with numbers exceeding their precision or scale
When storing floating-point numbers such as prices or totals in an SQL database, always use a DECIMAL
column. Never use FLOAT
or kittens will die.
DECIMAL
columns are parametrized with a precision and a scale. These parameters describe which numbers can be stored in that column. E.g. a decimal with a precision of 5 and a scale of 2 can store numbers from -999.99
to 999.99
, but not 1000
or 1.234
.
This card explains what various databases do when you try to store a number in a DECIMAL
field, and that number exceeds that colum...
Why preloading associations "randomly" uses joined tables or multiple queries
ActiveRecord gives you the :include
option to load records and their associations in a fixed number of queries. This is called preloading or eager loading associations. By preloading associations you can prevent the n+1 query problem that slows down a many index view.
You might have noticed that using :include
randomly seems to do one of the following:
- Execute one query per involved table with a condit...
Cast a string to the type of an ActiveRecord attribute
ActiveRecord models know how to cast a given string to the type of a given attribute (or column).
The following model will serve as our example:
create_table :notes do |t|
t.string :title
t.integer :user_id
t.boolean :deleted
end
You can make the Note
class cast strings into their respective types like this:
Note.columns_hash['user_id'].type_cast('123') # => 123
Note.columns_hash['deleted'].type_cast('1') # => true
Note.columns_hash['deleted'].type_cast('0') # => false
How to send HTTP requests using cURL
-
Reading a URL via GET:
curl http://example.com/
-
Defining any HTTP method (like POST or PUT):
curl http://example.com/users/1 -XPUT
-
Sending data with a request:
curl http://example.com/users -d"first_name=Bruce&last_name=Wayne"
If you use
-d
and do not set an HTTP request method it automatically defaults to POST. -
Performing basic authentication:
curl http://user:password@example.com/users/1
-
All together now:
curl http://user:password@example.com/users/1 -XPUT -d"screen_name=batman"
...
How to perform HTTP basic authentication in RSpec
The Basic Authentication header encodes username and password. Effectively, it's just Base64 plus a "Basic
" prefix.
You can use ActionController::HttpAuthentication::Basic.encode_credentials
for that, and put its result into the Authorization
request header.
Request specs
For request specs, use the :header
option.
it 'requires authentication' do
get '/'
expect(response.status).to eq(401)
end
it 'accepts valid credentials' do
encoded_credentials = ActionController::HttpAuthentication::Basic.encode_credentials(use...
Default views in Rails 3.0 with custom resolvers
It is common in Rails 3.0 applications that you want to provide default views for a group of controllers. Let’s say you have a bunch of controllers inside the Admin namespace and you would like each action to fallback to a default template. So if you are rendering the index action for Admin::PostsController and “app/views/admin/posts/index.html.*” is not available, it should then render “app/views/admin/defaults/index.html”.
Since Rails 3.0, we have a new abstraction called resolvers that holds the logic to find a template.
How to send a test e-mail from shell
If you want to manually check if e-mail delivery works on a machine by sending an e-mail you can run the following:
mail -s Test someone@example.com < /dev/null
This will send an empty e-mail with "Test" as its subject to someone@example.com
.
If you want it to contain a message body, call mail -s Test someone@example.com
only; the mail
application will then read your input from stdin. Finish your message by sending EOT with Ctrl-D -- if you are asked for anything else ...
Imperative vs Declarative Scenarios in User Stories
Bryan talked about the differences between imperative and declarative scenarios. In my opinion, both styles have benefits and should be used appropriately based on the situation. The majority of examples on rspec's story runner currently on the web, including mine, are of the imperative type. Since the declarative type has many advantages I thought it would be worth while to present some examples and contrast the differences between the two styles.
Where to put custom RSpec matchers
When you write a custom RSpec matcher a good place to store them is to create one file per matcher in spec/support/matchers
:
spec/support/matchers/be_same_numbers_as.rb
spec/support/matchers/be_same_second_as.rb
spec/support/matchers/exist_in_database.rb
spec/support/matchers/include_hash.rb
You can include all matchers in the support
directory by adding the following line to your spec_helper.rb
:
Dir[File.expand_path(File.join(File.dirname(__FI...
Test that a hash contains a partial hash with RSpec
To test whether a hash includes an expected sub-hash:
expect(user.attributes).to match(hash_including('name' => 'Bruce Wayne'))
expect(User).to receive(:create!).with(hash_including('name' => 'Bruce Wayne'))
Acceptance testing using Capybara's new RSpec DSL
Back when Steak was first released, Capybara didn’t have any of the nice RSpec helpers it does now. A lot has changed since. Besides the helpers, it got its own RSpec acceptance testing DSL recently, essentially eating Steak’s functionality and turning it into a complete acceptance testing solution (on top of RSpec).
Caching in Rails
The information in this card is only relevant for Rails 2.3-era apps.
This note gives a quick introduction into caching methods (page caching, action caching and fragment caching) in rails and describes some specific problems and solutions.
The descriptions below are valid for Rails 2 and 3. Recently, caching with timestamp- or content-based keys has become more popular which saves you the pain of invalidating stale caches.
How to enable/disable caching
To enable or disable caching in rails you ca...
Liquid Canvas
Liquid Canvas is a JavaScript library which allows you to draw inside an HTML canvas element with an easy yet powerful description language.
It can be used to add graphics to your web page without ever touching an image creation tool such as The Gimp, Inkscape or Photoshop.
Check out the Demo and the basic example and then download version 0.3.
Upgrade from Ruby 1.8.7 to Ruby 1.9.2 on Ubuntu
Note that you cannot currently use Ruby 1.9.2 with Rails 2 applications that use RSpec, so don't upgrade if that is your setup. The rspec-rails gem has a fatal bug that was only fixed for rspec-rails-2.x, which only supports Rails 3. There is no fix for the rspec-rails-1.3.x series of the gem which supports Rails 2.
Anyway, here are upgrade instructions if you only work with Rails 3 or don't use RSpec. You will lose all your gems in the process, but you can get them back easily if you h...
Prevent an ActiveRecord attribute from being changed after creation
Sometimes you can make your life easier by not allowing a record attribute to be changed after the record was created. An example for this is when your model represents a child node in a composition and has logic that is hard to support for cases when the container changes.
Here is an example for a container Region
composed of many children of type Holiday
. After saving a Holiday
it caches the current number of holidays in its region:
class Region < ActiveRecord::Base
...
Upgrading Cucumber and Capybara to the latest versions available for Rails 2
Specify these gem versions in your Gemfile:
gem 'cucumber', '~> 1.3.0'
gem 'cucumber-rails', '= 0.3.2' # max version for Rails 2
gem 'capybara', '< 2' # capybara 2+ requires Rails 3
gem 'mime-types', '< 2' # dependeny of capybara
gem 'nokogiri', '< 1.6' # dependency of capybara
gem 'rubyzip', '< 1' # dependency of selenium-webdriver, rubyzip 1+ requires Ruby 1.9
gem 'cucumber_factory'
gem 'database_cleaner', '< 1'
gem 'cucumber_spinner', '~> 0.2.5'
gem 'launchy', '~> 2.1.2'
With these versions set, `...
Onload callback for dynamically loaded images
Sometimes you need to dynamically load an image and do something as soon as its loaded (when for example its size is already available).
With jQuery, this seems to work across browsers:
$('<img>')
.attr('src', '')
.load(function() {
alert('fully loaded!');
})
.attr('src', '/the/real/image/url');
Customize your Bash prompt
The shell variable PS1
holds your bash prompt. You might want to change it to serve your needs best. Here is how to:
General
- non-printing escape sequences in your prompt have to be inclosed in
\[\e[
and\]
so your shell can correctly count its prompt's length - we recommend to highlight your prompt on production machines
- you can also [show different root prompts for each user](https://makandracards.com/makandra/9569-get-the-username-w...
Sanitize user-generated filenames and only send files inside a given directory
If in your application your users pass along params that result in filenames, like invoices/generated?number=123
. This could be your (very careless) controller method:
def generated
send_file File.join(Rails.root, 'shared', 'invoices', params[:number])
end
This allows your users not only to access those files but also any files your application can read, like this:
invoices/generated?number=../../../../../etc/passwd
# => send_file '/etc/passwd'
You do not want this. In most cases you should prefer a show
met...
CSS3 Pie: Element not properly redrawn
Pie sometimes does not properly redraw elements upon changes. This often happens when the change comes from somewhere further up the DOM.
Consider something like:
<ul>
<li class="active"><div class="content">Active element</div></li>
<li class="inactive"><div class="content">Inactive element</div></li>
</ul>
with CSS
li .content {
-webkit-box-shadow: #666 0px 2px 3px;
-moz-box-shadow: #666 0px 2px 3px;
box-shadow: #666 0px 2px 3px;
behavior: url(/PIE.htc);
back...
RSpec matcher to check if an ActiveRecord exists in the database
The attached RSpec matcher exist_in_database
checks if a given record still exists in the database and has not been destroyed:
describe Ticket do
describe '.purge_expired' do
fresh_ticket = Ticket.create(:expiry => Date.tomorrow)
expired_ticket = Ticket.create(:expiry => Date.yesterday)
Ticket.purge_expired
fresh_ticket.should exist_in_database
expired_ticket.should_not exist_in_database
end
end
Note that there is also [ActiveRecord::Base#destroyed?
](http://apidock.com/rails/ActiveRecord/Base/destroyed...
Mocks and stubs in Test::Unit when you are used to RSpec
We are maintaining some vintage projects with tests written in Test::Unit instead of RSpec. Mocks and stubs are not features of Test::Unit, but you can use the Mocha gem to add those facilities.
The following is a quick crash course to using mocks and stubs in Mocha, written for RSpec users:
|---------------------------------------------------------|
| RSpec | Mocha |
|---------------------------------------------------------|
| obj = double()
| obj = mock()
|
| obj.stub(:method => 'value')
| `obj.stubs...
Alternative to url_for's deprecated :overwrite_params option
If you have the following deprecation warning after upgrading to rails >= 2.3.10
DEPRECATION WARNING: The :overwrite_params option is deprecated. Specify all the necessary parameters instead.
that is for example caused by
url_for( :overwrite_params => { :order => 'name', :dir => 'asc' } )
you can fix this by using params.merge {:my_param_to_overwrite => 'foo' }
.
To fix the example above the code could look like:
url_for( params.merge { :order => 'name...
Output the descriptions of RSpec examples while they are running
In order to
- track down warnings and to see failing specs immediately
- or to get an overview of the core functionalities,
you can use RSpec's "nested" format. It looks like this:
Tool
validations
should require model to be set
should require place_id to be set
#identifier
should include the model and tag if the tool has a tag
should return the model if the tool has no tag
.search
should find tools by model and maker
should find tools by serial number
Call RSpec like...