Here is a Javascript function reloadUsers()
that fetches a HTML snippet from the server using AJAX and replaces the current .users
container in the DOM:
window.reloadUsers = ->
$.get('/users').then (html) ->
$('.users').html(html)
Testing this simple function poses a number of challenges:
<div class="users">...</div>
container in the current DOM. Obviously the Jasmine spec runner has no such container./users
and we want to prevent network interaction in our uni...In the past we validate and set default values for boolean attributes in Rails and not the database itself.
Reasons for this:
An alternative approach, which currently reflects more the general opinion of the Rails upstream on constraints in the database, is adding default values in the schema of the database itself. We also ...
HTTP header values must only contain low-ASCII (7-bit) characters for safe transport. From RFC 7230:
Historically, HTTP has allowed field content with text in the ISO-8859-1 charset [ISO-8859-1], supporting other charsets only through use of [RFC2047] encoding. In practice, most HTTP header field values use only a subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD limit their field values to US-ASCII octets.
If you need to transport 8-bit+ characters (e.g...
When installing gems, a lot of time is spent building locally installed documentation that you probably never use.
We recommend you disable documentation generation for gem install
by default.
Note that Bundler won't install documentation, so this advice applies only when installing gems manually.
If you don't already have it, create a ~/.gemrc
file. The gemrc is a Yaml file, so add the following line to add default switches to the gem
command.
gem: --no-document
(If you do n...
#size
in most cases.
#size
and #count
. See below.COUNT(*)
query if a counter cache is not set up.#count
will return that cached value instead of executing a new query.RubyMine has a HTTP Client that can be useful to test web APIs.
Just create a .http
scratch file an write your request in it.
The request can then be executed with the "Run all requests in File" button above the file.
Some alternatives:
The format for request is like this:
Method Request-URI HTTP-Version
Header-field: Heade...
Not all email clients support external images in all situations, e.g. an image within a link. In some cases, a viable workaround is to turn your images into inline attachments.
Note
Rails provides a simple mechanism to achieve this:
This documentation makes it look like you have to care about these attachments in two places. You have to create the attachment in t...
Carrierwave's BaseUploader
can have some validations that you can use by overriding a certain method, which's expected name is hard coded. A popular example is extension_allowlist
, which returns an array of strings and let's you only upload files that have a filename with an extension that matches an entry in that array. Another useful validation can be size_range
, which gives you a little bit of control over how your storage gets polluted.
This is often good enough, but some times you need to validate special cases.
Since Rails 7 you are able to encrypt database information with Active Record. Using Active Record Encryption will store an attribute as string in the database. And uses JSON for serializing the encrypted attribute.
Example:
p
: Payloadh
: Headersiv
: Initialization Vectorat
: Authentication Tag{ "p": "n7J0/ol+a7DRMeaE", "h": { "iv": "DXZMDWUKfp3bg/Yu", "at": "X1/YjMHbHD4talgF9dt61A=="} }
Note this before encrypting attributes with Active Record:
...
Just run git show branch:file
. Examples:
git show HEAD~:bin/command
git show origin/master:../lib/version.rb
For outputting a given String in HTML, you mostly want to replace line breaks with <br>
or <p>
tags.
You can use simple_format
, but it has side effects like keeping some HTML.
If you only care about line breaks, you might be better off using a small, specialized helper method:
def format_linebreaks(text)
safe_text = h(text)
paragraphs = split_paragraphs(safe_text).map(&:html_safe)
html = ''.html_safe
paragraphs.each do |paragraph|
html << content_tag(:p, paragraph)
end
html
end
Full di...
Sometimes I ran across a GitHub merge request of a gem where it was not completely obvious in which version the change was released. This might be the case for a bugfix PR that you want to add to your project.
Git can help you to find the next git tag that was set in the branch. This usually has the name of the version in it (as the rake release
task automatically creates a git tag during release).
git name-rev --tags <commit ref>
Note
The more commonly used
git describe
command will return the last tag before a c...
In Rails 5+ you can access a helper from a controller using the helpers
method:
# Inside a controller action
helpers.link_to 'Foo', foo_path
In older Rails versions you can use view_context
instead:
# Inside a controller action
view_context.link_to 'Foo', foo_path
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:
where
condition, even though you only wanted to use the where
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...
We can use ActiveRecord's where
to add conditions to a relation. But sometimes our condition is not on the model itself, but on an associated model. This card explains multiple ways to express this condition using ActiveRecord's query interface (without writing SQL).
As an example we will use a User
that has many Post
s:
class User < ApplicationRecord
has_many :posts
scope :active, -> { tra...
When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself.
Here we build a simple SVG image and wrap it into a data:
URI. All browsers support SVG, and you can easily adjust it yourself.
Simply set it as an image's src
attribute.
Simple solution in modern JavaScript, e.g. for use in the client's browser:
function svgUri(text) {
let svg = `
<svg width="320" height="240" xmlns="http://www.w3...
There is a kind of features in web applications that hinder automated integration tests. Examples include cookie consent banners or form captchas. Clearly, these should be disabled so you do not have to explicitly deal with them in each and every test (like, every test starting with accepting the cookies notice). On the other hand, they must be tested as well.
A good feature disabling solution should therefore meet these requirements:
The feature is generally disabled in tests. A test does not need to do anything manually.
It is *...
return
to return from a method. return
accepts a value that will be the return value of the method call.break
to quit from a block and from the method that yielded to the block. break
accepts a value that supplies the result of the expression it is “breaking” out of.next
to skip the rest of the current iteration. next
accepts an argument that will be the result of that block iteration.The following method will serve as an example in the details below:
def example
puts yield
puts ...
There are three ways to define your own RSpec matchers, with increasing complexibility and options:
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
# optional
failure_message do |actual|
"expected that #{actual} would be a multiple of #{expected}"
end
# optional
failure_message_when_negated do |actual|
"expected that #{actual} would not be a multiple of #{expected}"
end
end
This is automatically available in ...
Note
This card does not reflect the current state of lazy loading technologies. The native lazy attribute could be used, which is supported by all major browsers since 2022.
Since images are magnitudes larger in file size than text (HTML, CSS, Javascript) is, loading the images of a large web page takes a significant amount of the total load time. When your internet connection is good, this is usually not an issue. However, users with limited bandwidth (i.e. on mobile) need to mine their data budget...
A very informative and interesting presentation about browsing performance, looking at efforts Google Chrome takes to increase it.
There is a bunch of interesting pages in Chrome:
With <link rel="preconnect" href="https://the-domain.com">
in an HTML head, you give the browser an early hint that it will need to access the mentioned domain. By setting up the connection in advance, page load performance gets im...
Rails includes milliseconds in Time
/ DateTime
objects when rendering them as JSON:
JSON.parse(User.last.to_json)['created_at']
#=> "2001-01-01T00:00:00.000+00:00"
In RSpec you might want to use .to_json
instead of .iso8601
to use the build-in eq
matcher:
it 'returns the created at attribute of a user' do
get '/users/1'
expect(JSON.parse(response.body)['created_at']).to eq(Time.parse('2001-01-01').to_json)
end
Otherwise the strings do not match:
DateTime.parse('2001-01-01').to_s (will defa...
vertical-align
is hard. Have you ever wanted to vertically center an icon with text? This usually means "vertically align with capital letters", as visually, a text line goes from baseline up to the capital top. (That's because descenders are far less frequent than ascenders.)
In this card we'll vertically center an icon (or any "blockish" inline element, really) with the capital letters of surrounding text. This works well with our [modern approach to SVG icons](/mak...
RubyMine's terminal doesn't always terminate running processes when you close the whole RubyMine window. The most annoying case is when it leaves a dev server running that blocks port 3000. You can terminate such a dev server with this command:
lsof -t -i :3000 -s TCP:LISTEN | xargs kill -9
It might be worth it to add this to your bash aliases.