Material Design Lite
CSS (+ some Javascript) framework, implementing Google's material design for static web pages.
Can be used for plain websites without requiring a full blown Javascript framework, unlike the (also excellent) Polymer paper elements, or Angular material.
Prelimiary impression:
I would recommend against using it at this stage, for a couple of reasons:
- It is much less complete than you might expect from a CSS framewor...
A non-weird replacement for grouped_collection_select
Rails comes with grouped_collection_select that appears to be useful, but isn't.
As an alternative, consider the flat_grouped_collection_select found below. It takes a third argument that extracts the group from each element in the collection:
= form.flat_grouped_collection_select :user_id, users, :department, :id, :full_name
Here is the monkey-patch:
class ActionView::Helpers::FormBuilder
def flat_grouped_collection_selec...
Rails 3 ActiveRecord::Persistence#becomes does not copy changed attributes
Note: ActiveRecord::Base#becomes has a lot of quirks and inconsistent behavior. You probably want to use ActiveType.cast instead.
This issue will be encountered when relying on attribute_was methods of ActiveModel::Dirty after casting a model which has defaults to a form model, for example.
In my case a record with an assignable_values legacy value beca...
Querying model errors in Rails 4
ActiveModel supplies an errors object that behaves similar to a Hash. It can be used to add errors to a record, as well as to query the record for registered errors. This object is returned when calling <object>.errors:
errors = @user.errors # => #<ActiveModel::Errors ...>
Here are some helpful messages of its API:
[<attribute name>]-
Returns an array of error messages on that attribute. Example:
errors[:name] => ['is missing']
-
add_on_blank(<attribute list>)(similarlyadd_on_empty) -
Registers an error ...
Reverse-proxying web applications with Apache 2.4+
Note: Making a reverse proxy with nginx is much more straightforward.
A reverse proxy is a "man in the middle" server that tunnels requests to another server. You can use for things like:
- Expose a local service that you cannot directly reach over the internet
- "Change" the domain or path of a web application by rewriting them on the fly
- Instantly change servers that respond to a name or ...
sessionStorage: Per-window browser storage
All major browsers (IE8+, FF3.5+, Safari 4+, any Chrome) support sessionStorage, a JavaScript storage object that
- survives page reloads and browser restores,
- but is different per new tab/window (in contrast to
localStoragewhich is shared across all tabs).
MDN says:
The
sessionStorageobject is most useful for hanging on to temporary data that should be saved and restored if the browser is accidentally refreshed
Demo
Example usage:
Upgrading from Capistrano 2 to 3
Capistrano 3 is a major rework of the framework and requires several adjustments to your deploy configuration files. The biggest change is that they moved away from their custom DSL and use Rake instead. For connecting with and operating on the servers, they bring a new gem SSHKit which does the heavy lifting. It's SSHKit's DSL that is used anywhere inside the Rake tasks. See #Resources at the bottom for examples.
Step 1: Upgrade guide
For migration from 2 to 3, follow this tutorial: [Capistrano 3 Upgrade Guide](https://semaphorec...
Savon testing: How to expect any message
When using Savon to connect a SOAP API, you may want to use Savon::SpecHelper to mock requests in your tests as described in their documentation.
When sending a message body, the savon mock object requires a message to be set, like this:
savon.expects(:action_name).with(message: { user_id: 123 }).returns('<some xml>')
If you want to stub only the returned XML and do not care about request arguments, you can not omit with as Savon's helper will complain:
savo...
Testing setTimeout and setInterval with Jasmine
Jasmine has a jasmine.clock() helper that you can use to travel through time and trigger setTimeout and setInterval callbacks:
beforeEach(function() {
timerCallback = jasmine.createSpy("timerCallback");
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it("causes a timeout to be called", function() {
setTimeout(function() {
timerCallback();
}, 100);
expect(timerCallba...
Why you see a GET "/__identify__" request in Capybara tests
You might wonder about this request in your test.log:
Started GET "/__identify__" for 127.0.0.1 at 2015-04-29 18:00:02 +0100
This is what happens: For drivers like Selenium, Capybara will boot up a Thin or Webrick server in a separate thread. It then makes a GET request to /__identify__ to see if the server is ready to accept requests.
Since you don't have a route that responds to /__identify, Capybara will wrap your Rails app in...
PostgreSQL vs MySQL: How to UPDATE using a JOIN
When you want to UPDATE a table with information from an associated table, you can JOIN the associated table into the statement.
Example
Let's say you have a database schema where an Employee belongs_to :department:
+-----------------+
| Employee | +------------+
|-----------------| n 1 | Department |
| email |-------------------|------------+
| department_id | | name |
+-----------------+ +------------+
Because of perfo...
PSA: "index: true" in Rails migrations does not work as you'd expect
Several Rails migration methods accept index: true as an option to create an index. In some cases (like #add_column), this option is silently discarded. Know what you are doing, or use #add_index instead.
Example
Consider the following migration.
class CreateExamples < ActiveRecord::Migration
def change
create_table :examples do |t|
t.references :category, index: true
t.boolean :positive, index: true
t.integer :number_of_participants, index: true
end
add_reference :examples, :user, index: tr...
A solid and unobtrusive plugin for form field placeholders
jquery-placeholder is a simple jQuery plugin that enables form placeholders in browsers that do not support them natively, i.e. IE < 10.
Properties
- Works in IE6.
- Automatically checks whether the browser natively supports the HTML5 placeholder attribute for input and textarea elements. If this is the case, the plugin won’t do anything. If @placeholder is only supported for input elements, the plugin will leave those alone and apply to textareas exclusively. (This is the case for Safari 4, Opera 11.00, and possibly other browsers.)
...
Ruby bug: Symbolized Strings Break Keyword Arguments in Ruby 2.2
TL;DR Under certain circumstances, dynamically defined symbols may break keyword arguments in Ruby 2.2. This was fixed in Ruby 2.2.3 and 2.3.
Specifically, when …
- there is a method with several keyword arguments and a double-splat argument (e.g.
def m(foo: 'bar, option: 'will be lost', **further_options)) - there is a dynamically created
Symbol(e.g.'culprit'.to_sym) that is created before the method is parsed - the method gets called with both the
optionand aculpritkeyword argument
… then the `optio...
What Ruby’s ||= (Double Pipe / Or Equals) Really Does
It is a common misunderstanding that all [op]=-operators work the same way, but actually they don't.
||= and &&=
Those are special cases, because the assignment will only happen if the first variable passes the check (false or nil for || and true for &&).
a ||= b # => a || (a = b)
a &&= b # => a && (a = b)
But still, if reading a has any side effects, they will take place regardless of to what a resolves.
Other [op]=
Assignment will always take place, no matter the value of a.
Using mime types with send_file
When using send_file (for example for attachments of any kind), make sure your application knows the correct mime types so that all browsers can handle the files. It is much more convenient for users if they can decide to open a file directly instead of having to save it first.
For Rails >= 3.2
Simply put your mime types in config/initializers/mime_types.rb. send_file will take care of everything else.
For Rails < 3.2
Put your mime types in config/initializers/mime_types.rb. Additionally, tell send_file to use them (for ex...
RSpec: Tagging examples and example groups
In RSpec you can tag examples or example groups with any tags you like simply by saying
describe ReportCreator, slow: true do
# ..
end
describe ReportCreator do
it 'generates reports', slow: true do
# ...
end
end
You can then only run examples with these tags.
rspec --tag slow
rspec -t slow
# Using the parallel_tests gem
rake "parallel:spec[,,--tag slow]"
Or you can run all examples except the ones with a certain tag:
rspec --tag ~slow # note the ~
rspec -t ~slow
# Using the parallel_tests gem
r...
Ruby: How to grow or shrink an array to a given size
If you want to grow a Ruby Array, you might find out about #fill but it is not really what you are looking for. [1]
For arrays of unknown size that you want to grow or shrink to a fixed size, you need to define something yourself. Like the following.
Array.class_eval do
def in_size(expected_size, fill_with = nil)
sized = self[0, expected_size]
sized << fill_with while sized.size < expected_size
sized
end
end
Use it like this:
>> [1, 2, 3].in_size(5)
=> [1, 2, 3, nil, nil]
...
Don't forget: Automatically remove join records on has_many :through associations
Bad
# Given the following models
class Image < ActiveRecord::Base
has_many :album_images
has_many :albums, through: :album_images
end
class Album < ActiveRecord::Base
has_many :album_images
has_many :images, through: :album_images
end
# Join model
class AlbumImage < ActiveRecord::Base
belongs_to :album
belongs_to :image
end
Destroying a record in this setup will only remove the record itself, and leave orphaned join records behind.
image = Image.last
image.destroy # removes only the `image` record,
...
Using form models (aka decorators) with Devise
To use a form model with devise, you can simply override #resource_class in a controller. A typical use case would be the registrations controller, as users will need some fields only on sign-up. Example:
class Frontend::Authentication::RegistrationsController < Devise::RegistrationsController
private
def resource_class
FrontendUser::AsSignUp # my decorator class, extending from FrontendUser
end
end
Fontawesome 4+ icon naming conventions
Fontawesome 4 has introduced new naming conventions that make it easy to retrieve variants of a given icon.
The format is:
fa-[name]-[alt]-[shape]-[o]-[direction]
Note that this is a naming convention which doesn't imply there's an icon for any combination of tags.
name
The name of the icon, e.g. comment, print, bookmark etc. See the full list.
alt
An alternative icon.
shape
The icon inside a circle or square.
o
An outlined ...
Rails 4 introduced collection_check_boxes
Starting from Rails 4.0, you can use a special form options helper called #collection_check_boxes. It behaves similar to #collection_select, but instead of a single select field it renders a checkbox and a label for each item in the collection.
= form_for @post do |form|
= form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial
How generated form params look like
---------------------------------...
Capybara: Waiting for pending AJAX requests after a test
When ending a Selenium test Capybara resets the browser state by closing the tab, clearing cookies, localStorage, etc.
It may be a good idea to wait for all in-flight AJAX requests to finish before ending a scenario:
- You may have client-side JavaScript that freaks out when the tab closure kills their pending requests. If that JavaScript opens an error alert or spams errors to the console, your test may fail after the last step.
- With unlucky timing the server may receive an AJAX request as the browser tab closes, causing a connection ...
rspec_candy 0.4.0 released
- Now supports RSpec 3 and Rails 4
- Drops support for
state_machine, which has some issues with Rails 4 and isn't actively maintained