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",
...
Webpack: How to avoid multiple versions of jQuery
To avoid multiple versions of a package, you can manually maintain a resolutions
section in your package.json
. We recommend you to do this for packages like jQuery. Otherwise the jQuery library attached to window
might not include the functions of your packages that depend on jQuery.
Note: This is only an issue in case you want to use a package functionality from window
e.g. $(...).datepicker()
from your dev console or any other javascript within the application.
Background
By default yarn will create a folder node_modules
...
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...
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....
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...
Using Passenger Standalone for development
For our production servers we use Passenger as a Ruby application server. While it is possible to use Passenger for development as an Apache module, the installation process is not for the faint of heart.
Luckily Passenger also comes as a standalone binary which requires zero configuration.
You can Passenger Standalone as a replacement for Webrick or Thin if you'd like to:
- Use SSL certificates locally
- Get performance behavior that is closer to ...
Local development with SSL and Puma
Sometimes the need arises for SSL in local development. We have guides for different webservers, this one is for puma.
-
make sure mkcert is installed
-
create an SSL certificate for localhost with mkcert:
$ mkcert-v1.4.4-linux-amd64 localhost
Created a new local CA 💥
...
- use the certificate in the Puma config
config/puma.rb
:
localhost_key = "#{File.join('localhos...
Capistrano: exclude custom bundle groups for production deploy
Capistrano is by default configured to exclude the gems of the groups development
and test
when deploying to the stages production
and staging
. Whenever you create custom groups in your Gemfile
, make sure to exclude these, if they should not be deployed to the servers. The gems of these groups might not be loaded by rails, however, the deployment process will take longer as the gems will be downloaded and installed to the server.
e.g. to exclude the groups cucumber
and deploy
, add the following to `config/deploy/production.rb...
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...
How to send HTTP requests using cURL
-
Reading a URL via GET:
curl http://example.com/
-
Defining any HTTP method (like POST or PUT):
curl http://example.com/users/1 -XPUT
-
Sending data with a request:
curl http://example.com/users -d"first_name=Bruce&last_name=Wayne"
If you use
-d
and do not set an HTTP request method it automatically defaults to POST. -
Performing basic authentication:
curl http://user:password@example.com/users/1
-
All together now:
curl http://user:password@example.com/users/1 -XPUT -d"screen_name=batman"
...
Choosing the right gems for your project
Adding a gem means you take over the liability towards the external code.
Checklist
Based on "To gem, or not to gem":
- Gem is really needed (prefer writing your own code for simple requirements without many edge cases)
- Gem is tested well (coverage and quality)
- Gem has a good code quality
- Gem's licence fits to the project requirement
- Try to avoid gems that do much more than your requireme...
Webpacker: Configuring browser compatibility
Webpacker uses Babel and Webpack to transpile modern JavaScript down to EcmaScript 5. Depending on what browser a project needs to support, the final Webpack output needs to be different. E.g. when we need to support IE11 we can rely on fewer JavaScript features. Hence our output will be more verbose than when we only need support modern browsers.
Rails 5.1+ projects often use Webpacker to preconfigure the Webpack pipeline for us. The default configuration works something like this:
- Webpack checks w...
Integrating or upgrading makandra-rubocop
Introduction
Most of the time it is a tedious task to apply a code style guide to an existing code base as there are likely to be a lot of conflicts. At makandra we are using makandra-rubocop to have code style checks. Here is some advice on how to add makandra-rubocop efficiently.
Note
RubyMine by default has a Rubocop inspection with rules that we don't always agree with. We recommend replacing this with makandra-rubocop or disabling the inspection.
...
Five years of "Today I Learned" from Josh Branchaud
The linked GitHub repository is a bit like our "dev" cards deck, but groomed from a single person (Josh Branchaud). It includes an extensive list of over 900 TILs on many topics that might be interesting for most of us. (e.g. Ruby, Rails, Git, Unix..)
Ruby
Here is an excerpt of all the Ruby TILs that were new to me. I encourage you to take your time to skim over the original list as well!
-
Assoc For Hashes
- `Hash#ass...
Geordi 10.0.0 released
10.0.0 2024-03-07
Compatible changes
-
console
command: You can now globally disable the IRB multiline feature by settingirb_flags: --nomultiline
in~/.config/geordi/global.yml
. All configured irb_flags are automatically passed on to the console IRB. -
console
command:Ctrl + C
now properly exits a local Rails console -
rspec
andcucumber
commands: Run specs even if the automatic chromedriver update fails - Improve detection of IRB version
- Add new hints to 'Did you know'
Breaking changes
-
dump
command: Drop...
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...
Using multiple MySQL versions on the same linux machine using docker
We had a card that described how to install multiple mysql versions using mysql-sandbox
. Nowadays with the wide adoption of docker it might be easier to use a MySQL docker image for this purpose.
Create a new mysql instance
docker run --name projectname_db -e MYSQL_ROOT_PASSWORD=secret -p "33008:3306" -d --restart unless-stopped mysql:5.7
The port 33008 is a freely chosen free port on the host machine that will be used to establish a con...
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 ...
Mock the browser time or time zone in Selenium features
In Selenium features the server and client are running in separate processes. Therefore, when mocking time with a tool like Timecop, the browser controlled by Selenium will still see the unmocked system time.
timemachine.js allows you to mock the client's time by monkey-patching into Javascript core classes. We use timemachine.js in combination with the Timecop gem to synchronize the local browser time to the ...
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...
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...
Mailcatcher: An alternative to inaction_mailer
Looks simpler than inaction_mailer:
gem install mailcatcher
mailcatcher
Setup Rails to send mails to 127.0.0.1:1025. Usually you want the following config in config/environments/development.rb
and maybe in test.rb
or cucumber.rb
.
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => 'localhost',
:port => 1025
}
Now you can see sent mails in your browser when opening http://127.0.0.1:1080
Note: In order to s...
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...