3572 cards
View

Carrierwave: always limit images to a reasonable size

Today's cameras create huge images, some beyond 50MB. Unless you need to offer this large files, you should always shrink uploaded files to a reasonable resolution.

class ImageUploader < CarrierWave::Uploader::Base
  
  process resize_to_limit: [3000, 3000]
  
  # ...

end

Carrierwave processing facts

  1. Class-level process definitions are only applied to the original file
  2. Versions are generated based on the processed original file
  3. Callbacks (before/after) are applied to original file and each version by itself
  4. Under the hood, a version is an instance of the uploader class that has no versions
  5. Version uploader and original uploader can be distinguished by checking #version_name: version uploaders return the version name, whereas the original uploader instance returns nil
  6. Version instances do not have a re…
Repeats

Carrierwave reminder: always call model.save! after uploader.recreate_versions!

If your Carrierwave uploader dynamically generates the filename (e.g. by incorporating a user's name), you must call model.save! after recreating versions, because uploader.recreate_versions! does not update the model with the stored filename.

Repeats

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:

```text
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/

Linked contentRepeats

How to explain SQL statements via ActiveRecord

ActiveRecord offers an explain method similar to using EXPLAIN SQL statements on the database.

However, this approach will explain all queries for the given scope which may include joins or includes.

Output will resemble your database's EXPLAIN style. For example, it looks like this on MySQL:

User.where(id: 1).includes(:articles).explain

```
EXPLAIN for: SELECT users.* FROM users  WHERE users.id = 1
+—-+————-+——-+——-+—————+
| id | select_type | table | type  | possible_keys |
+—-+—–…

Linked contentAuto-destruct in 56 days

Consul 1.0 released

We've released consul 1.0.0, which is mostly identical to 0.14.1.

The support for the following methods was dropped:

Power.for_record(record)            # instead use Power.for_model(record.class)
Power#for_record(record)            # instead use Power#for_model(record.class)
Power#name_for_record(record)       # instead use Power#name_for_model(record.class)
Linked contentAuto-destruct in 53 days

ActiveType 1.0 released

We have released ActiveType 1.0, which is identical to 0.7.5.

Repeats

How to iterate over an Enumerable, returning the first truthy result of a block ("map-find")

Ruby has Enumerable.find(&block), which returns the first item in the collection for which the block evaluates to true.

first_post_with_image = posts.find do |post|
  post.image
end

However, sometimes it's not the item you're interested in, but some value depening on it – e.g. the value the block evaluated to. You could first map the collection and then take the first truthy value, but this way you need to process the whole collection twice:

first_image_url = posts.map(&:image).find(&:present?).url

If the mapping …

Repeats

Simple database lock for MySQL

Note: For PostgreSQL you should use an alternative that doesn't require a database table. For MySQL we still recommend the solution in this card.


If you need to synchronize multiple rails processes, you need some shared resource that can be used as a mutex. One option is to simply use your existing (MySQL) database.

The attached code provides a database-based mutex for MySQL. You use it by simply calling

Lock....
Linked contentRepeats

Copy to clipboard without flash (clipboard.js)

We used zeroclipboard.js in some of our projects but now we switched to clipboard.js because it does not rely on flash. Flash support of the major browsers has ended.

Some more advantages of clipboard.js:

  • it consists only of a single javascript file, so it does not trigger additional requests with rails
  • it automagically provides user feedback by selecting the text it has copied
  • it provides callbacks for success and error which make it easier to add custom behaviour after copying to the clipboar…
Linked contentAuto-destruct in 50 days

Updated: Rails routes: Extracting collection actions into their own controllers

In modern Rails versions we can define nested resources in a collection { ... } block to namespace them into an existing resource:

resources :projects, only: :show do
  collection do
    resource :report, only: :show, controller: 'projects/report'
  end
end

This generates the following routes:

GET /projects/:id        => ProjectsController#show
GET /projects/report     => Projects::ReportsController#show

Note how /projects/report does not take a :project_id.

Thanks Jakob for the hint.

Linked content

Cheat Sheet for the modern DOM API

See the attached link for a useful overview of modern (and classic) DOM API methods, like matches, contains, append, cssText, etc.

You will still need to look up some documentation, e.g. on how to modify a ClassList, but it's still better than browsing interfaces and superclasses of Element on MDN without knowing what to look for.

When coming from jQuery, also see the card on JavaScript without jQuery.

JavaScript without jQuery (presentation from 2019-01-21)

Summary

  • We want to move away from jQuery in future projects
  • Motivations are performance, bundle size and general trends for the web platform.
  • The native DOM API is much nicer than it used to be, and we can polyfill the missing pieces
  • Unpoly 0.60.0 works with or without jQuery

Is jQuery slow?

```text
From: Sven
To: unpoly@googlegroups.com
Subject: performance on smartphones and tablets

Hello

I just used your framework in one project and must say,
I am really pleased with it – but only on a desktop computer.

Have you benchm…

Linked contentRepeats

Why Using the Greedy .* in Regular Expressions Is Almost Never What You Actually Want – Marius Schulz

Explains the difference betwen .* and .*?, and why the latter can lead to faster patterns.

Linked contentRepeats

Things you probably didn’t know you could do with Chrome’s Developer Console

Collection of useful tools in the Chrome JavaScript console.

Make the whole page editable
This is not special to Chrome, but still a clever thing:
document.body.contentEditable=true 
Taking time
You can easily measure the time on the console with named timers:
console.time('myTime'); // Start timer
console.timeEnd('myTime'); // End timer and print the time
Reference previously inspected elements (from the Elements panel)
Variables $0, $1, … $n reference the nth-last inspected Element. $0 is the…
Linked contentRepeats

Make your Rails console (and irb) output better readable

Pour color on your Rails console with awesome_print. Turn confusing long strings into formatted output. Have objects and classes laid out clearly whenever you need it.

Put gem 'awesome_print', :group => :development into your Gemfile. Now on the Rails console you have the command ap that will give you a colored, formatted output of whatever you pass it. See the example output of the User class below.

For customization visit the repository on Github.

![awesome_print.png](https://makan…

How to install bundler for Ruby < 2.3

Bundler 2 requires at least Ruby 2.3.0 and RubyGems 2.5.0. You might get the following error when you try to install bundler for Ruby < 2.3:

ERROR:  Error installing bundler:
	bundler requires Ruby version >= 2.3.0.

To fix this error upgrade your project's ruby version or install the last supported version of Bundler for Ruby < 2.3:

gem install bundler -v=1.17.3

You will also see an error if your [RubyGems version is < 2.5.0](https://makandracards.com/makandra/61824-rubygems-can-t-find-bundle-executable-although-b…

Repeats

AngularJS 1: How to keep "ng-hidden" elements from flickering on page load

When you have an element you want to hide, you can add a ng-show='isOpen' attribute to that element. When you set isOpen to false on the scope, the element will be hidden.

However, when you load the page, the element is usually rendered by the browser before Angular has loaded and had a chance to hide it.

Generic fix (prefer)

The ng-cloak directive was designed for exactly this purpose. Add a ng-cloak attribute or class (and more, see the link) to any element you want to …

This website uses cookies to improve usability and analyze traffic.
Accept or learn more