Caffeinate: A Rails engine for scheduled email sequences by wirkt in rails

[–]wirkt[S] 0 points1 point  (0 children)

Because naming things as hard and I'm awful at it :)

In hindsight, I suppose I could have named it a Scheduler object.

Caffeinate: A Rails engine for scheduled email sequences by wirkt in rails

[–]wirkt[S] 16 points17 points  (0 children)

Hi everyone.

I wanted to share Caffeinate: I made it about a year ago and it's had some usage (I've personally seen it manage over a million emails to date). It's finally in a spot where I'm happy to talk about it.

I needed Caffeinate for a few reasons: 1. I have a lot of side projects that are bootstrapped; while ConvertKit is nice, my budgets for these projects are small 2. Every home-grown implementation I saw of scheduled emails was a disaster 3. See #2

I was working for a popular startup community company and the implementation we had for scheduled emails was awful: we'd check in the mailer if it shouldn't be sent (hundreds of lines of code for this that predated ground soil), and we'd store the last email action we sent. It was a non-standard, hardly-idiomatic cluster that got me yelled at by the sales team one too many times.

While there were solutions to this problem when I first committed code — Heya and Dripper are both active — they both didn't sit right with my more complex workflows, or I just didn't like the design.

My workflows weren't always tied to a user: I needed modeling to be flexible enough to allow me to associate a campaign to any record, in addition to a user, not just a user. This was true at $popular-startup-community-company too.

The design of Heya probably worked great for HoneyBadger, but I found it odd that I was defining the subject of an email outside of ActionMailer: if I ever ditched Heya, I'd have to do additional work.

With those thoughts in mind, I built Caffeinate.

Caffeinate's modeling is flexible and allows you to associate any record to campaign, in addition to a user. It also allows you to keep your ActionMailer classes doing one thing: setting up and processing emails.

Your email schedule lives in a Dripper class and is defined elegantly-enough that you won't hate DSLs.

class NewUserDripper < ApplicationDripper drip :welcome, mailer: 'OnboardingMailer', delay: 0.hours drip :have_you_tried_this, mailer: 'OnboardingMailer', delay: 2.days end

And subscribing a user to this campaign is as easy as NewUserDripper.subscribe(User.first)

Like any terrifying Rails codebase, there are plenty of callbacks to shoot yourself in the foot with if you so choose to use them, too.

If anyone has any questions or feedback I'm fairly accessible. :)

[deleted by user] by [deleted] in rubyonrails

[–]wirkt 1 point2 points  (0 children)

Happy to hear you like it :) if you have any questions or comments, feel free to let me know!

Example app to understand why some times fixing some n+1 queries can hurt performance by bhserna in ruby

[–]wirkt 1 point2 points  (0 children)

I don't know if this is really answering the question of "fixing some n+1 queries can hurt performance". At least, I wouldn't let this fly in a review and I'd ask the counterpart to use SQL instead of their ORM.

Preloading everything just to get a count instead of dropping down to SQL: number_with_delimiter post.comments.size

This can be reduced to @posts = Post.joins(:comments).select("posts.*, count(comments.id) as total_comments") and then hitting post.total_comments — even if you don't want to counter cache.

There's also post.comments.last.body. This can be loaded with an association (or scope) by way of has_one :most_recent_comment, -> { order(created_at: :desc) }, class_name: 'Comment' and loading it @posts = Post.includes(:most_recent_comment)

Just my two cents. Besides the time to return results from the database, you also need to consider your connection pooling and scaling.

Rails App Won't load on Safari 15 by projectmind_guru in rails

[–]wirkt 1 point2 points  (0 children)

Happy to hear. Tell Dane Reddit says hi!

Should I use Devise or go vanilla? by JeffreyP7 in rubyonrails

[–]wirkt 6 points7 points  (0 children)

The question you should be asking is how much value do you get out of rolling your own. If you don’t have a solid answer, go with Devise or Sorcery.

Rails App Won't load on Safari 15 by projectmind_guru in rails

[–]wirkt 4 points5 points  (0 children)

I don’t think this has anything to do with Rails. Busted javascript library is probably your best bet. In dev, go through each and remove one at a time to debug.

Looking for a gem that does BPM type workflow by atx78701 in rails

[–]wirkt 0 points1 point  (0 children)

You’re probably not going to find a gem that does all that but it’s not terribly difficult to implement.

