Rails provides abstractions for signing and encrypting data. If a Rails app needs to authenticate some data, (let’s say, to generate a magic link sent by email) Rails.application.message_verifier provides a convenient solution. This application-level interface was added in Rails 4.1, so it is already a mature Rails feature.
The examples below wrap an opaque login token that is associated with a user in the payload.
login_token = SecureRandom.urlsafe_base64(32) # => "2LfzCleMQtoNLYij4Ah_y5M80LwXbj3yPqeojsVvRBY" verifier = Rails.application.message_verifier(:magic_link) signed_message = verifier.generate( { token: login_token }, expires_in: 30.minutes, purpose: :login ) # => "eyJfcmFpbHMiOnsiZGF0YSI6eyJ0b2tlbiI6IjJMZnpDbGVNUXRvTkxZaWo0QWhfeTVNODBMd1hiajN5UHFlb2pzVnZSQlkifSwiZXhwIjoiMjAyNi0wNy0yNlQxMjowODozNS42ODBaIiwicHVyIjoibG9naW4ifX0=--3f9948547736a1650e31c35c6c7b38f518785380" payload = verifier.verify(signed_message, purpose: :login) # => {"token" => "2LfzCleMQtoNLYij4Ah_y5M80LwXbj3yPqeojsVvRBY"} Rails.application.message_verifier is a turnkey solution for signing and verifying application data with a MAC-based mechanism. It supports expiration and purpose scoping outside of the data itself. The secret is derived from secret_key_base.
Read more →
Today I learned that when doing database-migration on Rails, change_table :#{table_name}, bulk: true let us combine multiple alter-table statements and it could reduce the cost of the whole alteration. That is, instead of executing multiple alter-table separately,
def change add_column :users, :first_name, :string, null: false add_column :users, :last_name, :string, null: false end we can run a single alter-table statement by change_table like as follows.
def change change_table :users, bulk: true do |t| t.column :first_name, :string, null: false t.column :last_name, :string, null: false end end However, why should we do that? What are the differences between them?
Read more →
Today I learned that Rails 6.1.3 does not have methods that raise exceptions when more than one record was found. However, in future versions, we could use ActiveRecord::FinderMethods#sole for that purpose. It seems Enumerable#sole is also going to be introduced.
Sometimes I need to make sure there is one and only one record that matches a condition without using a unique-index, for example, when I cannot add that constraint to the database.
Read more →
Today I learned/remembered that to format a number with a delimiter, we can use ActiveSupport::NumericWithFormat#to_s(:delimited).
require 'active_support' require 'active_support/core_ext' 123456789.to_s(:delimited) # => "123,456,789" Not only that, but this method also provides other formats and takes options to tweak its behavior.
123456789.to_s(:delimited, delimiter: '-') # => "123-456-789" 123456789.to_s(:currency, precision: 3) # => "$123,456,789.000" 123456789.to_s(:human_size) # => "118 MB" 123456789.to_s(:human) # => "123 Million" Originally, when I need to format a number to a delimited number, I would try to use number_to_delimited provided by ActiveSupport::NumberHelper. But to_s is handy when we have to do that where the helper is not reachable by default, such as in a serializer class for ActiveModel Serializer. Calling this method passing a format is the same as calling ActiveSupport::NumberHelper.number_to_#{format}.
Read more →
I’m developing a small application which is built on Ruby on Rails, React and Relay. Since the project is based on my personal hobby and just a prototype, I preferred to write application codes rather than to write tests at first. However, as the application grows larger, I had to test the application manually every time when I make changes to make sure it doesn’t break other features. The lack of tests made development speed slower. So I decided to write automated tests.
Read more →