Whitelist Carrierwave attributes correctly
Say you have a User with a Carrierwave attribute #avatar:
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
When whitelisting the avatar field in the controller, you might do this:
params[:user].permit(:avatar)
But you probably want this:
params[:user].permit(:avatar, :avatar_cache, :remove_avatar)
In this example:
-
:avatar_cacheallows a newly upload image to persist through form roundtrips in the case of validation errors (something that isn't possibl...
How to find out the type of a model's attribute
When you want to find out the data type of an attribute, you can just use ActiveRecord's columns_hash method.
It returns a hash of column objects that include a type attribute (and more database-related information).
Example:
Contract.columns_hash['id'].type
=> :integer
Contract.columns_hash['active'].type
=> :boolean
Contract.columns_hash['updated_at'].type
=> :datetime
Mysql collate, searching case sensitive
Usually our mysql queries are not case sensitive. In order to query case sensitive, you can use the mysql COLLATE clause.
The collate clause lets you specify a collation, which basically is a set of rules for comparing characters in a given character set.
The suffixes ci, cs, bin of a collation stand for case insensitive, case sensitive and binary, respectively. A binary collation such as utf8_bin is case sensitive as well since it compares the characters based on their numeric values.
SELECT * FROM use...
Your database tables should always have timestamps
Whenever you create a table from a database migration, remember to add updated_at and created_at timestamps to that table. Without those timestamps, investigating future bug reports will be hell. Always have timestamps.
Adding timestamps to new tables
When you create a table using create_table, you can add timestamps by using the timestamps shortcut:
class CreateEpisode < ActiveRecord::Migration
def change
create_table :episodes do |t|
t.string :name
t.timestam...
Carrierwave – Recreate versions
A snippet of the carrierwave documentation
You might come to a situation where you want to retroactively change a version or add a new one. You can use the recreate_versions! method to recreate the versions from the base file. This uses a naive approach which will re-upload and process the specified version or all versions, if none is passed as an argument.
Call recreate_versions! on a mounted uploader.
A common usecase
User.all.each { |user| user.avatar.r...
A simpler default controller implementation
Rails has always included a scaffold script that generates a default controller implementation for you. Unfortunately that generated controller is unnecessarily verbose.
When we take over Rails projects from other teams, we often find that controllers are the unloved child, where annoying glue code has been paved over and over again, negotiating between request and model using implicit and convoluted protocols.
We prefer a different approach. We believe that among all the classes in a Rails project, controllers are some of the hardest to...
How to not repeat yourself in Cucumber scenarios
It is good programming practice to Don't Repeat Yourself (or DRY). In Ruby on Rails we keep our code DRY by sharing behavior by using inheritance, modules, traits or partials.
When you reuse behavior you want to reuse tests as well. You are probably already reusing examples in unit tests. Unfortunately it is much harder to reuse code when writing integration tests with Cucumber, where you need to...
PostgreSQL vs. Rails migration: How to change columns from string to integer
When writing Rails migrations to convert a string column to an integer you'd usually say:
change_column :table_name, :column_name, :integer
However, PostgreSQL will complain:
PG::DatatypeMismatch: ERROR: column "column_name" cannot be cast automatically to type integer
HINT: Specify a USING expression to perform the conversion.
The "hint" basically tells you that you need to confirm you want this to happen, and how data shall be converted. Just say this in your migration:
change_column :table_name, :column_name, 'i...
ActiveRecord::StatementInvalid: Mysql2::Error: closed MySQL connection
I recently experienced the error ActiveRecord::StatementInvalid: Mysql2::Error: closed MySQL connection. Apparently this happens when there is a timeout during query execution. In order to fix this you can reconnect to your db.
Therefore either add reconnect: true to your database.yml for automatic reconnection when the error occurs or catch the error and manually and reconnect explicitly via ActiveRecord::Base.connection.reconnect!
Be aware that reconnecting will have the following impact on your current connection:
- Any active tr...
How to change the locale of a PostgreSQL cluster
There may be reasons to change the locale of your Postgres cluster. A popular one is your development system's locale being used by default (which may be annoying). Here is how to do that.
Beware: By following the steps below, you will drop and recreate your cluster. You will lose all data (including roles). Instructions below include a procedure for dumping and restoring all cluster data (including roles). While it worked at the time of writing, you should have extra backup strategies for a production database.
- Find the cluster you...
PostgreSQL cheat sheet for MySQL lamers
So you're switching to PostgreSQL from MySQL? Here is some help...
General hints on PostgreSQL
-
\?opens the command overview -
\dlists things:\dulists users,\dtlists tables etc
Command comparison
| Description | MySQL command | PostgreSQL equivalent |
|---|---|---|
| Connect to the database | mysql -u $USERNAME -p |
sudo -u postgres psql |
| Show databases | SHOW DATABASES; | \l[ist] |
| Use/Connect to a database named 'some_database' | USE some_database; | \c some_dat... |
Capybara: Trigger requests with custom request method
Preface: Normally, you would not need this in integrations tests (probably that's why it is so hard to achieve), because it is no actual "integration testing". If you use this step, know what you are doing.
Destroying a record with Capybara is not as easy as calling visit user_path(user, method: :delete), because RackTest's visit can only perform GET requests.
With this step you can destroy a records using either Selenium or RackTest. Ex...
Consul 0.10.0 allows multiple power mappings for nested resources
Consul 0.10.0 now allows multiple power mappings for nested resources.
When using nested resources you probably want two power
checks and method mappings: One for the parent resource, another for the child resource.
Say you have the following routes:
resources :clients do
resources :notes
end
And the following power definitions:
class Power
...
power :clients do
Client.active if si...
Rails: Output helpers for migrations
When you're writing migrations that do more than changing tables (like, modify many records) you may want some output. In Rails > 3.1 you have two methods at hand: announce and say_with_time.
In the migration:
class AddUserToken < ActiveRecord::Migration
class User < ActiveRecod::Base; end
def up
add_column :users, :token, :string
announce "now generating tokens"
User.find_in_batches do |users|
say_with_time "For users ##{users.first.id} to ##{users.last.id}" do
users.each do |user|
...
Testing shared traits or modules without repeating yourself
When two classes implement the same behavior (methods, callbacks, etc.), you should extract that behavior into a trait or module. This card describes how to test that extracted behavior without repeating yourself.
Note that the examples below use Modularity traits to extract shared behavior. This is simply because we like to do it that way at makandra. The same techniques apply for modules and overriding self.included.
Example
---...
RSpec: Where to put shared example groups
Shared example groups are a useful RSpec feature. Unfortunately the default directory structure generated by rspec-rails has no obvious place to put them.
I recommend storing them like this:
spec/models/shared_examples/foo.rb
spec/models/shared_examples/bar.rb
spec/models/shared_examples/baz.rb
spec/controllers/shared_examples/foo.rb
spec/controllers/shared_examples/bar.rb
spec/controllers/shared_examples/baz.rb
To ma...
angular/angularjs-batarang
Extends the Chrome WebInspector so you can debug AngularJS applications and hunt down performance issues.
It's really, really good.
Git: How to remove ignored files from your repository's directory
When you have files in your .gitignore they won't be considered for changes, but still you might want to get rid of them, e.g. because they clutter your file system.
While a regular git clean will ignore them as well, passing the -x switch changes that:
git clean -x
If you want to see what would happen first, make sure to pass the -n switch for a dry run:
git clean -xn
Clean even harder by passing the -f (force cleaning under certain circumstances; I think this is also required by default) or -d (removes director...
MySQL: Careful when using database locks in transactions
We tend to use database transactions as a magic bullet to get rid of all our concurrency problems. When things get really bad, we might even throw in some locking mechanism, but then are usually done with it.
Unfortunately, transactions semantics in databases are actually very complicated, and chances are, your making some incorrect assumptions.
The MySQL innodb engine actually has [four different modes](ht...
Consul 0.9 lets you optimize records checks
Consul 0.9 comes with many new features to optimize powers that only check access to a given record. e.g. Power.current.post?(Post.last). See below for details.
Powers that only check a given object
Sometimes it is not convenient to define powers as a collection. Sometimes you only want to store a method that
checks whether a given object is accessible.
To do so, simply define a power that ends in a question mark:
class Power
...
power :upd...
How to tell ActiveRecord how to preload associations (either JOINs or separate queries)
Remember why preloading associations "randomly" uses joined tables or multiple queries?
If you don't like the cleverness of this behavior, you can explicitely tell ActiveRecord how to preload associations with either JOINs or separate queries.
This card gives an overview of the different options to preload associations, but
__Whic...
Common mistakes when storing file uploads with Rails
1. Saving files to a directory that is not shared between deploys or servers
If you save your uploads to a made up directory like "RAILS_ROOT/uploads", this directory goes away after every deploy (since every release gets a new). Also this directory is not shared between multiple application servers, so your uploads are randomly saved to one local filesystem or another. Fixing this afterwards is a lot of fun.
Only two folders are, by default, shared between our application servers and deployments: "RAILS_ROOT/storage" and `"RAILS...
Upgrading Rails 2 from 2.3.8 through 2.3.18 to Rails LTS
This card shows how to upgrade a Rails 2 application from Rails 2.3.8 through every single patch level up to 2.3.18, and then, hopefully, Rails LTS.
2.3.8 to 2.3.9
This release has many minor changes and fixes to prepare your application for Rails 3.
Step-by-step upgrade instructions:
- Upgrade
railsgem - Change your
environment.rbso it saysRAILS_GEM_VERSION = '2.3.9' - Change your ...
ActiveRecord.select
Active Record's select method allows you to make use of the power of MySQL select statements. On the one hand it allows you to select specific fields.
Post.select("content")
results in the following query:
"SELECT content FROM `posts`"
This means that your models will be initialized with only the content attribute and you will not be able to access any other attribute. In fact trying so would raise an ActiveRecord::MissingAttributeError error.
Post.select("content").first.title # => ActiveRecord::MissingAttributeErr...