Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support transactions #20

Closed
tfausak opened this issue Jul 11, 2013 · 2 comments
Closed

Support transactions #20

tfausak opened this issue Jul 11, 2013 · 2 comments
Assignees
Milestone

Comments

@tfausak
Copy link
Collaborator

tfausak commented Jul 11, 2013

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

Specifically look at wrapping execute in a transaction by default with an option to disable it.

@tfausak
Copy link
Collaborator Author

tfausak commented Jul 15, 2013

We'd have to add a dependency on ActiveRecord to do this. Looks like it'd be pretty straightforward, though:

require 'active_record'
module ActiveInteraction
  class Base
    def self.run(options = {})
      new(options).tap do |interaction|
        if interaction.valid?
          result = nil
          ::ActiveRecord::Base.transaction do
            result = interaction.execute
          end
          interaction.instance_variable_set(:@result, result)
        end
      end
    end
  end
end

Testing it would be a little difficult.

@ghost ghost assigned tfausak Jul 15, 2013
@tfausak
Copy link
Collaborator Author

tfausak commented Jul 15, 2013

I just want to reiterate that testing this is a pain in the ass. The implementation is a piece of cake:

module ActiveInteraction
  class Base
    begin
      require 'active_record'
      def self.transaction
        ::ActiveRecord::Base.transaction do
          yield
        end
      end
    rescue LoadError
      def self.transaction
        yield
      end
    end
    private_class_method :transaction

    def self.run(options = {})
      new(options).tap do |interaction|
        if interaction.valid?
          result = transaction { interaction.execute }
          interaction.instance_variable_set(:@result, result)
        end
      end
    end
  end
end

It's simple enough that I wouldn't feel bad about shipping it without tests, but that feels dirty. I just can't think of a clean way to set up a test that:

  1. Runs with and without transactions enabled. In other words, with ActiveRecord, then without it.
  2. Sets up a database connection and a model and saves instances of the model to the database. This is probably the least challenging part, but it's still worth mentioning.
  3. Checks nested transactions.

On top of all that, ActiveRecord should be disabled for the rest of the test suite because it'll slow it down somewhat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant