How to list updateable dependencies with Bundler and Yarn
Bundler
bundle outdated [--filter-major|--filter-minor|--filter-patch]
Example output for bundle outdated --filter-major
Other examples
A useful flag is --strict as it will only list versions that are allowed by your Gemfile requirements (e.g. does not show rails update to 6 if your Gemfile has the line gem 'rails', '~>5.2').
I also experienced that doing upgrades per group (test, development) are easier to do. Thus --groups might also be helpful.
$ bundle...
Ollama: Strip image data from VCR recorded requests
When testing Ollama vision requests with VCR, the recorded cassettes will contain the full base64-encoded image payloads. A single image can easily be hundreds of kilobytes; a handful of recorded interactions will balloon your repository size significantly.
The VCR configuration below solves two problems:
- It scrubs base64 image data from cassettes before they are written to disk, replacing each image with a placeholder string
- It filters Basic Auth credentials so they are never committed
It also registers a custom request matcher so ...
What edge_rider offers you
edge_rider is Power tools for ActiveRecord relations (scopes). Please note that some of the functions edge_rider provides have native implementations in newer rails versions.
Useful in applications
Relation#traverse_association(*names)
Edge Rider gives your relations a method #traverse_association which returns a new relation by "pivoting" around a named association. You can traverse multiple associations in a single call. E.g. to turn a relation of posts into a relation of all posts o...
makandra cards: A knowledge base on web development, RoR, and DevOps
What is makandra cards?
We are makandra, a team of 60 web developers, DevOps and UI/UX experts from Augsburg, Germany. We have firmly anchored the sharing of knowledge and continuous learning in our company culture. Our makandra cards are our internal best practices and tips for our daily work. They are read worldwide by developers looking for help and tips on web development with Ruby on Rails and DevOps.
15 years ago – in 2009 – we wrote our first card. Since then, over 6000 cards have been created, not o...
Self-expiring URLs with Apache
When delivering non-public uploaded files (images, documents etc), one has to decide whether and how to do authorization. The usual approaches are:
- Using
send_filewith a regular controller. This is secure, but potentially slow, especially for large collections of images. - Using unguessable URLs. This is fast (because Apache can deliver assets without going through Rails), but less secure.
When going with the "unguessable URL" approach, it is possible to somewhat increase security by using expiring URLs. The idea is to encode the expi...
How to iterate over all ActiveRecord models
Sometimes you have a maintenance script where you want to iterate over all ActiveRecord models. Rails provides this out of the box:
# script/maintenance_task.rb
# Load all models eagerly, otherwise you might only get a subset
Rails.application.eager_load!
ApplicationRecord.descendants.select(&:table_exists?).each do |model|
# ...
end
Caution
If you iterate over individual records, please provide a progress indicator: See [https://makandracards.com/makandra/625369-upload-run-scripts-production](https://makandracards.com/...
RSpec: How to write isolated specs with cookies
Background
Rails offers several methods to manage three types of different cookies along with a session storage for cookies. These are normal, signed and encrypted cookies.
By following the happy path of testing a web application, that is only the main use-case is tested as a integration test and the rest as isolated (more unit ...
Devise: Invalidating all sessions for a user
Background information about session storage in Rails
Rails has a default mechanism to store the session in the CookieStore. This is a cookie which holds the entire user session hash in the browser. This cookie is serialized, encoded with base64, and signed.
How Devise handles authentication
Devise uses this CookieStore. To track a users session, a salt is stored in the session ...
Ruby: How to determine the absolute path relative to a file
If you want to get the path of a file relative to another, you can use the expand_path method with either the constant __FILE__ or the method __dir__. Read this card for more information about __FILE__ and __dir__.
Example
Structure:
.
├── bin
│ ├── format_changelog
├── CHANGELOG.md
bin/format_changelog:
#!/usr/bin/env ruby
changelog_path = ? # How to get the path to ../CHANGELOG.md independent of the working dir of the caller
changelog = File.read(changelog_path)
# ... further actions...
Ruby: How to make your ruby library configurable
You might know a few examples, where you configure some library via a block. One example is the Rails configuration:
Rails.application.configure do |config|
config.enable_reloading = false
end
This card describes a simple example on how to make your ruby library configurable.
Example
module FooClient
class Client
class_attribute :config
def self.configure
self.config ||= Configuration.new
yield(config)
end
def test
uri = URI.parse(FooClient::Client.config.endpoint)
Net:...
Configuring Webpacker deployments with Capistrano
When deploying a Rails application that is using Webpacker and Capistrano, there are a few configuration tweaks that optimize the experience.
Using capistrano-rails
capistrano-rails is a Gem that adds Rails specifics to Capistrano, i.e. support for Bundler, assets, and migrations. While it is designed for Asset Pipeline (Sprockets) assets, it can easily be configured for Webpacker. This brings these features to the Webpacker world:
- Automatic removal of expired assets
- Manifest backups
An introduction to Hybrid search
Hybrid search runs a vector query and a keyword query in parallel against the same documents and merges the two ranked search results. Reach for it once either approach alone reaches its limit.
Vector search
Vector search converts documents and queries into embeddings (numeric vectors that place semantically similar text close together) and retrieves the closest matches with a k-Nearest-Neighbors (kNN) lookup. It is strong on synonyms, paraphrasing, and multilingual matches, where the user's wording differs from the document's. It's wea...
You don't need a vector database to build a RAG system
RAG is often equated with vector databases, embeddings, and semantic search. But RAG ("Retrieval-Augmented Generation") really is just 'put relevant data in the prompt' — the retrieval mechanism is up to you. If your app already has any working search functionality, you can build a useful RAG pipeline with it. Semantic search can still be included later on, if really needed.
The pipeline below is sketched for a chat-style "answer my question" flow, but the same shape works for any other RAG systems - only the framing of input and output cha...
Don't use log level :debug in your production environments
Catch phrase
You don't want sensitive user data in your logs.
Background
Rails per default filters sensitive data like passwords and tokens and writes [FILTERED] to the logs. The code which is responsible for enabling that usually lives in filter_parameter_logging.rb (Rails.application.config.filter_parameters). Here is an example of a filtered log entry:
Unfiltered:
`User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."token" = $1 LIMIT $2 [["token", "secret-token"], ["LIMIT", 1]]`
After the filter is appl...
Use Time.current / Date.current / DateTime.current on projects that have a time zone
Basically, you now need to know if your project uses a "real" time zone or :local, and if config.active_record.time_zone_aware_attributes is set to false or not.
-
With time zones configured, always use
.currentforTime,Date, andDateTime.ActiveRecord attributes will be time-zoned, and
.currentvalues will be converted properly when written to the database.
Do not useTime.nowand friends. Timezone-less objects will not be converted properly when written to the database. -
With no/local time zone use
Time.now, `...
RSpec: Where to put custom matchers and other support code
Custom matchers are a useful RSpec feature which you can use to DRY up repetitive expectations in your specs. Unfortunately the default directory structure generated by rspec-rails has no obvious place to put custom matchers or other support code.
I recommend storing them like this:
spec/support/database_cleaner.rb
spec/support/devise.rb
spec/support/factory_bot.rb
spec/support/vcr.rb
spec/support/matchers/be_allowed_access.rb
s...
JavaScript without jQuery
This is a 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?
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 o...
How to discard ActiveRecord's association cache
You know that ActiveRecord caches associations so they are not loaded twice for the same object. You also know that you can reload an association to make Rails load its data from the database again.
user.posts.reload
# discards cache and reloads and returns user.posts right away
# => [...]
If you want to discard the cache but not query the database (only the next time the association is accessed), you can use reset:
user.posts.reset
# discards cache, but does not load anything yet
user.posts
# SQL query happens to ...
ActiveRecord: validate_uniqueness_of is case sensitive by default
By default, Rails' validates_uniqueness_of does not consider "username" and "USERNAME" to be a collision. If you use MySQL this will lead to issues, since string comparisons are case-insensitive in MySQL.
(If you use PostgreSQL, read this instead.)
Say you have a user model
class User < ActiveRecord::Base
validates_uniqueness_of :name
end
with a unique index in the database.
If you try to create the users "user" and "USER", this will not trigger a validation error, but may fail with an SQL error due ...
Jasmine: Fixing common errors during initialization
Due to the way we setup Jasmine tests in our projects, you may run into various errors when Jasmine boots.
Setting jasmineRequire on undefined
Jasmine 4 may fail with an error like this:
Uncaught TypeError: Cannot set properties of undefined (setting 'jasmineRequire')
This is due to issues in Jasmine's [environment detection](https://github.com/jasmine/jasmine/blob/502cb24bb89212917a3c943b593fd918ffc481cb/lib/jasmine-core/...
Ruby: Referencing global variables with the built-in English library
tl;dr
Don't forget
require 'English'if you use a named global such as$LAST_MATCH_INFO. Otherwise this could result in an annoying bug.
With Ruby's build-in library English you can reference global variables with an english name. This makes you code easier to read and is also suggested by Rubocop's Style/GlobalVars cop.
Example before:
if 'foo' =~ /foo/
puts $~[1] # => foo
end
Example af...
The Ruby Object Model
In Ruby (almost) everything is an Object. While this enables a lot of powerful features, this concept might be confusing for developers who have been programming in more static languages, such as Java or C#. This card should help understanding the basic concepts of Ruby's object model and how things behave.
Usage of objects in Ruby
When working with objects in Ruby, you might think of a "container" that holds metadata, variables and methods. Metadata describes stuff like the object's class or its object_id whi...
How to eager load a single directory with Zeitwerk
Zeitwerk is the new autoloader of Rails. It is mandatory starting with Rails 7.0.
Sometimes, a model needs to know all its descendants. They might be organized in a subdirectory:
# Example
app/models/design.rb
app/models/design/light.rb
app/models/design/dark.rb
...
Now imagine that some external code needs to iterate all design subclasses.
To eager load all designs, use this line:
Rails.autoloaders.main.eager_load_dir(Rails.root.join 'app/models/design')
Make sure that app/models/design.rb is not required manually ...
Beware when using ActiveSupport time and date calculation methods
The pitfall
Rails Active Support provides some helpful methods for calculating times and dates, like Duration#ago or Duration#from_now. But beware when using those, because they wont give you Dates or Times but ActiveSupport::TimeWithZone instances. As the class name hints, you now have to be awa...