Unsaved record disappears when assigning to an association
If this happens to you:
user.avatar = Avatar.new
user.avatar # => nil
(where avatar
is a belongs_to
), you probably declared your association incorrectly.
Always do
class User < ActiveRecord::Base
belongs_to :avatar
end
and never
class User < ActiveRecord::Base
belongs_to 'avatar'
end
Spreewald: Old-school cucumber steps, freshly pickled
Cucumber_rails' old-school web-steps have been deprecated for a while, urging developers to write high-level step definitions that directly use Capybara or Webrat.
We think that's a bit drastic. More high-level steps are good, but ticking the odd check box with a general step is not always bad.
So we took the old web steps, improved them a bit, added some other favorites of ours (steps for emails, tables, [time travelling](/ma...
How to not leave trailing whitespace (using your editor or Git)
There is no reason to leave trailing whitespace characters in your project's files, so don't add any.
A git diff --check
will tell you if there are any and you should not commit when you see them. So go ahead and switch your editor/IDE to automatically remove them for you.
Below are a few instructions on how to get them removed by your favorite IDE or editor.
Note that except for RubyMine, the following changes will remove trailing white-space on all lines, not only those that you changed.
While this should not be a problem if your proje...
Using before(:context) / before(:all) in RSpec will cause you lots of trouble unless you know what you are doing
TL;DR Avoid before(:context)
(formerly before(:all)
), use before(:example)
(formerly before(:each)
) instead.
If you do use before(:context)
, you need to know what you are doing and take care of any cleanup yourself.
Why?
Understand this:
-
before(:context)
is run when thecontext
/describe
block begins, -
before(:context)
is run outside of transactions, so data created here will bleed into other specs -
before(:example)
is run before each spec inside it,
Generally, you'll want a clean setup for each s...
Git basics: checkout vs. reset
Today I got a better understanding of how git works, in particular what git checkout
and git reset
do.
Git basics
- A commit holds a certain state of a directory and a pointer to its antecedent commit.
- A commit is identified by a so-called ref looking something like
7153617ff70e716e229a823cdd205ebb13fa314d
. - HEAD is a pointer that is always pointing at the commit you are currently working on. Usually, it is pointing to a branch which is pointing to that commit.
- Branches are nothing but pointers to commits. Y...
Distribute files from a private bucket on AWS S3
Given you store files on Amazon S3 and you need to stream those files out to people while you don't want them to be able to distribute the content simply by sharing the S3 URL.
You could either mark the bucket as private and fetch the appropriate files from S3 to your application server and stream them to the client finally. While this is possible, I'd recommend to use what AWS calls "Query String Authentication".
If you're using Paperclip you can chose between two sto...
Highlight current navigation item with Staticmatic
StaticMatic is a nice tool to build simple static websites.
In case you want to have some nifty styles on the navigation item that is currently active, you can use this:
=link 'Aktuelles', :class => (current_page =~ /aktuelles/) ? 'current' : 'default'
Keep in mind that current_page
gives you the full relative path of your page. raise
current_path in case you're not sure.
I know there is an navigation helper out there. I did not use it and also did not want to migrate.
See which MySQL database is currently in use
When you work in the MySQL console and you want to see which database is used, type:
SELECT database();
The result you see is the database you would activate with
USE database_name;
Paperclip: Move attachements from local storage to AWS S3
We frequently use the handy Paperclip Gem to manage file attachments.
If you need to move the files from local storage (i.e., your servers' harddisk) to Amazon S3, you can simply change settings for Paperclip to use the S3 storage adapter and use this script to migrate to S3. Put the snippet into a chore if you don't want to run that in the console.
YOUR_LOCAL_STORAGE_MODEL_DIRECTORY should be something like 'storage/your_model'.
Dir.glob(YOUR_LOCAL_STORAGE_MODEL_DIRECTORY**/*).each do |path|...
Boolean fields in migrations
If you want to update some records with boolean fields in a migration, always remember to set your values with field=#{quoted_true}
and field=#{quoted_false}
. The Rails methods quoted_false
and quoted_true
return the correct boolean representations for your database.
How to test print stylesheets with Cucumber and Capybara
A print stylesheet is easy to create. Choose a font suited for paper, hide some elements, done. Unfortunately print stylesheets often break as the application is developed further, because they are quickly forgotten and nobody bothers to check if their change breaks the print stylesheet.
This card describes how to write a simple Cucumber feature that tests some aspects of a print stylesheets. This way, the requirement of having a print stylesheet is manifested in your tests and cannot be inadvertedly removed from the code. Note that you can...
Reset mysql root password
This article describes how to reset MySQL's or MariaDB's root password on your workstation. It's meant for local development purposes only, don't do this in production. This article will also help you if you have a fairly recent MariaDB version that uses authentication based on linux users instead of passwords for the root user and you prefer using a password for root.
Solution
Step 1 is getting a root mysql shell that allows us to change user credentials. We need to stop the mysql
daemon first and re-start it without authorization c...
Scoping a sunspot solr search by text using a string field
Assuming the following sunspot setup of the post class:
class Post < ActiveRecord::Base
searchable do
text :title
string :state
integer :category_ids
end
end
In Sunspot you can scope your search via the with
method. It allows you to do stuff like:
Post.search {
fulltext "your query", :fields => :title
with(:category_ids).any_of([1,2,3,4,5])
}
If you want to scope your search based on a text field, you have to add another field of the type string
(such as the state fi...
Accept nested attributes for a record that is not an association
Note: Instead of using the method in this card, you probably want to use ActiveType's nested attributes which is a much more refined way of doing this.
The attached Modularity trait allows you to accept nested attributes for a record that is not an association, e.g.:
class Site < ActiveRecord::Base
def home_page
@home_page ||= Page.find_by_name('home')
end
does 'a...
Git: When committing, check the diff
When committing, you should always check the diff of your changes so you don't include any leftovers or irrelevant/bad changes. Any time spent on that is well invested as it saves you rejected merge requests or any mess you need to clean up later.
While you can just use git diff
or git diff --cached
(to diff staged changes), you can also have Git include the changes as a comment below the commit message:
git commit -v
That will open up the usual commit "file" in your preferred text editor, but it will include a diff below the s...
How to inspect controller filter chains in specs
Sometimes you need to look at the filter chain in specs. You can do it like that on Rails 2:
controller.class.filter_chain.map(&:method)
Note that we need to look at the controller's class since before_filter
and after_filter
stuff happens on the class level.
Also mind that the above code will give you all filters, both those run before and after an action. You can query before?
and after?
on the filter objects to scope down to only some of them:
controller.class.filter_chain.select(&:before?).map(&:method)
For Rails 3, ...
Understanding the Selenium error "Modal Dialog Present" (aka Selenium::WebDriver::Error::UnhandledAlertError)
So your Cucumber feature sometimes dies with this exception:
Modal Dialog Present (Selenium::WebDriver::Error::UnhandledAlertError)
As a seasoned Selenium veteran you are used to misleading error messages. Hence you might be surprised that the reason for this particular error is that there is actually a modal dialog present and preventing Selenium from executing commands like click
or page.have_css?
.
How your code triggers this issue
The reason why a dialog is shown is somewhat fucked ...
Rails, callbacks, workers, and the race you never expected to lose « Logical Friday
How delayed jobs can make your after_save
callbacks execute before the record is saved.
MySQL: Can I speed up LIKE queries by adding an index?
For string columns, MySQL indexes the left side of a string. That means an index can speed a like query that has a wildcard on the right side:
SELECT * FROM foo WHERE field LIKE "bar%" # will be faster with an index
It can not speed up a query that has a variable left side:
SELECT * FROM foo WHERE field LIKE "%bar%" # will not be faster with an index
That also means if you use the ancestry gem you should index your ancestry
column if you use scopes like descendants
or `su...
RubyMine: Accessing views and partials from controllers
You can quickly access views that belong to a controller by using the tiny "page with arrow" icon in the gutter:
Access a method's view file
Click the icon next to the method definition in the controller.
If a view file does not yet exist, RubyMine will prompt you for its filename.
All views & partials associated to a controller
For a list of all views and partials that belong to the current ...
Why stubbing on associated records does not always work as expected
Be careful when stubbing out attributes on records that are defined by associations. Nothing is as it seems to be.
The associated record has its own universe of things; when delegating calls to it, you ca not stub methods on the associated record and expect them to be around. That is a general issue with this pattern/approach.
What's happening?
Consider these classes:
class Post < ActiveRecord::Base
belongs_to :thread
def thread_title
thread.title
end
end
class Thread < Acti...
Test your CSS rendering output with GreenOnion
No one wants to cry over regression issues in views; does testing HTML and CSS have to be such a back and forth between designers and devs? Why is it that the rest of the stack can have TDD and BDD but not the presentation layer? Well, GreenOnion is here to help you get the same results on testing front-end styling that you've enjoyed in your unit and integration tests up to now.
GreenOnion records 'skins', which are snapshots of the current state of a view (or any page that a browser can navigate to). The first time that it is run on a view...
Fix error: Missing the mysql2 gem
So you got this error, even though your Gemfile bundles mysql2
:
!!! Missing the mysql2 gem. Add it to your Gemfile: gem 'mysql2'
or
Please install the mysql adapter: `gem install activerecord-mysql-adapter` (mysql is not part of the bundle. Add it to Gemfile.)
The reason for this confusing error message is probably that your Gemfile says mysql2
, but your database.yml
still uses the mysql
adapter. Change it to use the mysql2
adapter:
development:
adapter: mysql2
database: myproject_developm...
MySQL 5.6 will expose tables as key/value stores through memcached, might be awesome
The next version of MySQL will include a built-in memcached daemon. This daemon can quickly get and set key/value pairs from and to InnoDB tables while completely bypassing the parsing and planning overhead of SQL.
This could potentially be very awesome because we would then have a distributed key/value store that stores data in a way it can also be queried with complex SQL queries.