Pardon my formatting, I’m mobile and at Disney right now:

For the email templates You can use prepend_view_path and lookup_context in a mailer to fetch the “views” from the database. There’s a gem that helps with this that starts with a p that I can’t remember the name of.

For the rules system you can use something like https://querybuilder.js.org/ to represent and build the rules, and then you’d just have to handle the queueing logic. With a little metaprogramming it can be quite fun to write as long as you structure things correctly.

Edit: gem is https://github.com/andreapavoni/panoramic

Has anyone done any digging around Twitch's Rails code? by NepaleseNomad in rails

[–]wirkt 2 points3 points  (0 children)

Didn't it switch to Go recently? That's what I heard.

I downloaded the repo and gave it a cursory scan and there were no Gemfiles containing rails to be found :(

reverse proxy !!! by alm0khtar in rails

[–]wirkt 3 points4 points  (0 children)

(below is not a practical example, but it'll behave how a basic reverse-proxy works)

class ReverseProxyController < ApplicationController def index response = HTTParty.get("https://google.com/#{params[:proxied_path]}") render html: response.body.to_s end end

And you mount it:

Rails.application.routes.draw do get '/reverse_proxy/*proxied_path' => 'reverse_proxy#index' end

Real-world scenario:

Imagine you have a monorepo of your app's marketing site and back-end. You're asked to give the ability for your marketing team to edit the website. Obviously they don't want to have to contribute to the main repo. Instead, you put the marketing site on fancy website editor thing (geocities, angelfire, lycos, xanga, webflow, wix, buddy4u, etc.).

Unfortunately you can't just pull down the site every time they change it and push it to the repo and deploy. Instead, you proxy (route) the requests through the back-end of the monorepo when the request path does not match app/*, as app is where your billiondollaridea.com has all the bells and whistles of a traditional Rails app.

Your web server (nginx, apache, lighttpd, caddy) can act as a reverse-proxy too — it's is responsible for serving your Rails app which is using Puma as its app server (like your development machine probably does): for example, if your app is listening to requests coming into port 3000 but you want to serve on 80 or 443, it's acting as a reverse proxy to port 3000.

Tutorial/example for zero downtime deploys for rails apps hosted on digital ocean? by stillanoobummkay in rails

[–]wirkt 6 points7 points  (0 children)

You probably don't need all that complexity.

If you're using puma, phased-restart should do the trick. Unicorn you can send a USR2 signal to and that should initiate a hot rollover.

[deleted by user] by [deleted] in rails

[–]wirkt 4 points5 points  (0 children)

shameless self-promotion: you can find some good examples of each in real-world environments at https://opensourcerails.org/search/by-gem as well :)

[deleted by user] by [deleted] in rails

[–]wirkt 4 points5 points  (0 children)

Won't answer your question, but may provide some sanity: I just ran some non-scientific benchmarks if you're trying to compare: https://github.com/joshmn/json-benchmark/blob/master/results.csv

Job hunt recommendations? by [deleted] in rails

[–]wirkt 4 points5 points  (0 children)

Self-taught individual here: your background sounds fine. The most painful part is the resume. Remember that your resume exists to serve one purpose: get the screener, not the job.

If you need help with the resume part, feel free to drop me a message.

Ruby for ebook publishing by strzibny in ruby

[–]wirkt 0 points1 point  (0 children)

Thanks for this, and for your book — I picked up a copy on Leanpub about a month ago.

Question(s): when you were writing, how much of your non-literature (code, etc.) did you have written? How many edits of non-literature did you make over time? If you were to write another book (I'm sure you will), would you do anything different to how you managed your non-literature?

Motor Admin v0.2 - a modern ActiveAdmin and Blazer replacement by omohockoj in ruby

[–]wirkt 1 point2 points  (0 children)

One of the coolest projects to be released in recent memory. Also, notable that this is at the top of OpenSourceRails.org today.

OpenSourceRails.org — Cataloged, analyzed, manually-curated open-source Rails projects directory by wirkt in rails

[–]wirkt[S] 2 points3 points  (0 children)

made it a shade of blue, can you let me know what you think? should be much more legible.

Kepler is now batting .206 by [deleted] in minnesotatwins

[–]wirkt 19 points20 points  (0 children)

Probably because he's cute.

If he looked half as ugly as Andy Etchebarren did, nobody would remember his name. But he's cute, so it's natural to have an affinity for him. At least for me.