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 for classes and methods #72

Closed
ream88 opened this issue May 18, 2015 · 4 comments
Closed

Support for classes and methods #72

ream88 opened this issue May 18, 2015 · 4 comments

Comments

@ream88
Copy link

ream88 commented May 18, 2015

In my current project I use a lot of DI in the form of:

def do_something(first: SomeClass, second: SomeClass.method(:some_method))
  # ...
end

Passing my dependencies to an ActiveJob fails with an ActiveJob::SerializationError: Unsupported argument type: Class (or respectively Unsupported argument type: Method). However, I think this could be easily done by serialising methods and classes into:

SomeClass.method(:some_method).to_global_id # => gid://App/SomeClass/some_method
SomeClass.to_global_id # => gid://App/SomeClass/class

Anyone interested in this feature? Suggestions?

@ream88
Copy link
Author

ream88 commented May 18, 2015

Btw this could be more of an ActiveJob problem, just tell me if this belongs to the Rails repository.

@rafaelfranca
Copy link
Member

I don't know if it is a good idea to include this behavior by default. Right now I think you can implement your own to_global_id implementation.

@ream88 ream88 changed the title Support for Classes and methods Support for classes and methods May 18, 2015
@kaspth
Copy link
Contributor

kaspth commented May 18, 2015

Yeah, I don't see this in Global ID directly. I'd probably create some sort of wrapper model that takes a method or class and implements find. Good luck ❤️

@kaspth kaspth closed this as completed May 18, 2015
@ream88
Copy link
Author

ream88 commented May 19, 2015

Just for the record, and if anybody else needs something similar:
Solved it for now using this dirty (overwriting private methods 👎) module:

# class_and_method_arguments.rb
require 'active_job/arguments'


module ActiveJob
  module ClassAndMethodArguments
    def serialize_argument(argument)
      case argument
      when Class, Module
        URI::GID.build(app: GlobalID.app, model_name: argument.name, model_id: :itself).to_s
      when Method
        URI::GID.build(app: GlobalID.app, model_name: argument.receiver.name, model_id: argument.name).to_s
      else
        super
      end
    end


    def deserialize_argument(argument)
      case argument
      when String
        gid = URI::GID.parse(argument)

        # GID probably references an Model instance,
        # when model_id starts with numeric characters.
        case gid.model_id
        when /^\d+/
          super
        when 'itself'
          gid.model_name.constantize
        else
          gid.model_name.constantize.method(gid.model_id)
        end
      else
        super
      end
    rescue URI::BadURIError
      super
    end
  end


  Arguments.send :extend, ClassAndMethodArguments
end
# class_and_method_arguments_test.rb
require_relative '../../test_helper'


module ActiveJob
  class ClassAndMethodArgumentsTest < Minitest::Test
    def test_classes
      argument = [ActiveJob::Base]

      assert_equal argument, Arguments.deserialize(Arguments.serialize(argument))
    end


    def test_modules
      argument = [ActiveJob]

      assert_equal argument, Arguments.deserialize(Arguments.serialize(argument))
    end


    def test_methods
      argument = [ActiveJob::Base.method(:new)]

      assert_equal argument, Arguments.deserialize(Arguments.serialize(argument))
    end
  end
end

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

No branches or pull requests

3 participants