integrallis / stripe_event

Stripe webhook integration for Rails applications.
https://rubygems.org/gems/stripe_event
MIT License
844 stars 104 forks source link

Added event_namespacer #51

Closed TrevorHinesley closed 9 years ago

TrevorHinesley commented 9 years ago

Possible example:

class EventNamespacer
  def call(event, params)
    event_namespace = event[:type]

    case event_namespace
    when /charge.dispute/
      event_namespace.insert(0, "subscription.") unless params[:user_id]
    when /charge.succeeded/
      event_namespace.insert(0, "subscription.") unless params[:user_id]
    when /charge.failed/
      event_namespace.insert(0, "subscription.") unless params[:user_id]
    end

    event_namespace
  end
end

StripeEvent.event_namespacer = EventNamespacer.new

Now I could subscribe to "subscription.charge.dispute.created" and treat it differently for users that aren't Stripe Connect users. Other namespacing uses exist as well.

coveralls commented 9 years ago

Coverage Status

Coverage remained the same at 100.0% when pulling 9f84dadec9c0da6c703fa59ddbbf38cf196fb070 on TrevorHinesley:master into 31bea5ca5de578dbb59d9981cf8164eb99a31733 on integrallis:master.

rmm5t commented 9 years ago

Sorry, I'm not a fan of this.

  1. There aren't any tests associated with the pull-request.
  2. This solution doesn't feel intuitive, and it feels like unnecessary repetition to solve the problem.

I'm not sure if this will work, but can't you just solve this problem entirely in your EventRetriever?

The EventRetriever has access to all the params and after looking up a Stripe::Event, because Stripe::Event is just StripeObject (really just a hash-like mashie-like object), you can just add a user_id attribute to it.

For example, imagine an EventRetriever like so:

class EventRetriever
  def call(params)
    api_key = retrieve_api_key(params[:user_id])
    Stripe::Event.retrieve(params[:id], api_key).tap do |event|
      event.user_id = params[:user_id]  # <------------- Here's the magic.
    end
  end

  def retrieve_api_key(stripe_user_id)
    Account.find_by!(stripe_user_id: stripe_user_id).api_key
  rescue ActiveRecord::RecordNotFound
    # whoops something went wrong - error handling
  end
end

Disclaimer: This idea is untested.

As long as you know your main Stripe account's ID, you can then handle this downstream and not have to further involve this gem.

invisiblefunnel commented 9 years ago

There was a similar discussion in #30.

You can return anything you'd like from the retriever, which effectively allows you to pass the params along.

Note that the hash returned needs to have a :type key so it can be properly dispatched.

Something like this should work:

StripeEvent.event_retriever = ->(params) do
  event = Stripe::Event.retrieve(params[:id])
  { type: event[:type], event: event, params: params }
end

Does this solution work for you @TrevorHinesley?

Maybe this should be a documented use case?

TrevorHinesley commented 9 years ago

@invisiblefunnel absolutely, very sorry! Missed that issue. Thanks @rmm5t as well, my mistake.

Oh and @invisiblefunnel, yes I think with the rise in popularity of Stripe Connect, this could be coming up more often. Might be nice to document it. I'm sure there's other valid uses cases outside of this one as well.

ollym commented 9 years ago

Would it not make sense to be able to set instance variables in the event retriever that can be used in the event callbacks themselves?