Giter VIP home page Giter VIP logo

dry-core's People

Contributors

acook avatar actions-user avatar alsemyonov avatar amatsuda avatar cllns avatar deepj avatar dry-bot avatar edwardbetts avatar elcuervo avatar esparta avatar flash-gordon avatar gustavocaso avatar jodosha avatar oleander avatar olleolleolle avatar poloka avatar skryukov avatar solnic avatar sztheory avatar tallica avatar timriley avatar waiting-for-dev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dry-core's Issues

uninitialized constant Dry::Struct::Extensions (NameError)

After upgrade to latest gems (zeitwerk release), I'm getting in the Rails app when trying to run tests:

/home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/dry-core-0.9.0/lib/dry/core/deprecations.rb:227:in `block (2 levels) in deprecate_constant': uninitialized constant Dry::Struct::Extensions (NameError)
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader/helpers.rb:127:in `const_get'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader/helpers.rb:127:in `cget'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader.rb:246:in `block (2 levels) in eager_load'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader/helpers.rb:41:in `block in ls'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader/helpers.rb:27:in `each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader/helpers.rb:27:in `ls'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader.rb:234:in `block in eager_load'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader.rb:219:in `synchronize'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader.rb:219:in `eager_load'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader.rb:318:in `each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/zeitwerk-2.6.1/lib/zeitwerk/loader.rb:318:in `eager_load_all'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/application/finisher.rb:74:in `block in <module:Finisher>'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/initializable.rb:32:in `instance_exec'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/initializable.rb:32:in `run'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/initializable.rb:61:in `block in run_initializers'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:228:in `block in tsort_each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:431:in `each_strongly_connected_component_from'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:349:in `block in each_strongly_connected_component'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:347:in `each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:347:in `call'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:347:in `each_strongly_connected_component'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:226:in `tsort_each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/3.1.0/tsort.rb:205:in `tsort_each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/initializable.rb:60:in `run_initializers'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/application.rb:372:in `initialize!'
	from /home/wojtek/Projects/tiramizoo/dm/config/environment.rb:5:in `<top (required)>'
	from /home/wojtek/Projects/tiramizoo/dm/test/test_helper.rb:2:in `require_relative'
	from /home/wojtek/Projects/tiramizoo/dm/test/test_helper.rb:2:in `<top (required)>'
	from /home/wojtek/Projects/tiramizoo/dm/test/controllers/healths_controller_test.rb:1:in `require'
	from /home/wojtek/Projects/tiramizoo/dm/test/controllers/healths_controller_test.rb:1:in `<top (required)>'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/test_unit/runner.rb:47:in `require'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/test_unit/runner.rb:47:in `block in load_tests'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/test_unit/runner.rb:47:in `each'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/test_unit/runner.rb:47:in `load_tests'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/test_unit/runner.rb:40:in `run'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/commands/test/test_command.rb:33:in `perform'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/command/base.rb:87:in `perform'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/command.rb:48:in `invoke'
	from /home/wojtek/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/railties-7.0.4/lib/rails/commands.rb:18:in `<top (required)>'
	from bin/rails:4:in `require'
	from bin/rails:4:in `<main>'

This happens when config.eager_load = true in the config/environments/test.rb (when it's false it works fine)

I'm not using Dry::Struct::Extensions anywhere directly.
I'm using only basic Dry::Validation::Contract and Dry::Struct

Risk of hash collisions with Dry::Core::Memoizable

Hello! I'm writing on behalf of the team behind MemoWise, a Ruby memoization gem that aims to provide fast memoized lookups. First of all, I wanted to say we're big fans of Dry::Core::Memoizable—had we known about it years ago we might not have ever written our gem and instead just used yours. 😄

In a recent push to increase performance, we took inspiration from Dry::Core::Memoizable and used Array#hash directly to produce our hash keys, rather than using array keys (which the hash has to compare using both Array#hash and a more expensive Array#eql? call). This is a really clever solution @flash-gordon came up with, and it made our gem much faster.

However, after discussions among our team we've decided we don't feel comfortable with this approach because of its risk of hash collisions: two different sets of method arguments could hash to the same integer, and our gem would return incorrect memoized results. While unlikely, collisions are not impossible (which is why hashes use both #hash and #eql? when comparing keys). This behavior would also be nondeterministic and hard for users to debug because Ruby uses pseudorandom hash functions so collisions will vary between different runs of the Ruby interpreter.

We haven't noticed any hash collisions ourselves, but because the bug would be subtle we can't be confident it hasn't already happened to us, and for the time being we do not consider this optimization safe. We wanted to let you know we plan to update MemoWise to use array hash keys again instead of directly calling .hash to produce integer keys, and give you the opportunity to similarly update Dry::Core::Memoizable if you agree with our conclusion. Please let us know what you decide to do! If you decide to remove Array#hash, we'll update our benchmarks to compare against the latest version of Dry::Core::Memoizable. If you decide not to, that's okay too—we'll just link to this issue explaining the differences between our gems.

Child classes attributes overwrites the parent one when used as hash

Describe the bug

Hello! I'm trying to define a simple DSL using ClassAttributes from dry-core but encountered a weird issue in the process. Please have in mind topic of instance/class variables, inheritance and all the hassles related to that are a bit challenging to me so please forgive my ignorance if I'm asking for something obvious :) I'm also not entirely sure it is a bug or just me misusing the ClassAccessor but i was asked to port that question here from Zulip so let's find out.

To Reproduce

class Base
  extend Dry::Core::ClassAttributes

  defines :exception_handlers

  def self.handle_exception(key, value)
    new_exception_handlers = exception_handlers || {}
    new_exception_handlers[key] = value
    exception_handlers new_exception_handlers
  end

  handle_exception :no_method_error, :default
end

class ClassA < Base
  handle_exception :no_method_error, :class_a_overwrite
end

class ClassB < Base
end

pp Base.exception_handlers
# => {:no_method_error=>:class_a_overwrite}

pp ClassB.exception_handlers
# => {:no_method_error=>:class_a_overwrite}

Expected behavior

pp Base.exception_handlers
# => {:no_method_error=>:default}

pp ClassA.exception_handlers
# => {:no_method_error=>:class_a_overwrite}

pp ClassB.exception_handlers
# => {:no_method_error=>:default}

My environment

  • Affects my production application: YES
  • Ruby version: 2.5.3

Ruby warnings of constant redefinition

Pretty much subj:

/home/ixti/.gem/ruby/2.3.3/gems/dry-validation-0.10.3/lib/dry/validation/message_compiler.rb:13: warning: already initialized constant Dry::Validation::MessageCompiler::EMPTY_OPTS
/home/ixti/.gem/ruby/2.3.3/gems/dry-core-0.2.1/lib/dry/core/constants.rb:52: warning: previous definition of EMPTY_OPTS was here

Not a greatest issue, but still would be nice to get rid of those ;))

[BUG] Uninitialized constant error for IDENTITY/Undefined

Describe the bug

Uninitialized constant error for IDENTITY/Undefined due using short namespaces.

NameError:
  uninitialized constant Dry::Core::ClassAttributes::IDENTITY
        def defines(*args, type: ::Object, coerce: IDENTITY) # rubocop:disable Metrics/PerceivedComplexity

To Reproduce

This issue appear in my project after dry-system version has been bumped from 0.25.0 to 0.26.0 (dry-core has been bumped from 0.8.1 to 0.9.0).

Expected behavior

No errors here :)

My environment

  • Affects my production application: YES
  • Ruby version: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin20]
  • Bundler version: 2.3.23
  • dry-core version: 0.9.0

PR

PR with fix this issue: #72

Memoization is slow

Describe the bug

https://www.reddit.com/r/ruby/comments/olksxg/optimizing_performance_in_memowise_a_new/h5fex06/?context=3
panorama-ed/memo_wise#189

I suppose we can steal something from memo_wise and make memoization faster (hey, they have the same license).
I'm planning to read their code and probably make a PR or two here, but time is scarce these days, so not sure when/if it will happen 😿

To Reproduce

Clone PR above, run benchmarks.

Expected behavior

dry-core is faster, of course.

My environment

  • Affects my production application: kinda?
  • Ruby version: 3.0.2
  • OS: linux x86_64

Dry::Core::Inflector loads ActiveSupport::Inflector

I'm adding Skylight.io to a Hanami app. It uses stuff from ActiveSupport, but they avoid using Core Extensions (monkey patches). So, ActiveSupport is available, but the Inflector isn't used for the normal application. (It is used for their CLI, but that's not being loaded here.)

The trouble is that, when Hanami uses a repository, it calls Dry::Core::Inflector.camelize(name) through ROM.

By itself, this should be fine, but Dry::Core::Inflector attempts to load 3 different back-end engines, in this order: ActiveSupport::Inflector, Dry::Inflector, Inflecto.

It first tries to require ActiveSupport::Inflector, which in this case succeeds, since activesupport is loaded. But, I don't actually want to load that :)

One way I was able to fix this was to change the order so dry-inflector is first, and add that to my Gemfile. This solves my problem, but I don't think we should be loading ActiveSupport::Inflector automatically. Some people use ActiveSupport without monkey patching, and we should encourage that. Maybe we could leverage it if it's already loaded, but not require it automatically here?

Related:

Happy to open a PR for this, just want to get everyone's thoughts before I move forward. I know this is an issue with ROM 3, since ROM 4 uses rom-support's Inflector, which is actually the apparent predecessor to the dry-core version I'm talking about now.

v1.0.1 Removes support for Ruby 2.7, breaking existing installations

Describe the bug

Version 1.0.1 removes support for Ruby 2.7. This is a breaking change that affects anyone running Ruby v2.7 and has this listed as a dependency.

To Reproduce

N/A

Expected behavior

The removal of support for a Ruby version should be done as a major version change. This would avoid inadvertent breaking changes when making patch updates.

My environment

  • Affects my production application: YES
  • Ruby version: 2.7
  • OS: N/A

Dry::Core::Memoizable regression in 0.8.0

Describe the bug

When we upgraded from dry-core 0.7.1 to 0.8.0, some tests in our test suite started failing. I think this commit (d2a8d24) changes what memoized value gets returned when a subclass inherits from a class where the memoization was defined.

To Reproduce

require "dry/core/memoizable"

class Base
  include Dry::Core::Memoizable

  def all
    [:base]
  end

  def page
    all + [:page]
  end

  memoize :all, :page
end

class Child < Base
  def all
    super + [:search]
  end
end

child = Child.new
pp all: child.all, page: child.page

__END__

Dry::Core 0.7.1

{:all=>[:base, :search],
 :page=>[:base, :search, :page]}

Dry::Core 0.8.0

{:all=>[:base, :search],
 :page=>[:base, :page]}
# Missing :search

Expected behavior

In our app, this is chaining ActiveRecord Relation objects, in this test case I've simulated it with an Array.

In dry-core 0.7.1, the #page method on Child uses its own memoized #all method, but in 0.8.0 it seems to have used Base#all instead, so its missing the :search it added.

My environment

  • Affects my production application: YES
  • Ruby version: 3.0.4
  • OS: Linux + MacOS

Add core/constants

So, we use common constants extensively in many projects, it'd be reasonable to gather them here. I'm talking about stuff like EMPTY_HASH, EMPTY_ARRAY or more "exotic" like Undefined etc.

uninitialized constant Dry::Core::ClassAttributes::IDENTITY

Describe the bug

Release 0.9.0 is broken. Because of the removal of the Constants:
v0.8.1...v0.9.0#diff-96814e9c79807ef64d126407350ffd3011e57aa5406c0625219fda5c6b1c8774L12

Causes error:

/usr/local/bundle/gems/dry-core-0.9.0/lib/dry/core/class_attributes.rb:65:in `defines': uninitialized constant Dry::Core::ClassAttributes::IDENTITY (NameError)

