sjmog / ralyxa

A Ruby framework for interacting with Amazon Alexa.
MIT License
180 stars 24 forks source link

Add Ruby 3 compatibility #21

Open magic4dev opened 8 months ago

magic4dev commented 8 months ago

What?

I've added support for ruby 3. It includes RSpec tests for all modified files.

Why?

I've used this gem for a variety of rails projects with Ruby version <= 2.7 and it works like a charm. The problem occurs with a Ruby version >= 3. In this case, when Ralyxa::Skill.handle(request) is invoked in a controller action, an ArgumentError: wrong number of arguments (given 1, expected 0 ) is raised. This is typical behavior after Ruby 3's decision to separate positional and keyword arguments. This decision can be found in this helpful ruby-lang article: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/

How?

For complete Ruby 3 support, I created a module called Ralyxa::RubyVersionManager that is automatically included in the Ralyxa::ResponseBuilder and Ralyxa::Handler classes (these two classes are affected by the big changes in Ruby 3). After being included, this module makes available a helper method called _"manage_ruby_versionfor" which takes 3 arguments:

  1. the class where full support between Ruby 2 and Ruby 3 is required
  2. the method to execute for this class
  3. the data (in this case the hash to be returned to the Amazon server for a voice response).

This method is smart enough to detect which version of Ruby is installed on the system and dynamically handle the incompatibility between Ruby 2 and 3 without any ArgumentError.

All the Ralyxa::RubyVersionManager technical details can be founded in _/lib/ralyxa/ruby_versionmanager.rb.

An example of the Ralyxa::RubyVersionManager's _manage_ruby_versionfor method can be found in lib/ralyxa/handler.rb at line 23. Instead of _responsebuilder.build(options) run _manage_ruby_version_for(responsebuilder, method: :build, data: options).

Testing?

I've write all RSpec tests for the Ralyxa::RubyVersionManager and updade all previous Ralyxa tests for the complete compatibility between ruby 2 and 3. Feel free to modifiy each test file if necessary.

Anything Else?

I also added a #locale method to the Ralyxa::ResponseEntities::Request class and documented it in the README.md file. As described in the README, this method returns the local value from the Amazon request. The idea of ​​introducing this method can be found in this discussion on StackOverflow: https://stackoverflow.com/questions/59913122/extending-a-ralyxa-to-manage-different-locales-and-directives

As in the previous testing section, feel free to suggest any changes.

All the best! magic4dev