dry-rb/dry-initializer

Option "as" feature not working

dmatamoroscr opened this issue · 2 comments

Describe the bug

Using the "as" feature described in the documentation does not work and renders an error.
https://dry-rb.org/gems/dry-initializer/3.0/params-and-options/

To Reproduce
gem install dry-initializer -v=3.0.3 (also tried 3.0.0 with the same results)
running the following in IRB:

require 'dry-initializer'

class User
  extend Dry::Initializer

  option :phone
  option :telephone, as: :phone
  option :name, optional: true
end

User.new(phone: '1234567890').phone

renders:

KeyError: User: option 'telephone' is required
	from (eval):7:in `block in __dry_initializer_initialize__'
	from (eval):7:in `fetch'
	from (eval):7:in `__dry_initializer_initialize__'
	from /home/......../.rvm/gems/ruby-2.4.6@atlas/gems/dry-initializer-3.0.0/lib/dry/initializer/mixin/root.rb:7:in `initialize'
	from (irb):11:in `new'
	from (irb):11

Expected behavior

I expected the alias behavior to work and not render an error.

Your environment

  • Affects my production application: NO
  • Ruby version: 2.4.6
  • OS: Ubuntu

TL;DR: I think this behavior is expected (but I understand why that's not clear)


If I'm reading this bug report correctly, the expectation is that option :telephone, as: :phone
would allow a User to be initialized like:

User.new(phone: '1234567890')

That isn't actually the case. I personally find the renaming mechanism confusing, but the documentation would suggest initializing the object with telephone:, then calling #phone to access the value. The way to initialize this object would then be:

User.new(telephone: '1234567890')

It might be helpful to think of it like

option :initialized_with, as: :accessed_with

The other thing that I see is that :phone is being listed as an option twice. Both options are required, but are stored internally as @phone. This results in:

user = User.new(telephone: "telephone", phone: "phone")
# => #<User:0x00007fd6fc844628 @__options__={:phone=>"telephone"}, @phone="telephone">
user.phone
# => "telephone"

@landongrindheim thank you! You're right

Actually, the reason behind that :as feature was the following:

class User
  extend Dry::Initializer

  option :"my beloved pet's name", as: :pet_name
end

User.new("my beloved pet's name": "Cecily").pet_name # => "Cecily"

Without it not any hash could be mapped via this interface, or it would require some opinionated implicit convention about sanitizing.