nebulab / simple_command Goto Github PK
View Code? Open in Web Editor NEWA simple, standardized way to build and use Service Objects (aka Commands) in Ruby
Home Page: http://nebulab.it
License: MIT License
A simple, standardized way to build and use Service Objects (aka Commands) in Ruby
Home Page: http://nebulab.it
License: MIT License
class ExampleCommand
prepend SimpleCommand
def initialize(foo:)
@foo = foo
end
def call
@foo
end
end
irb(main):010:0> ExampleCommand.call(foo: "bar")
/usr/local/bundle/gems/simple_command-0.1.0/lib/simple_command.rb:9: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
(irb):3: warning: The called method `initialize' is defined here
=> #<ExampleCommand:0x0000560f7af7f988 @foo="bar", @called=true, @result="bar">
The issue is describe here: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
The warning is in 2.7 and will error in 3.0
before do
allow_any_instance_of(Class).to receive(:call).and_return(double)
end
Failure/Error: allow_any_instance_of(Class).to receive(:call).and_return(double)
Using any_instance
to stub a method (call) that has been defined on a prepended module (SimpleCommand) is not supported.
I have written a couple of commands using this amazing gem, I wonder what is the best approach to test them with rspec.
Hello! I noticed your build badge reads 'failing' so I forked the repo and ran the specs on my machine, but they all pass.
Might be something to look into.
Thanks :)
When getting errors from an ActiveRecord, full_messages returns an array of joined set of key/value for the errors.
I will submit a PR for this if you are open to it. Thanks for a great gem.
I'm not sure if this is a real issue but I'm getting an error trying to use this method.
According to the spec here
irb(main):012:0> errors = SimpleCommand::Errors.new
=> {}
irb(main):013:0> errors.add(:foo, 'wha')
=> nil
irb(main):014:0> errors
=> {:foo=>["wha"]}
irb(main):015:0> errors.full_messages
Traceback (most recent call last):
1: from (irb):15
NoMethodError (undefined method `full_messages' for {:foo=>["wha"]}:SimpleCommand::Errors)
Hi, I'm using SimpleCommand in a Rails app with an Angular 7 front end. It all works beautifully and the auth is smooth and great.
I'm doing a very simple implementation similar to the one you have here in Github example.
My question is: how do I adjust the expiration date of the token ? It seems to default to 24 hours ( I think )
Let me know if you can, or point me in the right direction... thanks !
After update to v0.1.0
from v0.0.9
tests started to fail with
expect(
get_users(page: '-2')
).to eq(errors: { page: ["must be a positive number"] })
expected: {:errors=>{:page=>["must be a positive number"]}}
got: {:errors=>{:page=>"must be a positive number"}}
In the controller errors are rendered the following way:
load_users = LoadUsers.(params)
if load_users.success?
render json: load_users.result
else
render json: { errors: load_users.errors }
end
The problem is that SimpleCommand::Errors#to_json
format differs from ActiveModel::Errors#to_json
# SimpleCommand::Errors
load_users = LoadUsers.new
load_users.errors.add(:page, 'must be a positive number')
load_users.errors.add(:page, 'cannot be blank')
load_users.errors.as_json
=> {"page"=>"cannot be blank"}
# ActiveModel::Errors
user = User.new
user.errors.add(:email, 'is invalid')
user.errors.add(:email, 'cannot be blank')
user.errors.as_json
=> {:email=>["is invalid", "cannot be blank"]}
It would be good to have SimpleCommand::Errors#as_json
to be the same format as ActiveModel::Errors#as_json
I followed this tutorial.
But it looks like my command is not "autoloaded??"
"exception":"#<NameError: uninitialized constant Api::V1::AuthenticationController::AuthenticateUser>"
These are my files
module Api
module V1
class AuthenticationController < ApplicationController
skip_before_action :authenticate_request
def authenticate
command = AuthenticateUser.call(params[:username], params[:password])
if command.success?
render json: {auth_token: command.result}
else
render json: {error: command.errors }, status: :unauthorized
end
end
end
end
end
class AuthorizeApiRequest
prepend SimpleCommand
def initialize(headers = {})
@headers = headers
end
def call
user
end
private
attr_reader :headers
def user
@user ||= User.find(decoded_auth_token[:user_id]) if decoded_auth_token
@user || errors.add(:token, 'Invalid token') && nil
end
def decoded_auth_token
@decoded_auth_token ||= JsonWebToken.decode(http_auth_header)
end
def http_auth_header
if headers['Authorization'].present?
return headers['Authorization'].split(' ').last
else
errors.add(:token, 'Missing token')
end
nil
end
end
Hi -
Do you plan on releasing a version compatible with Ruby 3, now that it's the latest stable version of Ruby?
I see that the keyword argument issue was already fixed in #28.
Thanks
Hey guys, I found that the gem was lastly released 4 years ago. Since those times there were done a lot of changes in the gem. Could you do a new release with the latest changes?
I've followed this tutorial for JSON Web Tokens and things Simple Command work beautifully until I hit the tests. In the tests the commands each time AuthorizeApiRequest
is called I get this error: LoadError: Unable to autoload constant AuthorizeApiRequest
.
# app/commands/authorize_api_request.rb
class AuthorizeApiRequest
prepend SimpleCommand
def initialize(headers = {})
@headers = headers
end
def call
user
end
private
attr_reader :headers
def user
@user ||= User.find(decoded_auth_token[:user_id]) if decoded_auth_token
@user || errors.add(:token, 'Invalid token') && nil
end
def decoded_auth_token
@decoded_auth_token ||= JsonWebToken.decode(http_auth_header)
end
def http_auth_header
if headers['Authorization'].present?
return headers['Authorization'].split(' ').last
else
errors.add(:token, 'Missing token')
end
nil
end
end
# app/controllers/admin/authenticated_controller.rb
module Admin
class AuthenticatedController < ApplicationController
prepend SimpleCommand
before_action :authenticate_request
attr_reader :current_user
private
def authenticate_request
@current_user = AuthorizeApiRequest.call(request.headers).result
render json: { error: 'Not Authorized' }, status: 401 unless @current_user
end
end
end
Am I missing something here?
Does one need to do something extra to use Simple Commands in tests?
When calling add_multiple_errors with an error hash i get NoMethodError: undefined method
each' for #String:0x00007ff1cd1a8710`
I have an error object from another command object, when i call add_multiple_errors it works with version 0.9.0 and raises a NoMethodError
error with 0.1.0:
>command.errors
:error=>["21004 The shared secret you provided does not match the shared secret on file for your account."]}
>errors.add_multiple_errors(command.errors)
NoMethodError: undefined method `each' for #<String:0x00007ff1cd1a8710>
JSON API Errors Document in AMS
I want to render the error message by using AMS jsonapi serializer.
But there is something wrong if I render a simple_command result.
I can render the errors to json but can not to jsonapi.
#simple_command
Class AuthenticateUser
*
*
errors.add :user_authentication, 'invalid credentials'
*
*
end
#controller
command = AuthenticateUser.call(params[:email], params[:password])
render json: command, status: 401, adapter: :json_api, serializer: ActiveModel::Serializer::ErrorSerializer
log:
NoMethodError (undefined method `messages' for {:user_authentication=>["invalid credentials"]}:SimpleCommand::Errors):
app/controllers/authentication_controller.rb:10:in `authenticate'
What should I do?
Add new Assistance categories:
Clothing
Other
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.