Skip to content

Instantly share code, notes, and snippets.

View laserlemon's full-sized avatar

Steve Richert laserlemon

View GitHub Profile
@laserlemon
laserlemon / update_user.rb
Created November 14, 2017 16:28
Updating a record with rollback to original attributes
class UpdateUser
include Interactor
# Receives: user - A User record to update.
# new_attributes - A hash of attributes to be saved to the user.
# Updates: user
# Provides: old_attributes - A hash of only those user attributes that
# changed and their original values.
def call
@laserlemon
laserlemon / introduction.md
Last active February 12, 2021 10:04
Rendering form errors for non-database-backed changesets

Introduction

Disclaimer: I'm a one-day-old Elixir/Phoenix developer.

In Sonny's training yesterday, we used an Ecto.Changeset to handle user registration (a database-backed operation). This worked perfectly for rendering the intial form and re-rendering the form with validation errors.

This is because our Workshop.RegistrationController is calling Repo.Insert which sets the changeset's :action, whether or not the insertion succeeds. Then Phoenix.HTML's form_for function appropriately sets errors on the form so they can be rendered on the page.

The Problem

@laserlemon
laserlemon / ransack.rb
Created June 16, 2016 18:43
Ransack Sort Scopes
require "ransack/visitor"
require "ransack/adapters/active_record/context"
module Ransack
Visitor.class_eval do
def visit_Ransack_Nodes_Sort(object)
# The first half of this conditional is the original implementation in
# Ransack, as of version 1.6.6.
#
# The second half of the conditional kicks in when the column name
begin
require "active_record" # 4.2.4
require "ransack" # 1.6.6
require "sqlite3" # 1.3.11
rescue LoadError
warn "⚠️ Install the activerecord, ransack, and sqlite3 gems first."
exit
end
ActiveRecord::Base.establish_connection(
@laserlemon
laserlemon / technical-debit.md
Last active July 23, 2020 09:03
Keeping Track of Technical Debit

Keeping Track of Technical Debt

Don't forget your debt! Developers have a tendency to forget the bad or ugly code they write. In the Real World™, there are times when sacrifices in code quality need to be made in the interest of time. We call it "cowboy coding" and it's a slippery slope that can lead to loads of technical debt.

A big problem is that it's too easy for technical debt to be out of sight and out of mind. There are a few good ways to increase your debt's visibility.

Code Comments

Your first step should be to add code comments where appropriate to document technical debt as it arises. Fight the urge to deny the fact that you're writing less-than-awesome code. Try to include what's wrong with the code in question as well as at least one potential solution.

@laserlemon
laserlemon / place_order.rb
Created April 21, 2015 22:01
Proposed Interactor 4.0 Syntax
class PlaceOrder
include Interactor
# What goes here?
before do
context.user ||= User.find(context.user_id)
end
def call
@laserlemon
laserlemon / finish_optimization.rb
Last active August 29, 2015 14:15
Proposed Interactor v4 API
class FinishOptimization
include Interactor::Organizer
organize CommitImages
organize PushImages,
CreateOrUpdatePullRequest,
MarkAsFinished, if: -> { context.optimized_commit_sha }
end
@laserlemon
laserlemon / keybase.md
Created December 29, 2014 16:38
keybase.md

Keybase proof

I hereby claim:

  • I am laserlemon on github.
  • I am laserlemon (https://keybase.io/laserlemon) on keybase.
  • I have a public key whose fingerprint is CDB6 894C 1DA5 35AB 8425 DD90 C650 CD1B 7189 C7DF

To claim this, I am signing this object:

@laserlemon
laserlemon / cli.rb
Created May 23, 2014 23:21
Thor is hard.
# my_gem/cli.rb
require "thor"
require "my_gem/cli/foo_bar"
require "my_gem/cli/foo_baz"
require "my_gem/cli/install"
module MyGem
class CLI < Thor
@laserlemon
laserlemon / interactor.md
Created May 2, 2014 11:37
Old Interactor Documentation

What is an Interactor?

An interactor is a simple, single-purpose object.

Interactors are used to encapsulate your application's business logic. Each interactor represents one thing that your application does.

Context

An interactor is given a context. The context contains everything the interactor needs to do its work.