Collect all values for a given column in an ActiveRecord scope
In modern Rails versions you can also use ActiveRecord's pluck method.
User.active.pluck(:id)
=> [1, 5, 23, 42]
If you are plucking from the id column in particular you can also say:
User.active.ids
=> [1, 5, 23, 42]
For a DISTINCT selection, use distinct on your scope (not the resulting array).
Article.distinct.pluck(:state)
...
Testing state_machine callbacks without touching the database
You should test the callback methods and its correct invocation in two separate tests. Understand the ActiveRecord note before you move on with this note.
Say this is your Spaceship class with a transition launch and a release_docking_clamps callback:
class Spaceship
state_machine :state, :initial => :docked do
event :launch do
transition :docked => :en_route
end
before_transition :on => :launch, :do => :release_doc...
Detect the language of a string
You can use the whatlanguage gem to detect the language of a Ruby string.
Note that it also has not been updated in quite a while and that there might be alternatives. However, it still works.
It has problems with short strings, but works quite well on longer texts.
Use it like this:
>> WhatLanguage.new(:all).language('Half the price of a hotel for twice the space')
=> :english
There is also a convenience method on Strings (you may need to require 'whatlanguage/string').
>> 'Wir ent...
Understand ActiveRecord::ReadOnlyRecord error
When you load a record with find options that have SQL fragments in :select or :joins, ActiveRecord will make that record read-only. This is a protective measure by Rails because such a record might have some additional attributes that don't correspond to actual table columns.
You can override that precaution by appending :readonly => false to affected find options or scope options.
Automatic Flushing: The Rails 3.1 Plan « Katz Got Your Tongue?
This post explains, in some detail, how we will implement a nice performance boost for Rails developers. Understanding the details might help gain the full benefits of the optimization, but you will gain some benefits even if you have no idea how it works.
Scope to records with a given state in state_machine
The state_machine gem ships with a scope with_state. This scope has some problems in complex queries or scope chains.
Use this instead:
named_scope :having_state, lambda { |*state_or_states|
state_or_states = Array.wrap(state_or_states).map(&:to_s)
{ :conditions => [ 'articles.state IN (?)', state_or_states ] }
}
If you want a scope with hash options (with the side effects you should know about):
named_scope :having_st...
Rails: Preloading associations in loaded records
Sometimes you want to fetch associations for an ActiveRecord that you already loaded, e.g. when it has deeply nested associations.
Edge Rider gives your models a static method preload_associations. The method can be used to preload associations for loaded objects like this:
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
@user.preload_associations(threads: { posts: :author }, messages: :sender)
end
end
The attached initializers re...
Efficiently add an event listener to many elements
When you need to add a event listener to hundreds of elements, this might slow down the browser.
An alternative is to register an event listener at the root of the DOM tree (document). Then wait for events to bubble up and check whether the triggering element (event.target) matches the selector before you run your callback.
This technique is called event delegation.
Performance considerations
Because you only register a single listener, registering is ...
How Rails and MySQL are handling time zones
When working with times and dates in Rails applications, you need to deal with the following problem:
- In Rails,
Timeobjects have a time zone. You can get the zone name by doingtime_object.zone. - This zone is considered when doing time calculations, e.g. 10 AM CEST minus 8 AM UTC is zero.
- A datetime in MySQL does not have a zone. It just stores the literal string "2010-05-01 12:00:00".
- That means that Rails must make assumptions about timestamps loaded from and written to MySQL.
Rails has two completely different modes ...
Regular Expressions - Cheat Sheet
You can write regular expressions some different ways, e.g. /regex/ and %r{regex}. For examples, look here.
Remember that it is always a good idea to match a regex visually first.
Characters
Literal Characters
[ ] \ ^ $ . | ? * + ( )
Character Classes
[ae] matches a and e, e.g. gr[ae]y => grey or gray => but NOT graay or graey
[0-9] ...
Default implementation of resource_controller actions
jamesgolick / resource_controller at Github
module ResourceController
module Actions
def index
load_collection
before :index
response_for :index
end
def show
load_object
before :show
response_for :show
rescue ActiveRecord::RecordNotFound
response_for :show_fails
end
def create
build_object
load_object
before :create
if object.save
...
Order for SELECT ... IN (5,100,23) queries
When doing a query like this:
SELECT id FROM users WHERE (users.id IN (899,1084,1095,100,2424,2429,2420))
the order of the returned records is undefined. To force the query to return the records in a given order, you have to add ORDER BY FIELD(id, 899, 1084, ...)
So the query looks like this:
SELECT id FROM users WHERE (users.id IN (899,1084,1095,100,2424,2429,2420)) ORDER BY FIELD(id,899,1084,1095,100,2424,2429,2420);
Faking and testing the network with WebMock
An alternative to this technique is using VCR. VCR allows you to record and replay real HTTP responses, saving you the effort to stub out request/response cycles in close details. If your tests do require close inspection of requests and responses, Webmock is still the way.
WebMock is an alternative to FakeWeb when testing code that uses the network. You sh...
Change default size of Gnome terminal
Open the configuration file:
gksudo gedit /usr/share/vte/termcap/xterm
Find a line like this:
:co#80:it#8:li#24:\
Change the first and last number to your desired columns and rows:
:co#160:it#8:li#40:\
Save your changes and close all open terminals. New terminals should now open with the new size.
Dumping and importing from/to MySQL in an UTF-8 safe way
In a nutshell: to avoid your shell character set from messing with imports, use -r to export and SOURCE when importing.
Dumping safely
# Do not do this, since it might screw up encoding
mysqldump -uroot -p database > utf8.dump # this is bad
Better do:
mysqldump -uroot -p database -r utf8.dump
Note that when your MySQL server is not set to UTF-8 you need to do mysqldump --default-character-set=latin1 (!) to get a correctly e...
UTF-8ify an existing MySQL database
First do
ALTER DATABASE database_name CHARACTER SET "utf8";
ALTER DATABASE database_name COLLATE "utf8_unicode_ci";
After that, for each table:
ALTER TABLE table_name DEFAULT CHARACTER SET "utf8" COLLATE "utf8_unicode_ci";
This just changes the default character set / collation for each table. To convert them, you need:
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
jeremyevans's home_run at master - GitHub
home_run is an implementation of ruby’s Date/DateTime classes in C, with much better performance (20-200x) than the version in the standard library, while being almost completely compatible.
stefankroes's ancestry at master - GitHub
Ancestry is a gem/plugin that allows the records of a Ruby on Rails ActiveRecord model to be organised as a tree structure (or hierarchy). It uses a single, intuitively formatted database column, using a variation on the materialised path pattern. It exposes all the standard tree structure relations (ancestors, parent, root, children, siblings, descendants) and all of them can be fetched in a single sql query. Additional features are STI support, named_scopes, depth caching, depth constraints, easy migration from older plugins/gems, integrit...
MySQL replication how-to
This may be awkward to set up, but will work once you're done.
Fun facts:
- In case of a connection loss the slave will try to reconnect to the master server and resume replication for the next 24 hours
- If you want to use your slave as a "real" MySQL server, you basically need to switch off replication (
STOP SLAVE; RESET SLAVE;and reset your my.cnf) and restart the MySQL daemon.
Master server configuration
-
- Create replication user
- In the MySQL shell:
CREATE USER 'replicator'@'%' IDENTI...
MySQL Server and UTF-8 Defaults
Unless all MySQL server defaults are set to UTF-8, mysqldump encodes UTF-8 characters incorrectly and only outputs correct UTF-8 when you switch to Latin 1 (!). Also you need to setup charset and collation manually for each new database.
To prevent this, make sure your /etc/mysql/my.cnf looks like this:
[mysqld]
default-character-set = utf8mb4
collation-server = utf8mb4_unicode_ci
[mysql]
default-character-set=utf8mb4
After that do
sudo /etc/init.d/mysql restart
Test concurrent Ruby code
To test concurrent code, you will need to run multiple threads. Unfortunately, when you use blocking system calls (e.g. locks on the database), Ruby 1.8 threads won't work because system calls will block the whole interpreter.
Luckily you can use processes instead. fork spins off a new process, IO.pipe sends messages between processes, Process.exit! kills the current process. You will need to take care of ActiveRecord database connections.
Here is a full-fledged example:
describe Lock, '.acquire' do
before :each do
...
Concurrent Tests
Install gem and plugin
sudo gem install parallel
script/plugin install git://github.com/grosser/parallel_tests.git
Adapt config/database.yml
test:
database: xxx_test<%= ENV['TEST_ENV_NUMBER'] %>
Create test databases
script/dbconsole -p
CREATE DATABASE `xxx_test2`;
...
Generate RSpec files
script/generate rspec
(you'll probably only let it overwrite files in script/)
Prepare test databases...
Convert Haml to ERB
This is about converting Haml to ERB and not the other way round which you probably want!
This process can not be automated 100%, but you can still save time.
First do
script/plugin install http://github.com/cgoddard/haml2erb.git
Then in the console type
hamls = Dir["app/views/**/*.haml"] - ['app/views/layouts/screen.html.haml'];
hamls.each do |haml|
puts haml
erb = haml.sub(/\.haml$/, '.erb')
File.open(erb, 'w') do |file|
file.write Haml2Erb.convert(File.read(haml))
end
end
After th...
How to install the date_performance gem
sudo gem install zip
git clone git://github.com/rtomayko/date-performance.git
cd date-performance
rake package:build
cd dist
sudo gem install --no-ri --no-rdoc date-performance-0.4.7.gem