diff --git a/Gemfile b/Gemfile index 507491c..a3d355a 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,7 @@ source "https://rubygems.org" gem "pry", "~> 0.14" gem "rspec", "~> 3.11" +gem "activesupport", "~> 7.0.4" gem "rubocop-shopify" gem "rubocop-rspec" gem "rubocop" diff --git a/Gemfile.lock b/Gemfile.lock index 07380f1..99b79fa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,11 +1,20 @@ GEM remote: https://rubygems.org/ specs: + activesupport (7.0.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) ast (2.4.2) coderay (1.1.3) + concurrent-ruby (1.1.10) diff-lcs (1.5.0) + i18n (1.12.0) + concurrent-ruby (~> 1.0) json (2.6.2) method_source (1.0.0) + minitest (5.16.3) parallel (1.22.1) parser (3.1.2.1) ast (~> 2.4.1) @@ -51,6 +60,8 @@ GEM ruby2_keywords (0.0.5) saharspec (0.0.9) ruby2_keywords + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) unicode-display_width (2.3.0) PLATFORMS @@ -58,6 +69,7 @@ PLATFORMS x86_64-linux DEPENDENCIES + activesupport (~> 7.0.4) pry (~> 0.14) rspec (~> 3.11) rspec-its diff --git a/VERSION b/VERSION index f905682..8f0916f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.7 +0.5.0 diff --git a/lib/core_ext.rb b/lib/core_ext.rb deleted file mode 100644 index 306a182..0000000 --- a/lib/core_ext.rb +++ /dev/null @@ -1,2 +0,0 @@ -require "core_ext/deep_dup" -require "core_ext/duplicable" diff --git a/lib/core_ext/deep_dup.rb b/lib/core_ext/deep_dup.rb deleted file mode 100644 index b0a3758..0000000 --- a/lib/core_ext/deep_dup.rb +++ /dev/null @@ -1,53 +0,0 @@ -# https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/object/deep_dup.rb - -class Object - # Returns a deep copy of object if it's duplicable. If it's - # not duplicable, returns +self+. - # - # object = Object.new - # dup = object.deep_dup - # dup.instance_variable_set(:@a, 1) - # - # object.instance_variable_defined?(:@a) # => false - # dup.instance_variable_defined?(:@a) # => true - def deep_dup - duplicable? ? dup : self - end -end - -class Array - # Returns a deep copy of array. - # - # array = [1, [2, 3]] - # dup = array.deep_dup - # dup[1][2] = 4 - # - # array[1][2] # => nil - # dup[1][2] # => 4 - def deep_dup - map(&:deep_dup) - end -end - -class Hash - # Returns a deep copy of hash. - # - # hash = { a: { b: 'b' } } - # dup = hash.deep_dup - # dup[:a][:c] = 'c' - # - # hash[:a][:c] # => nil - # dup[:a][:c] # => "c" - def deep_dup - hash = dup - each_pair do |key, value| - if ::String === key || ::Symbol === key - hash[key] = value.deep_dup - else - hash.delete(key) - hash[key.deep_dup] = value.deep_dup - end - end - hash - end -end diff --git a/lib/core_ext/duplicable.rb b/lib/core_ext/duplicable.rb deleted file mode 100644 index b60cdc6..0000000 --- a/lib/core_ext/duplicable.rb +++ /dev/null @@ -1,42 +0,0 @@ -# https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/object/duplicable.rb - -class Object - # Can you safely dup this object? - # - # False for method objects; - # true otherwise. - def duplicable? - true - end -end - -class Method - # Methods are not duplicable: - # - # method(:puts).duplicable? # => false - # method(:puts).dup # => TypeError: allocator undefined for Method - def duplicable? - false - end -end - -class UnboundMethod - # Unbound methods are not duplicable: - # - # method(:puts).unbind.duplicable? # => false - # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod - def duplicable? - false - end -end - -require "singleton" - -module Singleton - # Singleton instances are not duplicable: - # - # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton - def duplicable? - false - end -end diff --git a/lib/statinize.rb b/lib/statinize.rb index ca66b99..79c47f0 100644 --- a/lib/statinize.rb +++ b/lib/statinize.rb @@ -1,7 +1,9 @@ require "set" require "pry" +require "active_support" +require "active_support/core_ext/object/deep_dup" +require "active_support/core_ext/object/with_options" require "bigdecimal/util" -require "core_ext" require "statinize/statinizable" require "statinize/dsl" require "statinize/statinizer" diff --git a/lib/statinize/dsl.rb b/lib/statinize/dsl.rb index a042bbd..8c820df 100644 --- a/lib/statinize/dsl.rb +++ b/lib/statinize/dsl.rb @@ -1,6 +1,8 @@ # Defines DSL for statinize block module Statinize module DSL + alias_method :with, :with_options + def attribute(*attrs, **options) attrs.each do |attr| Attribute.create(klass, attr, options) unless attribute? attr @@ -15,26 +17,6 @@ def validate(*attrs, **options) end end - def with(**options, &block) - # create new statinizer instance - instance = self.class.new(klass) - instance.force(force) - - # execute block in the context of that statinizer - # while it's attached to the klass - # then rewind and attach the original statinizer(self) - # back to the klass - klass.instance_variable_set(:@statinizer, instance) - instance.instance_exec(&block) - klass.instance_variable_set(:@statinizer, self) - - # merge the newly created statinizer with the options - instance.merge_options(**options) - - # populate self with the instance's attributes - populate(instance.attributes) - end - def before(&block) return unless block_given? diff --git a/lib/statinize/statinizer.rb b/lib/statinize/statinizer.rb index e1b6833..8a86c7c 100644 --- a/lib/statinize/statinizer.rb +++ b/lib/statinize/statinizer.rb @@ -40,14 +40,6 @@ def check_validators_exist! raise NoSuchValidatorError unless all_validators_defined? end - def merge_options(**options) - attributes.each do |attribute| - attribute.options_collection.each do |option| - option.merge!(options) - end - end - end - def populate(attrs) attrs.each do |attr| attribute attr.arg_name, name: attr.name, default: attr.default, default_exec: attr.default_exec diff --git a/spec/statinize/with_spec.rb b/spec/statinize/with_spec.rb new file mode 100644 index 0000000..0a6aaaf --- /dev/null +++ b/spec/statinize/with_spec.rb @@ -0,0 +1,40 @@ +RSpec.describe "With" do + subject { WithDummy.new(params) } + + context "two with blocks" do + context "first validation is violated" do + let!(:params) { { a: "a", c: :a } } + + its(:valid?) { should be_truthy } + + context "both validations are calls to validate" do + let!(:params) { { a: :a, c: "c" } } + + its(:valid?) { should be_falsey } + end + end + end +end + +class WithDummy + include Statinize + + statinize do + with type: Symbol do + attribute :a + end + + with presence: true do + attribute :a + end + + attribute :c + with type: Symbol do + validate :c + end + + with presence: true do + validate :c + end + end +end diff --git a/statinize.gemspec b/statinize.gemspec index 70a959c..4aa14e7 100644 --- a/statinize.gemspec +++ b/statinize.gemspec @@ -10,4 +10,6 @@ Gem::Specification.new do |s| s.files = Dir["lib/**/*.rb"] s.license = "MIT" s.platform = Gem::Platform::RUBY + + s.add_runtime_dependency "activesupport", "~> 7.0.0" end