Because of the reference to the constant here:
v0.8.1...v0.9.0#diff-96814e9c79807ef64d126407350ffd3011e57aa5406c0625219fda5c6b1c8774R65

References
https://github.com/dry-rb/dry-core/blob/v0.9.0/lib/dry/core/constants.rb#L30

Expected behavior

Not to get an unexpected constant missing error

My environment

  • Affects my production application: YES
  • Ruby version: 2.7
  • OS: linux, alpine

The dry-logger raises an exception

Describe the bug

The dry-logger raises an exception while trying to warn about something

To Reproduce

class TestLogger
  extend Dry::Initializer  
  option :array, Types::Strict::Array.default([])  
end

in this example Logger should inform about freezing the default value

The problem could be solved if we update the Logger.new in this line
from Logger.new(output) to Logger.new(stream: output)

Expected behavior

Warning should be visible in the log and no exception should be raised

My environment

  • Affects my production application: did not test on production
  • Ruby version: 3.2.2p53
  • OS: Linux Mint 21.1 Vera \n \l
  • dry-logger (1.0.3)
  • dry-core (1.0.1)

Constant being resolved as anonymous class

Hello!

I have a Rails application which has some unusual behaviour when paired with dry-core.

Here's the branch that replicates the issue. If you clone down this app with this branch and run:

bundle install
DISABLE_SPRING=1 rails runner projects.rb

Then you will see the issue that I am facing. It's a two-parter:

  1. The class of instance that is returned by repo.all.first should be a Projects::Project, and it is... but it's seemingly coming from Dry::Core::ClassBuilder, rather than the one defined in the application.
  2. The instance should respond to a to_model call, but it doesn't. This call should be inherited from ApplicationModel, by way of the Projects::Project class within the application.

So in effect, both of the last statements in projects.rb should return true if this code is working as it should.

To attempt to work around this, I've tried doing require "projects/project" in project_repository.rb, but this flips it around:

  1. It defines the class as an anonymous class.
  2. The instance does respond to a to_model call.

The source of this problem appears to be this code within ClassBuilder:

namespace.module_eval do
remove_const(name)
const_set(name, klass)
const_get(name).name if RUBY_VERSION < '2.4'
remove_const(name)
const_set(name, base)
end

In particular:

const_get(name).name if RUBY_VERSION < '2.4'

If I remove the if statement from this line and manually require the projects/project file in my ProjectRepository class, everything works correctly, at least in my application.

That line -- in its entirety -- was added in abdb106, but the reasoning for this is opaque to me. Seems to be fixing / working around some sort of Ruby bug that only existed pre-Ruby 2.4? Well, my app is using Ruby 2.5 so this line doesn't do anything.

