fxn / zeitwerk

Efficient and thread-safe code loader for Ruby
MIT License
1.98k stars 118 forks source link

Acronyms #86

Closed mrrooijen closed 5 years ago

mrrooijen commented 5 years ago

What's the recommended way to define classes/modules that contain (or are entirely) acronyms?

For example (form 1):

lib/http.rb => Http
lib/smtp.rb => Smtp
lib/uri.rb  => Uri

This works, but in stdlib such names are defined as HTTP, SMTP and URI. This style guide also recommends keeping acronyms uppercase.

For example (form 2):

lib/h_t_t_p.rb => HTTP
lib/s_m_t_p.rb => SMTP
lib/u_r_i.rb   => URI

This also works, but the file names now look quite unusual.

What is the recommended way to deal with this?

Thanks!

casperisfine commented 5 years ago

If you are using Zeitwerk in a Rails app, it uses ActiveSupport inflection framework, so you can define the acronyms:

>> 'http'.camelize
=> "Http"
>> ActiveSupport::Inflector.inflections { |i| i.acronym('HTTP') }
=> /(?:(?<=([A-Za-z\d]))|\b)((?-mix:CCMenu|HTTP))(?=\b|[^a-z])/
>> 'http'.camelize
=> "HTTP"

However the big downside is that this is a global setting, and it might conflict with other parts of your code base.

Alternatively (or if you are outside of a Rails app) you can define a custom Zeitwerk inflector that knows about the special cases, see: https://github.com/fxn/zeitwerk#custom-inflector

mrrooijen commented 5 years ago

Thanks for the quick response.

Sticking to form 1 or 2 would be the least error-prone and most consistent approach. Perhaps it isn't such a bad trade-off to go with form 2. The file name might look unusual, but at least you get to use acronyms without inflection, know it'll work, and won't have any potential side effects throughout the rest of the system.

casperisfine commented 5 years ago

In the end it's really up to you. I was just pointing the third option.

mrrooijen commented 5 years ago

Yep. Thanks for your input. I'll go ahead and close the issue.

fxn commented 5 years ago

Let me emphasize that a custom inflector does not affect or can be affected. It is independent, and it would me more idiomatic than the weird filename (but fine if you like it of course).

You have a global effect only if you use Zeitwerk in Rails AND you define an acronym in Active Support.

mrrooijen commented 5 years ago

What would the idiomatic approach be in Rails to add a few acronyms in that case? I watched your talk on Zeitwerk which mentions the use of ActiveSupport to add acronyms in a Rails environment. I tried that out it and appears to work. However, in the event that adding an acronym to ActiveSupport isn't viable due to a conflict, would you be able to define a custom Zeitwerk Inflector in Rails and use that instead, purely for loading purposes? How would you go about doing that in a Rails environment?

fxn commented 5 years ago

@mrrooijen yes, you can do that. The released guide does not explain how yet, but we have it now in the edge one. That section will be in the stable docs with 6.0.1.

In particular, you are probably interested in the third example.

mrrooijen commented 5 years ago

@fxn yep, that's exactly what I'm looking for. Thanks a lot!

casperisfine commented 5 years ago

@fxn this makes me wonder wether the default Zeitwerk inflector should allow to register acronyms (not the full AS acronym API, but a simplified inflector.register_acronym('http', 'HTTP')).

Even for Rails users it would be convenient to be able to register these exceptions without impacting the global inflection framework.

fxn commented 5 years ago

I am a bit reluctant. Let me say why.

The default inflector is a one-liner, it is fast, it is predictable, easy to understand, and does the job. I like this code to be extremely simple. That sends also a message of determinism and that future versions of the gem won't introduce strange edge-cases in any way.

On the other hand, I believe in practice acronyms are not so common. A typical app may have just a handful, and probably not repeated a hundred times. So a custom inflector with a small case statement or small hash table is easy to write and can handle that.

Finally, if you really have HTML present in 15 files, you can still write a regexp.

Prefer to keep it that way.