Threads for calebhearth

  1. 2

    I’ve been using this pattern of naming and structuring service objects over the past ~year. It’s initially been greeted with some uncertainty and skepticism when I introduce it to new developers, but it tends to grow on folks as they give it a shot and look at how it’s already been used.

    I wrote this up partially to codify some of how I’ve been explaining it to folks ad-hoc, but also to share with the broader community and get input on this way of extracting processes in Ruby/Rails projects.

    1. 3

      Good starting point, but I would strongly advise reducing your dependency on constants, and using the initialization for dependency-injection, so that you can treat these like first-class functions.

      The Dry-rb family of gems has been supporting this style for a while.

      • dry-monads is an ideal Result type for these objects to use, so that you can trivially compose them
      • dry-container gives you a threadsafe object to register keys. This is used to encapsulate the build process of instantiating a class with optional memoization
      • dry-auto_inject builds on that to give you a DSL for injecting container keys during initialization
      • dry-system builds on that to give you automatic, convention-based component registration
      • dry-rails provides some nice integration for Rails controllers
      • Hanami Has been rewritten from the ground up to follow these principles

      So your controller example might look more like

      # app/operations/make_purchase.rb
      class MakePurchase < Operation
        include Deps[:create_order, :process_payment, :fulfill_order]
        def call(customer:, product:)
          order = yield create_order.(customer:, product:)
          result = yield process_payment.(payment_method: customer.payment_method, amount: order.cost)
          if result.declined?
            Failure[:declined, result]

      Every time the Operation yields, it is checking the monad type. A Failure will immediately halt execution and return the failure result, while a Success is unwrapped for continued processing.

      # app/controllers/purchases_controller.rb
      class PurchasesController < ApplicationController
        schema :create do
        before_action do
          if safe_params&.failure?
            render(:error, errors: safe_params.errors.to_h)
        def create
          product = Product.find(safe_params[:product_id])
          case resolve(:make_purchase).(customer: current_user, product:)
          in Success(order)
            redirect_to order
          in Failure[:declined, result]
            render :declined, result
          in Failure(MyApp::Error => err)
            render :server_error, err

      You get the Operation by name using resolve. This means that 1. your controller doesn’t need knowledge of how to instantiate MakePurchase, and 2. the specific constant identity is irrelevant. Want to refactor the process in a different Operation? Replace the automatic container key with a manual registration that uses a feature flag to choose the implementation.

      MyApp::Container.register(:make_purchase) do
        if Feature?(:new_purchase)



      This also makes testing really easy. Need to stub out the coordinating dependencies? Inject a proc in your unit test.

      subject :make_purchase do
          create_order: ->(**) { Success(fake_product) },
          process_payment: ->(**) { Success(, amount:, "USD"))) }

      If your dependency graph is more complicated than this, you can also stub the container keys directly

      let(:process_payment) { Success(, amount:, "USD"))) }
      around :each do |example|
        container.stub(:process_payment, process_payment) { }
    1. 5

      Excited to announce a new gem release that allows Rails apps to accept, verify, and parse Webmentions!

      What are Webmentions? They’re sort of like Pingback, but more concretely they’re a way to let some other website know that your website linked to it.

      I’d love to hear if you do end up trying Mentionable out.

      1. 1

        Looks cool! Makes me miss the plug-n-play nature of Rails gems from my Ruby days. :’)

        Nit: on mobile the main text takes up 100% of the viewport width, so with the margins I have to scroll horizontally and keep the text centered as I read. I’m on Firefox on Android.

        1. 2

          Hmm thanks Coby. I got a similar report from someone else on Android/Firefox.

      1. 4

        “Read Ruby’s Enumerable Docs” is part of the Blogging with AI series.

        From the first post in that series:

        These blog posts were drafted by me, ChatGPT, and edited by Caleb Hearth. The ideas and prompts for the posts were provided by Caleb, and the resulting content and insights were generated through our collaboration. We hope that you enjoy reading these posts and that they inspire you to think about these topics in new and exciting ways. Thank you for joining us on this journey.

        I don’t know if Lobsters has a policy on ChatGPT posts, but maybe it should.

        1. 2

          OP here. It certainly could! This post was started with an idea for a post I’d had kicking around for quite a while. I fed that into ChatGPT and the result was ok, but this is heavily rewritten. I think maybe one paragraph was up to my standard for being published, though a decent number made it in from the initial output with edits.

          I didn’t post the original ChatGPT output but the prompt is available at the bottom and pretty obviously not a direct prompt for this article:

          How would you convince developers to read up on that, with a few examples of naive approaches to problems with each or map being replaced with more appropriate Enumerable methods?

          1. 2

            I’d like to see the original output so I can see what kind of edits you made!

        1. 7

          I found the documentation for this feature to be obscure and opaque. Took me 15 minutes of browsing to find all the necessary steps and, once I realized how difficult it was to implement, I gave up.

          For one, it does not work with the default macOS 12.3 git.

          1. 20

            I found this article quite helpful. You can see the changes to my dotfiles based on this here, in case that helps. In my case I use two computers with different SSH keys, so I also made some changes to support custom Git configurations, but you can skip past that if not needed.

            1. 5

              That blog post is 100x better than the github blog post or its linked documentation.

              1. 2

                Aww, thanks Mike.

                1. 4

                  Thank you, pushed my first verified commit on GitHub today thanks to your easy walkthru.

                  1. 1

                    Love it!

            2. 3

              Seems clear enough to me. Use ssh-agent (if you don’t already; a lot of devs already need it for other reasons). Add two lines of config to tell git that your signing method is SSH and which key to use. Tell GitHub the key too so it can validate. Add -S to some commands or turn on an “always sign” config option.

              But yes, it does require a version of git that’s less than a year old. It’s a new feature.

            1. 2

              Is it ironic that the site is not mobile friendly?

              1. 1

                Sure is. Sorry about that, the overflow has been fixed now.

              1. 2

                The animated GIF reflowing the text was weird. I had no idea this was possible!

                1. 2

                  Yeah it’s trippy. I tweeted another example the other day that used a ninja stick figure with a sword and it really caused the text to jump around.

                  1. 1

                    That is wild

                1. 2

                  I’ve also heard that Wordpress or Medium are better options

                  Respectfully, I feel like this is an apples to oranges comparison. Wordpress at its core is 100% open source, with open source, shareware or commercial themes and extensions to choose from. I know it’s reviled as a security risk, and not being a security person I can’t weigh in on whether or not that’s true.

                  Medium is a 100% closed source commercial offering with positively poisonous commercial content up-sell. I wish technical authors would avoid it like the plague. I didn’t agree with that viewpoint at first, but with all the changes they’ve made in their policies, I am now very firmly in that camp.

                  That said, I certainly don’t disagree that both of these options represent a potential loss of control and opportunity to improve your craft and flex your software construction muscles, so rolling your own in Rails sounds like a commendable plan!

                  I also agree that Rails isn’t necessarily too heavyweight for a blog, because modern Rails stock configuration comes ready to scale to an impressive degree, and that’s not anything to sneeze at! There is definitely a cost of ownership there around all the moving parts, but infrastructure at scale is like that pretty much no matter which framework you choose.

                  1. 2

                    Why not using Plume in place of medium?

                    It is open source, federated and many servers are free.

                    1. 1

                      Plume seems like a nice option but why not a hammer versus a wrench? Tools are personal.

                      1. 2

                        I totally agree. Each personal blog should be that… personal. A custom theme, favorite theme, tone, and pictures (or not). But I can understand people they don’t want to host, manage, secure a public site. Perhaps some don’t want to post in their own name. Medium got popular by its ease to use and its centralization. A clean (impersonal) design. But it is closed source and has all the downside you mention. Plume is a look alike but does not suffer the same.

                        I didn’t mention WordPress, that is customizable at ease. My personal taste shouts that it is an hammer to kill a fly but I have to admit that it is (was?) manageable by most people.

                        Custom tool as the article mention its for the elite. Only a bunch of people can manage to develop their own solution. I’m happy I can. But I know that most cannot.

                        As you said, told are personal but not only by choice.

                        1. 2

                          Oh there’s no doubt that WordPress is several orders of magnitude more than the average blogger needs.

                          I wonder if there are any other engines out there that offer the same ease of use and flexibility without the bulk?

                    2. 1

                      Respectfully, I feel like this is an apples to oranges comparison.

                      Not sure I follow - are you suggesting that I’m comparing Wordpress and Medium? I think I’m comparing my blog to Wordpress and my blog to Medium, but not the two to each other.

                      I agree with your analysis of both options.

                    1. 3

                      Misuse of event tag–this isn’t about a particular event. Maybe practices would be a better fit here.

                      1. 1

                        Yup, probably. Thanks!

                      1. 2

                        From the blog post:

                        To visualize these answers, we’ll create salary distribution charts like this one for various answers:

                        Who is “we?” Who, other than yourself, will have access to individual answers?

                        Also, it would be nice if you provided contact info other than Twitter; you are excluding many people by requiring correspondents to sign up for a proprietary commercial service just to ask a question.

                        1. 1

                          It’s the company “we”. No one but me has access.

                          2 proprietary commercial services at this point. If you have questions you’re welcome to message me. I’ll also add further contact options to which now has the “blog post” of why I’m doing this.

                        1. 2

                          Requires a google account login, sure I can fake one up.

                          Asks for my employer… No thanks.

                          1. 2

                            Employer name (and almost all other questions) are optional

                            1. 1

                              Yup, sorry it does require a google account for now. Thanks for faking one. It’s the easiest way to reduce some “noise” responses and using Google Forms was a good step 1 to get a baseline of data I can use to build out a more interesting set of visualizations and questions.

                            1. 2

                              Interested in freelancers? And if yes, how optimistic should we be? Average workload for me would be working 75%-ish of the weeks in a year, but that varies drastically.

                              1. 1

                                If you haven’t looked yet, there is a section for freelancers.

                                1. 1

                                  Yes, definitely.

                                  And if yes, how optimistic should we be? Average workload for me would be working 75%-ish of the weeks in a year, but that varies drastically.

                                  Interesting, I’d not considered that. I’d say if you have historical data (i.e., last year’s total income) you could provide that. Otherwise best guess of 75% * your rate would be good. Make sure to mark that you’re a freelancer so that I can factor in that you don’t get some employer-provided benefits.

                                1. 1

                                  Submitted - I was quite surprised to see the result when I converted my GBP contractor rate to an annual “salary” in USD.

                                  As an aside, is it just me or does @calebthompson bear a passing resemblance to Ross Ulbricht? :)

                                  1. 1

                                    As an aside, is it just me or does @calebthompson bear a passing resemblance to Ross Ulbricht? :)

                                    Huh I’ve never heard that but I suppose I kind of do.

                                    1. 1

                                      Surprised in a good or a bad way?

                                      I’m always surprised by how low GBP job offers seem to be (around £40k/yr., even in London, for supposedly senior positions).

                                      1. 1

                                        In a good way, I suppose, although if I think about it the figure is a straight GBP -> USD conversion of my annual contracting income.

                                        Yes, GBP offers can vary a lot - as you say. I’ve seen positions with very similar descriptions and seniority vary from around £65k-£95k (all in London).

                                    1. 4

                                      I tried to submit from an incognito window, but that does not work. Is there any way this form can work w/o being logged in?

                                      1. 1

                                        Sorry, not at this point. I wanted to reduce duplicate answers and spam responses because with all of the free form responses there’s already a good amount of cleanup I need to do on this.

                                        You can log in with a personal google account to answer, or you can message me the answers if you’d like and I’ll add them manually.

                                      1. 15

                                        I think it’d be also useful to have asked about bonuses and other compensation over and above the base salary. For example, when I was at Apple, over 30% of my total comp was in Apple stock, which, being a public company, was pretty liquid and I pretty much equated to cash when I was comparing offers. I also got a 20% signing bonus and another 10% bonus almost a year later. Put that all together and the base comp woefully understates how much I got to put in the bank.

                                        1. 6

                                          Agreed. A lot of software engineering jobs have:

                                          1. Stock options (hard to value)
                                          2. RSU (can be easier to value for Amazon/Facebook/Google/Microsoft)
                                          3. Bonus structures

                                          Even 401k matching can be worth mentioning.

                                          1. 2

                                            Agreed! I had a really hard time finding a good phrasing for the questions because I wanted people to consider both monetary and non-monetary benefits. I had these two questions:

                                            Estimate your non-salary monetary benefits.

                                            This can be difficult to be sure on, so please make your best guess. For example, I don’t make commissions, I’ll likely get ~15% bonus, and my employer matches up to $5000 into my retirement account. I also got a restricted stock grant when I joined the company. You might have other sources, but those are the ones I could think of. Only include benefits provided by your employer.

                                            This one’s hard. Please try to estimate the monetary value of other benefits.

                                            Your employer probably has this in a spreadsheet somewhere, and maybe they’ll tell you. If you estimate it yourself, consider things like PTO (e.g. weeks * salary / 52), health insurance (try the calculator and say “no” to the spouse question (4) if you get health insurance from your employer. Use the silver plan annual cost), and other non-monetary benefits. I have “unlimited” PTO but based on what I think I’ve taken I said 4 weeks, so my salary / 52 * 4 for PTO.

                                            I asked for feedback on my questions from several people and anyone who addressed these questions noted that they were not good ones. They put too much work on the survey taker, and there’s already a good number of questions I’m asking. The alternative I could think of was to break out each of these into a bunch of questions like “What is the value of stocks you’re given?”, “How much does your health insurance cost based on this calculator”, “How much PTO do you get * how much it costs the company to employ you per day”, etc. It would have been a ton of extra questions and I didn’t think it was a good fit for this pass at the survey.

                                            In the future I plan to turn this into a more fun/interactive process and at that point I’ll definitely put some work into making this a part of the survey. To do that, I needed some seed data and I made the call that excluding non-salary benefits was right for this version.

                                            Thanks for the feedback! I really appreciate it.

                                          1. 2

                                            Thank you for writing this. Sometimes depression is bad enough that hobbies get put aside, but I’ve realized that hobbies that have “small wins” and are non-techie are often the best for getting some positive thinking back in one’s head.

                                            btw, you wrote:

                                            And sometimes we even create false limits for ourselves because we are unsure we will be able to

                                            Is there a missing word here?

                                            1. 1


                                            1. 8

                                              I have been doing a lot of thinking on burnout and mental health recently. This is the product of a lot of research into these, as well as the effects of hobbies on mental illnesses such as depression and anxiety.

                                              It was wonderful to be able to combine sharing my miniature painting hobby and some of this thinking.

                                              It’s especially important this time of year to be cognizant of mental health concerns. A big way to help spread this awareness is to talk and write about it.

                                              1. 1

                                                Thank you for writing about this! I really appreciate it.

                                                1. 1

                                                  Thank you for this. :)

                                                  1. 1

                                                    There’s something telling in that we should be the two people to comment on this … (something something trans something something)

                                                1. 7

                                                  Pretty Good Weekly is a pretty new security-oriented annotated list of links to articles/announcements/etc. relating to security and cryptography that I’ve been curating.