I'm betting this is going to be down to some weird combination between dry-core and Rails' own auto-loading mumbo-jumbo. I'd just like to get an expert opinion before I go blaming Rails (again).

Deprecation warnings should default to $stderr instead of $stdout

An added deprecation warning in dry-types v0.12.0 caused a breakage in scale-factory/aws-assume-role. It has a subcommand aws-assume-role environment where it sets environment variables by writing sourcable bash to $stdout (similar to rbenv init -); but the deprecation warnings emitted by dry-types caused the output to get mangled. Writing to $stderr would have ensured that the warnings were still printed but not would not have broken the aws-assume-role environment command.

scalefactory/aws-assume-rule#15 documents some of the background.

Warning emitted on Ruby 2.7.3 when using memoize

Describe the bug

This wasn't an issue in 0.5.0, but when we upgraded to 0.6.0 we started getting lots of warnings from using #memoize on methods that take no args:

warning: Skipping set of ruby2_keywords flag for foo (method accepts keywords or method does not accept argument splat)

To Reproduce

Provide detailed steps to reproduce, an executable script would be best.

pry(main)> class MyClass
pry(main)*   include Dry::Core::Memoizable
pry(main)*   def foo; end
pry(main)*   memoize(:foo)
pry(main)* end
/home/rando/.gem/ruby/2.7.3/gems/dry-core-0.6.0/lib/dry/core/memoizable.rb:78: warning: Skipping set of ruby2_keywords flag for foo (method accepts keywords or method does not accept argument splat)
=> MyClass

Expected behavior

No warnings emitted.

My environment

  • Affects my production application: YES
  • Ruby version: 2.7.3
  • OS: Fedora 33, OSX, whatever Heroku is running
  • Dry::Core 0.6.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.