diff --git a/lib/stripe/stripe_object.rb b/lib/stripe/stripe_object.rb index ed1b30c8c..d4795c2bc 100644 --- a/lib/stripe/stripe_object.rb +++ b/lib/stripe/stripe_object.rb @@ -144,6 +144,28 @@ def dirty! end end + # Implements custom encoding for Ruby's Marshal. The data produced by this + # method should be comprehendable by #marshal_load. + # + # This allows us to remove certain features that cannot or should not be + # serialized. + def marshal_dump + # The StripeClient instance in @opts is not serializable and is not + # really a property of the StripeObject, so we exclude it when + # dumping + opts = @opts.clone + opts.delete(:client) + [@values, opts] + end + + # Implements custom decoding for Ruby's Marshal. Consumes data that's + # produced by #marshal_dump. + def marshal_load(data) + values, opts = data + initialize(values[:id]) + initialize_from(values, opts) + end + def serialize_params(options = {}) update_hash = {} diff --git a/test/stripe/stripe_object_test.rb b/test/stripe/stripe_object_test.rb index 8e90561f5..60bd02be4 100644 --- a/test/stripe/stripe_object_test.rb +++ b/test/stripe/stripe_object_test.rb @@ -410,5 +410,18 @@ class StripeObjectTest < Test::Unit::TestCase end assert_match(/\(object\).foo = nil/, e.message) end + + should "marshal and unmarshal using custom encoder and decoder" do + obj = Stripe::StripeObject.construct_from( + { id: 1, name: "Stripe" }, + api_key: "apikey", + client: StripeClient.active_client + ) + m = Marshal.load(Marshal.dump(obj)) + assert_equal 1, m.id + assert_equal "Stripe", m.name + expected_hash = { api_key: "apikey" } + assert_equal expected_hash, m.instance_variable_get("@opts") + end end end