Preloaded associations are filtered by conditions on the same table
When you eagerly load an association list using the .include
option, and at the same time have a .where
on an included table, two things happen:
- Rails tries to load all involved records in a huge single query spanning multiple database tables.
- The preloaded association list is filtered by the
where
condition, even though you only wanted to use thewhere
condition to filter the containing model.
The second case's behavior is mostly unexpected, because pre-loaded associations usually don't care about the circumstances under whi...
Use the contents of a WordPress database in your Rails app
These two models can be used to access the posts and associated comments of a WordPress database.
Git: Changing commit messages
To change the commit message of the latest (unpushed, unmerged) commit, you can use
git commit --amend
To change the commit message of an earlier (unpushed, unmerged) commit [COMMIT], you can do
git rebase -i COMMIT~
For a current version of git, you can simply mark the line with "reword", and git will ask you later for the new message.
For older versions:
- mark the line with
edit
- save the file
- do a
git commit --amend
when rebasing stops at the relevant commit git rebase --continue
Hints for debugging MySQL InnoDB deadlocks
Deadlocks only occur if two transactions in separate threads compete for the same rows in the database. They usually (but not necessarily) only happen when trying to update or otherwise lock several rows in different order.
Solving deadlocks is potentially complicated, so here are a few pointers:
- MySQL should always detect the deadlock right when it happens, and will throw an error to one of the offending threads. This error states the SQL statement that this thread was currently waiting for, and that tried to acquire one of the competin...
Git: Amending older commits
Lets say you need to make a change to a commit OLD_COMMIT
, but this is not the most recent. If you have neither pushed nor merged it, you can do this:
- Make a new commit now, with a message like "fix".
- Do a
git rebase -i OLD_COMMIT~
- In the editor window that opened, move the "fix" commit directly after the one you want to amend (so it should be the second from the top), and mark it as "fixup". Save the file.
- If there are conflicts, solve them, add them, and do
git rebase --continue
MySQL: Select a default value for NULL fields
If you need to do calculations inside the database and can not use Ruby objects you may run into problems when encountering fields with NULL values:
SELECT foo, bar, foo - bar AS baz FROM plop;
+-----+------+------+
| foo | bar | baz |
+-----+------+------+
| 30 | 20 | 10 |
| 30 | NULL | NULL |
+-----+------+------+
Solve this by using IFNULL
: it returns the selected value if present and a given alternative if it would select NULL:
SELECT foo, bar, foo - IFNULL(bar, 0) AS baz FROM plop;
+-...
Virtual attributes for array fields
When a has_many
association basically serves to store a list of associated strings (tags, categories, ...), it can be convenient to represent this association as a string array in the containing model. Here is an example for this pattern from the acts-as-taggable-on gem:
post = Post.last
p post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
p post.tag_list # ['bam']
This string array tag_list
is magical in several ways:
- It is read from and written to a `has...
Hunt down that elusive debug message in Ruby
When you just went through a long debug-fest and infested your code with dozens of debug messages, it can be hard to find all those calls to puts
and p
. This note describes a hack that lets you trace those messages in your code.
Let's say you want to get rid of a console message "foobar". Copy the Undebug
class below to config/initializers.rb
. In the same initializer, type a line:
Undebug.trace_message('foobar')
Now run tests or whatever you need to do to to trigger that message. The console output should look like this:
...
Virtual attributes for integer fields
Note that this card is very old. You might want to use ActiveType for your auto-coerced virtual attributes instead.
We sometimes give our models virtual attributes for values that don't need to be stored permanently.
When such a virtual attribute should contain integer values you might get unexpected behavior with forms, because every param is a string and you don't get the magic type casting that...
Don't use migrations to seed default data
Don't insert table rows in a Rails database migration. This will break tests that expect that database to be empty and cause you all sorts of pain.
If you need a place for default application data, use db/seed.rb or put a script into lib/scripts
. It won't run automatically, so add a chore story to Pivotal Tracker as a reminder.
Take care when joining and selecting on scopes
Occasionally some complex query must be processed on the database because building thousands of Ruby objects is impracticable.
Many times you would use scope options, like this:
users = User.scoped(
:joins => 'INNER JOIN orders joined_orders ON users.id = joined_orders.user_id',
:conditions => [ 'joined_orders.date BETWEEN ? AND ?', start_date, end_date ],
:select => '*, SUM(joined_orders.amount) AS amount_sum',
:group => 'users.id'
)
You get ActiveRecord objects and you can ask each of them about its `amou...
Test a gem in multiple versions of Rails
Plugins (and gems) are typically tested using a complete sample rails application that lives in the spec
folder of the plugin. If your gem is supposed to work with multiple versions of Rails, you might want to use to separate apps - one for each rails version.
For best practice examples that give you full coverage with minimal repitition of code, check out our gems has_defaults and assignable_values. In particular, take a look at:
- Multiple `sp...
Retrieve the total number of records when paginating with will_paginate
When you use will_paginage to paginate a scope, and you want to obtain the total number of records matched before pagination, you can use total_entries
:
users = User.active.paginate
puts users.count # number of records on this page, e.g. 50
puts users.total_entries # total number of records before pagination, e.g. one billion trillion
This will trigger a second database query in order to retrieve the count (which will run anyway if you render any kind of pagination widget).
`wil...
Change the id of an ActiveRecord record
You most likely never want to do this. But if you do:
Model.update_all({:id => new_id}, {:id => old_id})
Migrate or revert only some migrations
To only run the next two migrations:
rake db:migrate STEP=2
To revert the previous two migrations:
rake db:rollback STEP=2
To revert the last two migrations and then migrate to the most current version:
rake db:migrate:redo STEP=2
To migrate to a given migration number, regardless of whether that means migrating up or down:
rake db:migrate VERSION=20100627185630
To migrate exactly one individual migration out of the sequence* (careful):
rake db:migrate:up VERSION=20100627185630
To revert exactly one individual m...
Select a random table row with ActiveRecord
Use this scope:
class Stick
named_scope :shuffled, lambda {
last_record = last
{ :conditions => [ 'id >= ?', rand(last_record.id) ] } if last_record
}
end
You can now pick a random stick by saying
Stick.shuffled.first
Or, if you prefer something smaller:
class Stick
named_scope :shuffled, :order => 'RAND()'
end
Note however that you should never order by RAND()
on tables that may become large some day, as this performs horribly and can kill your database server.
Show a MySQL table's charset, collation and engine
Use this MySQL command to show further info about a table:
SHOW CREATE TABLE tags;
This will output a table schema like this:
CREATE TABLE `tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_tags_on_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=60 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Undocumented :inverse_of option for ActiveRecord associations
You can now add an :inverse_of option to has_one, has_many and belongs_to associations.... Without :inverse_of m and f.man would be different instances of the same object (f.man being pulled from the database again). With these new :inverse_of options m and f.man are the same in memory instance.
Migrating to RSpec 2 from RSpec 1
You will need to upgrade to RSpec >= 2 and rspec-rails >= 2 for Rails 3. Here are some hints to get started:
- In RSpec 2 the executable is
rspec
, notspec
. - RSpec and rspec-rails have been completely refactored internally. All RSpec classes have been renamed from
Spec::Something
toRSpec::Something
. This also means that everyrequire 'spec/something'
must now berequire 'rspec/something'
. - In
spec_helper.rb
,Spec::Runner.configure
becomesRSpec.configure
- It has become really hard to extend specific example groups ...
Inspecting model callback chains
If you need to look at the list of methods that are called upon certain events (like before/after saving etc), do this:
Model._save_callbacks.select {|cb| cb.kind == :before}.map{ |c| c.instance_variable_get :@filter }
Rails 2
User.after_save_callback_chain
To look at the method names only, you could do something like that:
User.after_save_callback_chain.collect(&:method)
Preload tags with acts-as-taggable-on
When you do tags with acts-as-taggable-on and want to preload associated tags, you can do so with
TaggedModel.scoped(:include => :tag)
Note however that this will only prevent tagged_model.tags
from hitting the database. Using tagged_model.tag_list
does not use the preloaded association.
MySQL: Disable query cache for database profiling
If you want to see how long your database queries actually take, you need to disable MySQL's query cache. This can be done globally by logging into a database console, run
SET GLOBAL query_cache_type=OFF;
and restart your rails server.
You can also disable the cache on a per query basis by saying
SELECT SQL_NO_CACHE * FROM ...
You also probably want to disable Rails internal (per-request) cache. For this, wrap your code with a call to ActiveRecord::Base.uncached
. For example, as an around_filter
:
d...
apotonick's hooks at master - GitHub
Hooks lets you define hooks declaratively in your ruby class. You can add callbacks to your hook, which will be run as soon as you run the hook.
Sun Java JVM/JRE on Ubuntu Linux
Note that you should disable the Java plug-in in your browsers after installation.
Ubuntu >= 12.04
Java 11
sudo apt install openjdk-11-jre-headless
Java 10
sudo add-apt-repository ppa:linuxuprising/java
sudo apt-get update
sudo apt-get install oracle-java10-installer
Java 8
You probably want to get rid of OpenJDK (which is installed by default and leads to bad RubyMine performance):
...