Skip to content

Commit

Permalink
fix: update active support support for Ruby 3.0
Browse files Browse the repository at this point in the history
Fixes: #85
  • Loading branch information
bethesque committed Jan 21, 2021
1 parent 575e491 commit 6c30d42
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 27 deletions.
42 changes: 27 additions & 15 deletions lib/pact/shared/active_support_support.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@

module Pact
module ActiveSupportSupport

extend self

def fix_all_the_things thing
if thing.is_a?(Regexp)
fix_regexp(thing)
elsif thing.is_a?(Array)
thing.each{ | it | fix_all_the_things it }
elsif thing.is_a?(Hash)
thing.values.each{ | it | fix_all_the_things it }
elsif thing.class.name.start_with?("Pact")
thing.instance_variables.collect{ | iv_name | thing.instance_variable_get(iv_name)}.each do | iv |
fix_all_the_things iv
if defined?(ActiveSupport)
if thing.is_a?(Regexp)
fix_regexp(thing)
elsif thing.is_a?(Array)
thing.collect{ | it | fix_all_the_things it }
elsif thing.is_a?(Hash)
thing.each_with_object({}) { | (k, v), new_hash | new_hash[k] = fix_all_the_things(v) }
elsif thing.is_a?(Pact::Term)
# matcher Regexp is fixed in its own as_json method
thing
elsif thing.class.name.start_with?("Pact")
warn_about_regexp(thing)
thing
else
thing
end
else
thing
end
thing
end

# ActiveSupport JSON overwrites (i.e. TRAMPLES) the json methods of the Regexp class directly
Expand All @@ -27,10 +33,7 @@ def fix_all_the_things thing
# original as_json to the Regexp instances in the ConsumerContract before we write them to the
# pact file. If anyone can find a better way, please submit a pull request ASAP!
def fix_regexp regexp
def regexp.as_json options = {}
{:json_class => 'Regexp', "o" => self.options, "s" => self.source }
end
regexp
{:json_class => 'Regexp', "o" => regexp.options, "s" => regexp.source }
end

# Having Active Support JSON loaded somehow kills the formatting of pretty_generate for objects.
Expand All @@ -49,5 +52,14 @@ def remove_unicode json
json.gsub(/\\u([0-9A-Za-z]{4})/) {|s| [$1.to_i(16)].pack("U")}
end

def warn_about_regexp(thing)
thing.instance_variables.each do | iv_name |
iv = thing.instance_variable_get(iv_name)
if iv.is_a?(Regexp)
require 'pact/configuration'
Pact.configuration.error_stream.puts("WARN: Instance variable #{iv_name} for class #{thing.class.name} is a Regexp and isn't been serialized properly. Please raise an issue at https://github.com/pact-foundation/pact-support/issues/new.")
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/pact/term.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def initialize(attributes = {})
end

def to_hash
{ json_class: self.class.name, data: { generate: generate, matcher: fix_regexp(matcher)} }
{ json_class: self.class.name, data: { generate: generate, matcher: fix_regexp(matcher) } }
end

def as_json(options = {})
Expand Down
46 changes: 35 additions & 11 deletions spec/lib/pact/consumer_contract/active_support_support_spec.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
require 'spec_helper'
require 'pact/shared/active_support_support'
require 'pact/configuration'

module Pact
describe ActiveSupportSupport do

include ActiveSupportSupport
class TestClassWithRegexpInstanceVariables
attr_accessor :pattern, :not_pattern

def initialize
@pattern = /foo/
@not_pattern = "bar"
end
end
describe ActiveSupportSupport do
include ActiveSupportSupport

describe "fix_regexp" do
let(:regexp) { /moose/ }

subject { fix_regexp regexp }

it "returns the original regexp" do
expect(subject).to be(regexp)
end

it "fixes the as_json method for Regexp that ActiveSupport tramples beneath its destructive hooves of destruction" do
expect(subject.to_json).to eq("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"moose\"}")
end

end

describe "fix_all_the_things" do
Expand All @@ -28,16 +32,36 @@ module Pact

subject { fix_all_the_things(hash) }

it "returns the original object" do
expect(subject).to be(hash)
end

it "finds all the Regexp objects in hashes or Pact class attributes and fixes the as_json method" do
json = subject.to_json
expect(json).to include("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"a*b\"}")
expect(json).to include("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"blah\"}")
expect(json).to include("{\"json_class\":\"Regexp\",\"o\":0,\"s\":\"alligator\"}")
end

context "with Pact class that have Regexp instance variables" do
before do
allow(Pact).to receive_message_chain(:configuration, :error_stream).and_return(error_stream)
end

let(:error_stream) { double('stream', puts: nil) }
let(:thing_to_serialize) do
{
something: {
blah: [ TestClassWithRegexpInstanceVariables.new ]
}
}
end

subject { fix_all_the_things(thing_to_serialize) }

context "when ActiveSupportSupport is defined" do
it "prints a warning", skip: ENV['LOAD_ACTIVE_SUPPORT'] != 'true' do
expect(error_stream).to receive(:puts).with("WARN: Instance variable @pattern for class Pact::TestClassWithRegexpInstanceVariables is a Regexp and isn't been serialized properly. Please raise an issue at https://github.com/pact-foundation/pact-support/issues/new.")
subject.to_json
end
end
end
end

describe "fix_json_formatting" do
Expand Down

0 comments on commit 6c30d42

Please sign in to comment.