Comments (4)
I like that. It makes sense. I think I just need some sort of mechanism that tells the Email that when we call deliver
, don't actually do it. So I guess the skip_email
method would be the thing that sets the flag.
I'm thinking something like this:
abstract class Carbon::Email
property? deliverable : Bool = true
def skip_sending_email
self.deliverable = false
end
end
So the before/after hooks would all be empty similar to how they work in Avram. It would be up to you to decide what logic happens. The difference is Avram has add_error()
and valid?
which will short circuit the saving. In this case, we don't have that.
Lines 124 to 126 in 6cda3dd
This then becomes more like
def deliver
before_send
if deliverable?
response = settings.adapter.deliver_now(self)
after_send(response)
end
end
Does that sound good?
from carbon.
Doing this would actually solve the case for #61
class NotifierEmail < BaseEmail
def initialize(@recipient : Carbon::Emailable)
end
before_send do
# this would be up to you
unless @recipient.wants_to_get_marketing_emails?
# not sure about this...
skip_sending
end
end
after_send do |delivery_response|
# if this runs, the delivery_response would
# be the return value of the deliver_now adapter method
end
to @recipient
subject "Info for you"
templates text, html
end
I also wonder if this would fit better in the Deliver Later strategy
class CustomHookDeliverStrategy < Carbon::DeliverLaterStrategy
def run(email : Carbon::Email, &block)
before_send(email)
response = block.call
after_send(email, response)
end
def before_send(email)
# custom logic
end
def after_send(email, response)
# custom logic
end
end
BaseEmail.configure do |settings|
settings.deliver_later_strategy = CustomHookDeliverStrategy.new
end
The downsides to doing that path would be that you'd have to ALWAYS call deliver_later
to get the callbacks. Calling deliver
would skip those (maybe built-in escape hatch?). The next thing is where the logic for this all goes... On the one hand you could do it like this and have access to the email being sent, or you could move it in to all of the emails and call something like email.before_send
instead of before_send(email)
. But if you do put the logic here, you can't guarantee that the recipient of the email is always the same type of object. For example, you may have a User
and Admin
as two separate models. Trying to short circuit the email here could get a little hairy.
from carbon.
It also seems that this could coincide with #43 Where the idea is that you could subscribe to before email sending events, or after sending email events to do whatever it is you need (maybe save to Breeze?)
from carbon.
At the strategy layer, in order to solve #61 you'd need to be able to tag an email with a type (marketing, password, transactional) and then short circuit it in there. I don't think that's a great way to solve it. I can see that there would be some benefits to having a before/after hook at the strategy layer but I don't think it's a good fit for filtering out unwanted emails. It feels like a place to hang framework level concerns instead.
Adding a before hook to the Email base class seems like it'd be really powerful. Eg:
# include into any email which can be opted-out of
module EmailOptOutHandler
macro included
before_send do
unless @recepient.opt_in_email_types.includes? @type
skip_email
end
end
end
end
from carbon.
Related Issues (20)
- Support Postmark
- File attachment HOT 3
- Add markdown mailable and methods for embedding pre-made HTML components
- Add default templates
- DSL like Lucky Framework
- SendInBlue adapter HOT 5
- Add inline docs
- Integrate with Pulsar HOT 1
- Extract SendGrid adapter into separate shard HOT 1
- DevAdapter print_email option should highlight links HOT 1
- Add LuckyCli Task for generating a new email
- Why is colorize undefined? HOT 4
- Short circuit email sending HOT 1
- README uses deliver_now incorrectly
- be_delivered expectation fails when it shouldn't HOT 4
- Add layouts
- Generating a new email should detect if the word "Email" is included
- Consider changing how the layout is defined
- The layout filename should include the content type
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from carbon.