namespace :cleanup do
desc "Enqueue a job to purge expired sessions"
task expired_sessions: :environment do
job = ExpiredSessionCleanupJob.perform_later
Rails.logger.info("[cleanup:expired_sessions] enqueued job #{job.job_id}")
end
Rails.application.routes.draw do
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :articles, only: [:index, :show, :create, :update, :destroy]
resources :sessions, only: [:create]
end
# Map - transform elements
[1, 2, 3, 4].map { |n| n * 2 } # => [2, 4, 6, 8]
['alice', 'bob'].map(&:upcase) # => ['ALICE', 'BOB']
users.map(&:email) # => ['alice@example.com', ...]
# Select/Reject - filter elements
class AddSoftDeleteToUsers < ActiveRecord::Migration[7.1]
def change
add_column :users, :deleted_at, :datetime
add_index :users, :deleted_at, where: "deleted_at IS NULL", name: "index_users_on_live"
require 'sinatra'
require 'json'
require_relative 'book'
require_relative 'helpers'
set :books, {
class AddSlugToArticles < ActiveRecord::Migration[7.1]
def change
add_column :articles, :slug, :string
add_index :articles, :slug, unique: true
reversible do |dir|
import { Turbo } from "@hotwired/turbo-rails"
Turbo.StreamActions.redirect = function () {
const url = this.getAttribute("url")
if (!url) return
require 'activerecord-import'
class BulkImportPostsService
BATCH_SIZE = 1000
def initialize(csv_file_path)
<!DOCTYPE html>
<html>
<head>
<title><%= content_for(:title) || "App" %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<div class="bookmarks">
<h1>Saved Bookmarks</h1>
<table>
<tbody id="bookmarks">
<%= render partial: "bookmark", collection: @bookmarks %>
require "securerandom"
class RedisMutex
class LockError < StandardError; end
UNLOCK_SCRIPT = <<~LUA.freeze
require 'uri'
require 'rack/utils'
module PaginationLinks
module_function