Hello community, here is the log from the commit of package rubygem-zeitwerk for openSUSE:Factory checked in at 2019-12-14 12:21:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-zeitwerk (Old) and /work/SRC/openSUSE:Factory/.rubygem-zeitwerk.new.4691 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-zeitwerk" Sat Dec 14 12:21:45 2019 rev:3 rq:756943 version:2.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-zeitwerk/rubygem-zeitwerk.changes 2019-11-13 13:25:23.899514628 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-zeitwerk.new.4691/rubygem-zeitwerk.changes 2019-12-14 12:23:58.519193924 +0100 @@ -1,0 +2,7 @@ +Sat Dec 14 00:32:05 UTC 2019 - Manuel Schnitzer <mschnit...@suse.com> + +- updated to version 2.2.2 + + * `Zeitwerk::NameError#name` has the name of the missing constant now. + +------------------------------------------------------------------- Old: ---- zeitwerk-2.2.1.gem New: ---- zeitwerk-2.2.2.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-zeitwerk.spec ++++++ --- /var/tmp/diff_new_pack.j8tKPW/_old 2019-12-14 12:23:59.011193850 +0100 +++ /var/tmp/diff_new_pack.j8tKPW/_new 2019-12-14 12:23:59.011193850 +0100 @@ -24,7 +24,7 @@ # Name: rubygem-zeitwerk -Version: 2.2.1 +Version: 2.2.2 Release: 0 %define mod_name zeitwerk %define mod_full_name %{mod_name}-%{version} ++++++ zeitwerk-2.2.1.gem -> zeitwerk-2.2.2.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.md new/README.md --- old/README.md 2019-11-01 12:53:07.000000000 +0100 +++ new/README.md 2019-11-29 17:02:42.000000000 +0100 @@ -15,8 +15,9 @@ - [Nested root directories](#nested-root-directories) - [Usage](#usage) - [Setup](#setup) - - [Reloading](#reloading) + - [Autoloading](#autoloading) - [Eager loading](#eager-loading) + - [Reloading](#reloading) - [Inflection](#inflection) - [Zeitwerk::Inflector](#zeitwerkinflector) - [Zeitwerk::GemInflector](#zeitwerkgeminflector) @@ -219,33 +220,28 @@ Zeitwerk works internally only with absolute paths to avoid costly file searches in `$LOAD_PATH`. Indeed, the root directories do not even need to belong to `$LOAD_PATH`, everything just works by design if they don't. -<a id="markdown-reloading" name="reloading"></a> -### Reloading +<a id="markdown-autoloading" name="autoloading"></a> +### Autoloading -Zeitwerk is able to reload code, but you need to enable this feature: +After `setup`, you are able to reference classes and modules from the project without issuing `require` calls for them. They are all available everywhere, autoloading loads them on demand. This works even if the reference to the class or module is first hit in client code, outside your project. -```ruby -loader = Zeitwerk::Loader.new -loader.push_dir(...) -loader.enable_reloading # you need to opt-in before setup -loader.setup -... -loader.reload -``` - -There is no way to undo this, either you want to reload or you don't. +Let's revisit the example above: -Enabling reloading after setup raises `Zeitwerk::Error`. Similarly, calling `reload` without having enabled reloading also raises `Zeitwerk::Error`. - -Generally speaking, reloading is useful while developing running services like web applications. Gems that implement regular libraries, so to speak, or services running in testing or production environments, won't normally have a use case for reloading. If reloading is not enabled, Zeitwerk is able to use less memory. +```ruby +# lib/my_gem.rb (main file) -Reloading removes the currently loaded classes and modules and resets the loader so that it will pick whatever is in the file system now. +require "zeitwerk" +loader = Zeitwerk::Loader.for_gem +loader.setup -It is important to highlight that this is an instance method. Don't worry about project dependencies managed by Zeitwerk, their loaders are independent. +module MyGem + include MyLogger # (*) +end +``` -In order for reloading to be thread-safe, you need to implement some coordination. For example, a web framework that serves each request with its own thread may have a globally accessible RW lock. When a request comes in, the framework acquires the lock for reading at the beginning, and the code in the framework that calls `loader.reload` needs to acquire the lock for writing. +That works, and there is no `require "my_gem/my_logger"`. When `(*)` is reached, Zeitwerk seamlessly autoloads `MyGem::MyLogger`. -On reloading, client code has to update anything that would otherwise be storing a stale object. For example, if the routing layer of a web framework stores controller class objects or instances in internal structures, on reload it has to refresh them somehow, possibly reevaluating routes. +If autoloading a file does not define the expected class or module, Zeitwerk raises `Zeitwerk::NameError`, which is a subclass of `NameError`. <a id="markdown-eager-loading" name="eager-loading"></a> ### Eager loading @@ -269,6 +265,8 @@ Eager loading is synchronized and idempotent. +If eager loading a file does not define the expected class or module, Zeitwerk raises `Zeitwerk::NameError`, which is a subclass of `NameError`. + If you want to eager load yourself and all dependencies using Zeitwerk, you can broadcast the `eager_load` call to all instances: ```ruby @@ -279,6 +277,34 @@ Note that thanks to idempotence `Zeitwerk::Loader.eager_load_all` won't eager load twice if any of the instances already eager loaded. +<a id="markdown-reloading" name="reloading"></a> +### Reloading + +Zeitwerk is able to reload code, but you need to enable this feature: + +```ruby +loader = Zeitwerk::Loader.new +loader.push_dir(...) +loader.enable_reloading # you need to opt-in before setup +loader.setup +... +loader.reload +``` + +There is no way to undo this, either you want to reload or you don't. + +Enabling reloading after setup raises `Zeitwerk::Error`. Attempting to reload without having it enabled raises `Zeitwerk::ReloadingDisabledError`. + +Generally speaking, reloading is useful while developing running services like web applications. Gems that implement regular libraries, so to speak, or services running in testing or production environments, won't normally have a use case for reloading. If reloading is not enabled, Zeitwerk is able to use less memory. + +Reloading removes the currently loaded classes and modules and resets the loader so that it will pick whatever is in the file system now. + +It is important to highlight that this is an instance method. Don't worry about project dependencies managed by Zeitwerk, their loaders are independent. + +In order for reloading to be thread-safe, you need to implement some coordination. For example, a web framework that serves each request with its own thread may have a globally accessible RW lock. When a request comes in, the framework acquires the lock for reading at the beginning, and the code in the framework that calls `loader.reload` needs to acquire the lock for writing. + +On reloading, client code has to update anything that would otherwise be storing a stale object. For example, if the routing layer of a web framework stores controller class objects or instances in internal structures, on reload it has to refresh them somehow, possibly reevaluating routes. + <a id="markdown-inflection" name="inflection"></a> ### Inflection Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zeitwerk/loader/callbacks.rb new/lib/zeitwerk/loader/callbacks.rb --- old/lib/zeitwerk/loader/callbacks.rb 2019-11-01 12:53:07.000000000 +0100 +++ new/lib/zeitwerk/loader/callbacks.rb 2019-11-29 17:02:42.000000000 +0100 @@ -14,7 +14,7 @@ if logger && cdef?(*cref) log("constant #{cpath(*cref)} loaded from file #{file}") elsif !cdef?(*cref) - raise Zeitwerk::NameError, "expected file #{file} to define constant #{cpath(*cref)}, but didn't" + raise Zeitwerk::NameError.new("expected file #{file} to define constant #{cpath(*cref)}, but didn't", cref.last) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zeitwerk/loader.rb new/lib/zeitwerk/loader.rb --- old/lib/zeitwerk/loader.rb 2019-11-01 12:53:07.000000000 +0100 +++ new/lib/zeitwerk/loader.rb 2019-11-29 17:02:42.000000000 +0100 @@ -494,7 +494,7 @@ rescue ::NameError => error path_type = ruby?(abspath) ? "file" : "directory" - raise NameError, <<~MESSAGE + raise NameError.new(<<~MESSAGE, error.name) #{error.message} inferred by #{inflector.class} from #{path_type} #{abspath} @@ -558,7 +558,7 @@ end # @param dir [String] directory that would have autovivified a module - # @param file [String] the file where the namespace is explictly defined + # @param file [String] the file where the namespace is explicitly defined # @param parent [Module] # @param cname [Symbol] # @return [void] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zeitwerk/version.rb new/lib/zeitwerk/version.rb --- old/lib/zeitwerk/version.rb 2019-11-01 12:53:07.000000000 +0100 +++ new/lib/zeitwerk/version.rb 2019-11-29 17:02:42.000000000 +0100 @@ -1,5 +1,5 @@ # frozen_string_literal: true module Zeitwerk - VERSION = "2.2.1" + VERSION = "2.2.2" end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2019-11-01 12:53:07.000000000 +0100 +++ new/metadata 2019-11-29 17:02:42.000000000 +0100 @@ -1,14 +1,14 @@ --- !ruby/object:Gem::Specification name: zeitwerk version: !ruby/object:Gem::Version - version: 2.2.1 + version: 2.2.2 platform: ruby authors: - Xavier Noria autorequire: bindir: bin cert_chain: [] -date: 2019-11-01 00:00:00.000000000 Z +date: 2019-11-29 00:00:00.000000000 Z dependencies: [] description: |2 Zeitwerk implements constant autoloading with Ruby semantics. Each gem