1

Right now I have a model Trip that when saved, runs some callbacks. I want to isolate this behavior so that it happens only when it runs on the controller (create/update/destroy), so I want to remove the callbacks.

Assuming I have a service object DoSomething#call which accepts trip and does everything I need, what are my options to run it in create/update/destroy?

I have a few ideas but they involve horror things like:

def create
  super() do |success, failure|
    @action_successful = failure.instance_of?(
      InheritedResources::BlankSlate
    ) || failure.class.nil?
    if @action_successful
      DoSomething.call(Trip.find(params[:id]))
    end
  end
end

Which comes with a lot of downsides:

  • The horrible way to detect if an action is successful
  • No way to get the in-memory reference to the object being acted on (reload from db)
  • Since I have no reference to the in memory object, it's quite problematic to run something during on destroy (no reference, can't reload)

Additional code as requested

class Trip
end

The custom service (I've multiples)

class SaveLastChangedTrip
  def call(user, trip)
    return if user.nil?
    user.update_attributes!(last_trip: trip)
  end
end

and the activeadmin file

ActiveAdmin.register Trip do
  controller do
    def update
      if super() # This is pseudocode, I want to run this branch only if save is successful
        SaveLastChangedTrip.call(current_user, resource)
      end
    end
  end
end
Francesco Belladonna
  • 11,361
  • 12
  • 77
  • 147
  • hello, have you considered using an observer pattern https://medium.com/@mitchocail/observer-pattern-in-ruby-e80ac3c1dac7? – Bohdan Apr 25 '17 at 18:53
  • Hello @Bohdan , the observer pattern would fit, but I have no access to the in-memory copy of the object, not that I'm aware of, so it gets a bit complicated even "watching" the object to use the observer pattern – Francesco Belladonna Apr 26 '17 at 04:29
  • could you add more code? Problem looks complicated and more info would be helpful – Bohdan Apr 26 '17 at 04:37
  • Sure, added an example of what I'm trying to achieve! – Francesco Belladonna Apr 26 '17 at 17:43
  • hey, I'm not familiar with ActiveAdmin but from what I've read you may be able to access object with `@trip = Trip.find(params[:id])`, also you may try to insert `debugger/binding.pry` to see what data you have – Bohdan Apr 27 '17 at 03:42
  • With rails is straightforward, the problem is indeed activeadmin itself, I found that in their public API `resource` is cached, problem is I still have no way to know if the save was successful or not, maybe I can check for `errors` – Francesco Belladonna Apr 27 '17 at 21:16

1 Answers1

2

I think you are looking for something like this:

    def create
      create! do |success, failure|
        success.html do
          DoSomething.call(resource)
        end
      end
    end

See comments.rb for similar example.

Piers C
  • 2,880
  • 1
  • 23
  • 29