Haml Whitespace Preservation (or: Fixing Textarea Indentation in Haml)
Haml renders HTML with indentation reflecting the nesting level of elements. When it comes to white-space preserving content, this may become a problem: the content will be rendered including the HTML indentation.
Problematic: Preserved Indentation
.nest
%span Reference
%pre
= content
<div class="nest">
<span>Reference</span>
<pre>
Hello
World
</pre>
</div>
Better: Without Extra Indentation
Render with tilde ~ instead of equal...
CarrierWave: How to remove GIF animation
When accepting GIF images, you will also accept animated GIFs. Resizing them can be a time-consuming task and will block a Rails worker until the image is processed.
Save yourself that trouble, and simply tell ImageMagick to drop any frames but the first one.
Add the following to your uploader class:
process :remove_animation
private
def remove_animation
if content_type == 'image/gif'
manipulate! { |image| image.collapse! }
end
end
You may also define that process for specific versions only (e.g. only for thum...
Fix for mysql2 error "Incorrect MySQL client library version! This gem was compiled for x.x.x but the client library is y.y.y."
This should be fixed in the latest LTS-branches of our mysql2 fork, 0.2.x-lts and 0.3.x-lts.
Use
gem 'mysql2', git: 'https://github.com/makandra/mysql2', branch: '0.2.x-lts' # for Rails 2.x
gem 'mysql2', git: 'https://github.com/makandra/mysql2', branch: '0.3.x-lts' # for Rails 3.x
in your Gemfile, and do a
bundle update mysql2
Background
mysql2 used to check that the client library used at runtime actually matches the one it was compiled against. However, at least on Ubunt...
ActiveRecord: Query Attributes
tl;dr
You can useattribute?as shorthanded version ofattribute.present?, except for numeric attributes and associations.
Technical Details
attribute? is generated for all attributes and not only for boolean attributes.
These methods are using #query_attribute under the hood. For more details you can see ActiveRecord::AttributeMethods::Query.
In most circumstances query_attribute is working like attribute.present?. If your attribute is responding to :zero? then you have to be aware that `query_attri...
Installing old versions of mysql2 on Ubuntu 20.04+
On some of our older projects, we use the mysql2 gem. Unfortunately, versions 0.2.x (required for Rails 2.3) and versions 0.3.x (required for Rails 3.2) can no longer be installed on Ubuntu 20.04. Trying this either leads to errors when compiling the native extension, or a segfaults when using it.
For Rails 4.2, mysql2 version 0.4.10 seems to work okay. If you still have issues, upgrade to 0.5.x, which should be compatible.
To install it, you have to switch the mysql2 gem to our fork. In your Gemfile, ...
How to enable SSL in development with Passenger standalone
Here is how to start your Rails application to accept both HTTP and HTTPS in development.
-
gem install passenger -
Create a self-signed SSL certificate. Store the generated files in config/passenger-standalone-ssl.
-
Create a Passengerfile.json at the project root with this content (or save the attached file):
{ "ssl": true, "ssl_port": 3001, "ssl_certificate": "config/passenger-standalone-ssl/server.crt",...
Bash: How to grep logs for a pattern and expand it to the full request
Example
I, [2024-01-21T06:22:17.484221 #2698200] INFO -- : [4cdad7a4-8617-4bc9-84e9-c40364eea2e4] test
I, [2024-01-21T06:22:17.484221 #2698200] INFO -- : [4cdad7a4-8617-4bc9-84e9-c40364eea2e4] more
I, [2024-01-21T06:22:17.484221 #2698200] INFO -- : [6e047fb3-05df-4df7-808e-efa9fcd05f87] test
I, [2024-01-21T06:22:17.484221 #2698200] INFO -- : [6e047fb3-05df-4df7-808e-efa9fcd05f87] more
I, [2024-01-21T06:22:17.484221 #2698200] INFO -- : [53a240c1-489e-4936-bbeb-d6f77284cf38] nope
I, [2024-01-21T06:22:17.484221 #2698200] INFO -- ...
When Date.today and Date.tomorrow return the same day...
... you probably have a time zone issue.
When you get
Timecop.travel(Date.parse("2011-11-11 00:00") do
Time.current # Thu, 10 Nov 2011 23:00:01 UTC +00:00
Time.now # Fri Nov 11 00:00:02 +0100 2011
Date.today # Fri, 11 Nov 2011
Date.tomorrow # Fri, 11 Nov 2011
end
you probably haven't defined a zime zone yet.
So might fix this by adding the following lines to your application.rb:
class Application < Rails::Application
config.time_zone = 'Berlin' # or whatever your time zone
end
It se...
Specify Gemfile for bundle
Bundler allows you to specify the name of the Gemfile you want to bundle with the BUNDLE_GEMFILE environment variable.
BUNDLE_GEMFILE=Gemfile.rails.7.2 bundle
By default, bundler will look for a file called Gemfile in your project, but there may be cases where you want to have multiple Gemfiles in your project, which cannot all be named Gemfile. Let's say for example, you maintain a gem and want to run automated tests against multiple rails versions. When you need to bundle one of your secondary Gemfiles, the solution above ...
Ruby: Debugging a method's source location and code
Access the Method object
Dead simple: Get the method object and ask for its owner:
"foo".method(:upcase)
# => #<Method: String#upcase>
"foo".method(:upcase).owner
# => String
Look up a method's source location
Ruby 1.9 adds a method Method#source_location that returns file and line number where that method is defined.
class Example; def method() end; end
# => nil
Example.new.method(:method).source_location
# => ["(irb)", 11]
"foo".method(:upcase).source_location
# => nil # String#upcase is a native method...
ActiveStorage: How to add a new preprocessed named version
Given there is a user with an attachable avatar:
class User < ApplicationRecord
has_one_attached :avatar
end
If you want to add a preprocessed version follow these steps:
- Add the named version and deploy
class User < ApplicationRecord
has_one_attached :avatar do |attachable|
attachable.variant :preview, resize_to_fit: [177, 177 * 9 / 16], preprocessed: true
end
end
- Preprocess this version for all existing records `bundle exec rails runner 'User.find_each { |user| user.avatar.variant(:preview).proc...
Organizing custom Date(Time) formats
Large Rails projects tend to define multiple custom ways to format Dates or DateTimes. 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...
Writing strings as Carrierwave uploads
When you have string contents (e.g. a generated binary stream, or data from a remote source) that you want to store as a file using Carrierwave, here is a simple solution.
While you could write your string to a file and pass that file to Carrierwave, why even bother? You already have your string (or stream).
However, a plain StringIO object will not work for Carrierwave's ActiveRecord integration:
>> Attachment.create!(file: StringIO.new(contents))
TypeError: no implicit conversion of nil into String
This is because Carrierwav...
Cast an ActiveRecord to a subclass or superclass
Note: ActiveRecord::Base#becomes has a lot of quirks and inconsistent behavior. You probably want to use ActiveType.cast instead.
ActiveRecord models have with a method becomes(klass) which you can use to cast the record into an instance of its subclasses or superclass. This is useful because some parts of Rails reflect on the class of an instance, e....
OpenAI TTS: How to generate audio samples with more than 4096 characters
OpenAI is currently limiting the Audio generating API endpoint to text bodies with a maximum of 4096 characters.
You can work around that limit by splitting the text into smaller fragments and stitch together the resulting mp3 files with a CLI tool like mp3wrap or ffmpeg.
Example Ruby Implementation
Usage
input_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi eget mauris pharetra et ultrices neque."
output_mp3_path = Rails.root.join("tts/ipsum...
Automatically build sprites with Lemonade
How it works
See the lemonade descriptions.
Unfortunately, the gem has a few problems:
- it does not work with Sass2
- it always generates all sprites when the sass file changes, which is too slow for big projects
- it expects a folder structure quite different to our usual
All these problems are solved for us, in our own lemonade fork. This fork has since been merged to the original gem, maybe we can use t...
Transfer records to restore database entries (with Marshal)
If you ever need to restore exact records from one database to another, Marshal might come in handy.
Marshal.dump is part of the ruby core and available in all ruby versions without the need to install anything. This serializes complete ruby objects including id, object_id and all internal state.
Marshal.load deserializes a string to an object. A deserialized object cannot be saved to database directly as the the dumped object was not marked dirty, thus rails does not see the need to save it, even if the object is not present in...
Manually requiring your application's models will lead to trouble
In a nutshell:
If you require your Rails models manually, pay attention to the path you use. Unless you have to, don't do it at all.
Background
Consider these classes:
# app/models/user.rb
class User < ActiveRecord::Base
validate :magic
def magic
errors.add_to_base('failed') if bad_things?
end
end
^
# app/models/foo.rb
require 'user'
class Foo
# something happens here
end
Now, when your environment is booted, Rails will automatically load your models, like User...
How to fix: Session hash does not get updated when using "merge!"
tl;dr: Do not use merge! for session hashes. Use update instead.
Outline
Let's assume you're modifying the Rails session. For simplicity, let's also assume your session is empty when you start (same effect when there is data):
# In our example, we're in a Rack middleware
request = Rack::Request.new(env)
request.session.merge! :hello => 'Universe'
request.session
=> {}
Even worse: When you inspect your request.session like above (e.g. in a debugger shell, o...
Do not forget mailer previews
When changing code in mailers, updating the corresponding mailer preview can be forgotten very easily.
Mailer previews can be tested like other code as well and I sometimes add the following tests to test suites:
# Make sure to require the previews
Dir[Rails.root.join('spec/mailers/previews/*.rb')].each { |file| require(file) }
ActionMailer::Preview.all.index_with(&:emails).each do |preview, mails|
mails.each do |mail|
describe preview do
specify "##{mail} works" do
expect { preview.call(mail...
Some tips for upgrading Bootstrap from 3 to 4
Recently I made an upgrade from Bootstrap 3 to Bootstrap 4 in a bigger project. Here are some tips how to plan and perform such an upgrade. The effort will scale with the size of the project and its structure. If your stylesheets already follow strict rules, it may take less time to adapt them to the new version.
Preparation
There are several gems and libraries that works well with bootstrap or provide at least stylesheets/plugins to easily integrate the bootstrap theme. But very often they only work with specific version or are no long...
RSpec: How to turn off partial double verification temporarily
While verifying doubles in RSpec is a good default, it is limited in the amount of methods it actually is able to verify.
The background is that RSpec can't verify dynamically defined methods, which is a known issue for the usage of helper_method and also the reason why [RSpec >= 3.6](http://rspec.info/blog/2017/05/rspec-3-6-has-been-rel...
8 steps for fixing other people's code
Guide how to make fixes in other people's GitHub repositories. It's basically "Open Source Development 101".
Way back in mid-2007, when Rails 1.2 was the new hotness and GitHub was still a year away from crawling out of the primordial internet soup, prolific open source contributor Dr Nic wrote an article titled “8 steps for fixing other people’s code”. (...)
Here in the fantastical future world of 2012, while we still don’t have hoverboards or household nuclear fusion, we do have some great tools that make fixing other people’s code...
How to make Webpacker compile once for parallel tests, and only if necessary
Webpack is the future. We're using it in our latest Rails applications.
For tests, we want to compile assets like for production.
For parallel tests, we want to avoid 8 workers compiling the same files at the same time.
When assets did not change, we do not want to spend time compiling them.
Here is our solution for all that.
Its concept should work for all test suites.
Copy the following to config/initializers/webpacker_compile_once.rb. It will patch Webpacker, but only for the test environment:
# Avoid hardcoded asset host...