RubyMine: Efficiently filtering results in the "Finder" overlay
RubyMine comes with a nice way to grep through your project's files: The finder (ctrl + shift + f
). Don't be discouraged about the notice 100+ matches in n+ files
if your searched keyword is too general or widely used in your project.
RubyMine comes with a few ways to narrow down the resulting list, don't hesitate to apply those filters to speed up your search. Your keybinding might vary based on your personal settings.
File mask (alt + k
)
If you already know the file extension of your ...
Rails asset pipeline: Using ESNext without a transpiler
If your app does not need to support IE11, you can use most ES6 features without a build step. Just deliver your plain JavaScript without transpilation through Babel or TypeScript, and modern browsers will run them natively.
Features supported by all modern browsers include:
- fat arrow functions (
() => { expr }
) -
let
/const
class
-
async
/await
- Promises
- Generators
- Symbols
- Rest arguments (
...args
) - Destructuring
You won't be able to use import
and export
, or use npm modules.
See this [ES6 compatibility mat...
Ruby: Do not mix optional and keyword arguments
Writing ruby methods that accept both optional and keyword arguments is dangerous and should be avoided. This confusing behavior will be deprecated in Ruby 2.7 and removed in Ruby 3, but right now you need to know about the following caveats.
Consider the following method
# DO NOT DO THIS
def colored_p(object = nil, color: 'red')
switch_color_to(color)
puts object.inspect
end
colored_p(['an array']) # ['an array'] (in red)
colored_p({ a: 'hash' }, color: 'blue') # {:a=>'hash'} (in blue)
colored_p({ a: 'ha...
Caution: `.includes` can make `.ids` non-unique.
This can happen with a very simple model:
class Note
has_many :attachments
end
Everything looks normal:
Note.all.to_a.size # => 8
Note.all.ids.size # => 8
Then .includes
leads to weird results:
Note.all.includes(:attachments).to_a.size # => 8
Note.all.includes(:attachments).ids.size # => 12
If a note has 5 attachments, its id will be included 5 times.
With .preload
it works as expected:
Note.all.preload(:attachments).to_a.size # => 8
Note.all.preload(:attachments).ids.size # => 8
Note
I crea...
Organizing custom Date(Time) formats
Large Rails projects tend to define multiple custom ways to format Date
s or DateTime
s. This often leads to duplicated format strings, wrong formats and unnecessary introduction of new formats.
to_fs
also supports to refer to those formats by name e.g. to_formatted_s(:iso_8601)
or to_formatted_s(:short)
.
to_fs
is an alias for to_formatted_s
.
Those names are defined in Time::DATE_FORMATS
and it's possible to add your own formats. There is a how to in the official [docs](https://api.rubyonrails.org/classes/Date.html#method-i-t...
Chrome DevTools: Treasure (Overview)
tl;dr
The Chrome DevTools are a neat collection of tools for the daily work as a web developer. If you're lucky, you'll maybe find some handy stuff in here.
Analysing
Breakpoints
- [Breakpoints on HTML Elements](https://makandracards.com/makandra/517982-chrome-devtools...
Sass: Get rid of deprecation warnings in dependencies
TLDR: sass >= 1.35.0
has the option quietDeps
and silenceDeprecations
to silence deprecation warnings from dependencies.
quietDeps: If true, the compiler must not print deprecation warnings
for stylesheets that are transitively loaded through an import path or importer.
You might have seen deprecation warnings like this during assets compilation:
DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($grid-gutter-width, 2)
More info and automated...
Using CSS transitions
CSS transitions are a simple animation framework that is built right into browsers. No need for Javascript here. They're supported by all browsers.
Basic usage
Transitions are used to animate the path between to property values. For example, to let the text color fade from red to green on hover, the following SASS is used (shorthand syntax):
.element
color: red
transition: color .1s
&:hover
color: green
This tells the browser "whenever the color
of an .element
changes...
Everything you ever wanted to know about constant lookup in Ruby
If you ever wondered why a constant wasn't defined or wasn't available where you expected it to be, this article will help.
Also see Ruby constant lookup: The good, the bad and the ugly.
Checklist: Rails Authentication
Authentication is a special part of web applications. On the one hand, it usually is a crucial security mechanism restrict access to certain people and roles. On the other hand, most users authenticate only once, so it is very unlikely to spot issues by accident.
So, here comes a quick checklist to help you verifying your authentication solution is all set.
- This should be default: use HTTPS with HSTS. The HSTS part is important.
- Use a reliable authentication solution, e.g. Clearance or [Devise...
What Sass means by "@function rules may not contain style rules."
When writing a Sass function, you may run into an error message that may be confusing:
@function rules may not contain style rules.
What Sass is trying to tell you is that a line in your Sass function is computing a result that is neither assigned to a variable nor returned.
Keep in mind that all functions in Sass return something, Sass does not mutate objects.
Chrome DevTools: Event Listener Breakpoints
tl;dr
In Chrome DevTools in the Sources tab you can activate Event Listener Breakpoints for debugging events.
Example
The Event Listener Breakpoints in the Chrome DevTools can be quiet useful for debugging why and where code is handling specific events.
Here you can see a very simple example that shows what lines of code handle a click:
You can use this Code Pen if you want to try it yourself.
Limitation
...
Chrome DevTools: DOM Breakpoints - Breakpoints on HTML Elements
tl;dr
In Chrome DevTools in the Elements tab or in Firefox in the Inspector tab you can right click on an element and choose Break on to debug changes related to this element.
Example
DOM Breakpoints can be quite useful to quickly find the JavaScript that is responsible for some (unexpected) behavior. You can use DOM Breakpoints for debugging subtree modifications, attribute modifications or node removal.
Here you can see a very simple example that shows what JavaScript lines are responsible for ...
Stop writing "require 'spec_helper'" in every spec
Simply add this to your .rspec
instead:
--require spec_helper
If you are on rspec >= 3 and use a rails_helper.rb
require this instead of the spec_helper
:
--require rails_helper
If you are using parallel_tests
and this is not working for you, .rspec
might be ignored. Try using a .rspec_parallel
file.
Escape a string for transportation in a URL
To safely transport an arbitrary string within a URL, you need to percent-encode characters that have a particular meaning in URLs, like &
or =
.
If you are using Rails URL helpers like movies_path(:query => ARBITRARY_STRING_HERE)
, Rails will take care of the encoding for you. If you are building URLs manually, you need to follow this guide.
Ruby
In Ruby, use CGI.escape
:
CGI.escape('foo=foo&bar=bar')
=> "foo%3Dfoo%26bar%3Dbar"
Do not ever use URI.encode
or ...
Capybara: evaluate_script might freeze your browser
Capybara gives you two different methods for executing Javascript:
page.evaluate_script("$('input').focus()")
page.execute_script("$('input').focus()")
While you can use both, the first line (with evaluate_script
) might freeze your browser window for 10 seconds.
The reason is that evaluate_script
will always return a result. The return value will be converted back to Ruby objects, which in case of complex objects (e.g. a jQuery collection) is very expensive.
Because of this we recommend to only use evaluate_script
whe...
GitLab: Git alias for creating a merge request on push
Git allows you to set push options when pushing a branch to the remote.
You can use this to build an alias that automatically pushes a branch and creates a merge request for it.
Put this in your ~/.gitconfig
in the [alias]
section:
mr = push origin HEAD -o merge_request.create -o merge_request.draft
Now you can do git mr
and a draft merge request will be created.
Target branch is your project's default branch, i.e. main
or master
.
To specify a different target branch, add -o merge_request.target=other-branch
.
[There...
Chrome DevTools: Quick Bite - Store Element in Global Variable
tl;dr
In the Elements tab in the Chrome DevTools you can right click on an element and select Store as global variable.
Example
How to: Use git bisect to find bugs and regressions
Git allows you to do a binary search across commits to hunt down the commit that introduced a bug.
Given you are currently on your branch's HEAD that is not working as expected, an example workflow could be:
git bisect start # Start bisecting
git bisect bad # Tag the revision you are currently on (HEAD) as bad. You could also pass a commit's SHA1 like below:
git bisect good abcdef12345678 # Give the SHA1 of any commit that was working as it should
# shorthand:
git bisect start <bad ref> <good ref>
Git will fetch a comm...
How to organize monkey patches in Ruby on Rails projects
As your Rails project grows, you will accumulate a number of small patches. These will usually fix a bug in a gem, or add a method to core classes.
Instead of putting many files into config/initializers
, I recommend to group them by gem in lib/ext
:
lib/
ext/
factory_girl/
mixin.rb
carrierwave/
change_storage.rb
fix_cache_ids.rb
sanitize_filename_characters.rb
ruby/
range/
covers_range.rb
array/
dump_to_excel.rb
xss_aware_join.rb
enumerable/
...
Taking screenshots in Capybara
Capybara-screenshot can automatically save screenshots and the HTML for failed Capybara tests in Cucumber, RSpec or Minitest.
Requires Capybara-Webkit, Selenium or poltergeist for making screenshots. They're saved into $APPLICATION_ROOT/tmp/capybara
The attached files contain config for cucumber integration and a Then show me a screenshot
step.
If your project uses Spreewald, you can use its Then show me the page
step instead.
Inclu...
ActiveType::Object: Be careful when overriding the initialize method
Background:
ActiveType::Object
inherits from ActiveRecod::Base
and is designed to behave like an ActiveRecord Object, just without the database persistence.
Don't remove any of the default behavior of the initialize method!
If you have a class which inherits from ActiveType::Object
and you need to override the #initialize
method, then you should be really careful:
- Always pass exactly one attribute.
ActiveRecod::Base
objects really want to get their arguments processable as keyword arguments. Don't change the syntax, or y...
Temporary solution for connection errors with rubygems
The problem
If you're experiencing that your bundle install command fails with an error message like this, rubygems.org might have issues with their ipv6 connectivity:
$ bundle install
Fetching source index from https://rubygems.org/
Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from https://rubygems.org/ due to underlying error <timed out (https://rubygems.org/specs.4.8.gz)>
The (a little bit dirty) possible solution
If that's actually the case, then you can try to deprioritize the ipv...
Debug flaky tests with an Unpoly observeDelay
The problem
Unpoly's [up-observe]
, [up-autosubmit]
and [up-validate]
as well as their programmatic variants up.observe()
and up.autosubmit()
are a nightmare for integration tests.
Tests are usually much faster than the configured up.form.config.observeDelay
. Therefore, it may happen that you already entered something into the next field before unpoly updates that field with a server response, discarding your changes.
The steps I wait for active ajax requests to complete
(if configured) and capybara-lockstep can catch some ...