Comments (11)
Thanks a lot for explain, i will use this gem several days, and switch all my service from interactor to it.
If still have question, i will discuss here.
Thank you.
from actor.
For #2 you could accept several types and override the handler method to transform into an integer:
It works!
input :stock_id, type: Integer, allow_nil: false
This way raise error when user not pass :stock_id in.
ServiceActor::ArgumentError: Input insider_id on RetrieveInsiderHistory is missing
so, the only way is use default: nil
, and business logic is decide use if :stock_id
inside service object.
from actor.
Hi @zw963!
In Actor, the defaults are just like the default keyword values in Ruby. E.g.:
def serve_dish(name: "fries")
puts "Enjoy your #{name.inspect}"
end
serve_dish
# => Enjoy your "fries"
serve_dish(name: nil)
# => Enjoy your nil
Acts the same way as:
class ServeDish < Actor
input :name, default: "fries"
def call
puts "Enjoy your #{name.inspect}"
end
end
ServeDish.()
# => Enjoy your "fries"
ServeDish.(name: nil)
# => Enjoy your nil
In cases like these using compact
before passing nil
argument works well, like you did.
If you’d like to treat nil
as being the default, I guess you could also do this like so:
class ServeDish < Actor
input :name, default: nil
def call
puts "Enjoy your #{name.inspect}"
end
def name
result.name.nil? ? "fries" : result.name
end
end
ServeDish.()
# => Enjoy your "fries"
ServeDish.(name: nil)
# => Enjoy your "fries"
But your solution with slice
seems much better in that case!
from actor.
Thank you for excellent explain.
But, my slice solution exists another issue.
Let's us said we have a service like this, stock_name
is not always exists.
class RetrieveStocks < Actor
input :sort_column, default: 'next_earnings_date'
input :sort_direction, default: 'asc'
input :page, default: '1'
input :per, default: '20'
input :stock_name
def call
# ...
end
end
Assume invoke this service like this:
RetriveStocks.call, it will raise error because
stock_name
no default value.
But, for my service logic, if no stock_name
provided, it should not
search base on stock_name instead, the only solution is, give nil as default value,
class RetrieveStocks < Actor
input :sort_column, default: 'next_earnings_date'
input :sort_direction, default: 'asc'
input :page, default: '1'
input :per, default: '20'
input :stock_name, default: nil
def call
# ...
end
end
But, this means, all input 'MUST' have default value, so, here is a choice dilemma ...
if pass in all, will meet passed in nil issue.
if not pass in(as use slice), have to add default: option to all input ...
from actor.
To disallow nil
you can actually use the allow_nil
option or even the type
option. For example:
class RetrieveStocks < Actor
input :stock_name, default: nil, allow_nil: false
input :sort_column, default: 'next_earnings_date', type: 'String'
def call
puts "Stock name: #{stock_name}, Sort: #{sort_column}"
end
end
RetrieveStocks.call
# => ServiceActor::ArgumentError: The input "stock_name" on RetrieveStocks does not allow nil values
RetrieveStocks.call(stock_name: nil)
# => ServiceActor::ArgumentError: The input "stock_name" on RetrieveStocks does not allow nil values
RetrieveStocks.call(stock_name: "Apple", sort_column: nil)
# => ServiceActor::ArgumentError: The input "sort_column" on RetrieveStocks does not allow nil values
RetrieveStocks.call(stock_name: "Apple")
# => Stock name: Apple, Sort: next_earnings_date
from actor.
After switch to several of my service to actor, following is some note:
- When i invoke service from roda router, i can use like following directly. (no need slice or compact)
result = RetrieveInsiderHistory.call(r.params)
because it seem like actor can assure if one arg not statement use input, it not accessable in service object.
and r.params never return return value as nil
- most of my input can not specify type, because those args come from params, as following:
class RetrieveInsiderHistory < Actor
input :days, default: '7'
input :sort_column, default: 'date'
input :sort_direction, default: 'desc'
input :stock_name, default: nil
input :stock_id, default: nil, type: Integer
input :insider_id, default: nil, type: Integer
in fact, days
should be a integer, but i have to use string instead, because, if specify type: Integer for days
, i have to handle it
before pass to it., like this:
days = r.params['days']
if days.present?
days = days.to_i
else
days = 7
end
result = RetrieveInsiderHistory.call(days: days)
that not good, because i have to write dirty logic outside service object for make type: Integer can pass.
I really should write those logic in service object instead,
e.g if we have a handler option:
```rb
input :days, handler: -> { if _1.present? ? _1.to_i : 7 }
- i have to specify default option for all my input, even, as following case
input :stock_id, default: nil, type: Integer
I have to specify default: nil
+ type: integer
for my logic still work.
because if for cases user not passed in :stock_id in params, i need avoid raise error, and use nil in service for determinate.
Anyway, i don't know if i misunderstood or misusage somethings, it a little strange ...
from actor.
For #2 you could accept several types and override the handler method to transform into an integer:
class RetrieveInsiderHistory < Actor
input :days, default: 7, type: [Integer, String]
def call
puts "#{days.inspect} days"
end
private
def days
result.days.to_i
end
end
RetrieveInsiderHistory.call
# => "7 days"
RetrieveInsiderHistory.call(days: 99)
RetrieveInsiderHistory.call(days: "99")
# => "99 days"
For #3 it’s because when you are asking for a specific type it assumes you want this type and don’t want nils. So you could write it any of these two ways:
input :stock_id, type: Integer, default: nil
# or
input :stock_id, type: Integer, allow_nil: false
from actor.
I switch all my service to use actor now.
Finally, i add all my input with type
and default
option,like this
class RetrieveInsiderHistory < Actor
input :days, default: 7, type: [Integer, String]
input :sort_column, default: 'date', type: String
input :sort_direction, default: 'desc', type: String
input :stock_name, default: nil, type: String
input :stock_id, default: nil, type: Integer
input :insider_id, default: nil, type: Integer
# ...
end
a little tediously, but, anyway, it useful, and more clear for find out what service object accepted.
There still a issue, when i run test, get many warn message like this:
/home/zw963/Stocks/marketbet_crawler/app/services/retrieve_insider_history.rb:97: warning: method redefined; discarding old days
/home/zw963/others/.rvm/gems/ruby-3.0.2@marketbet_crawler/gems/service_actor-3.1.2/lib/service_actor/attributable.rb:26: warning: previous definition of days was here
If this gem want user override exists same name method this way, it should do some hack for avoid produce those warning.
the offical recommand way for this is to add a alias. as following code, (i copy from sequel gem).
you can check discuss here.
https://groups.google.com/g/sequel-talk/c/fwa1Pwye_CY/m/DANKiBGOBQAJ
from actor.
Another issue, please check following example.
# i assign result.institutions = ??? in this service.
result = RetrieveInstitutions.result(params)
if result.success?
@institutions = result.institutions1 # But i never defined this method in above service, but when invoke it, not raise any error, just return nil, this is not acceptable?
end
Above result.institutions1 return nil, which make result.success? almost no any means for this case.
from actor.
If this gem want user override exists same name method this way, it should do some hack for avoid produce those warning.
Thank for the link, didn’t know about that hack! I’d be happy to accept a patch with a test that could remove this warning.
But when invoke it, not raise any error, just return nil
Indeed, that is a side effect of using an OpenStruct to store the set of results. I’d be happy for a patch that would raise an error in that case.
from actor.
let us discuss another issue in new issue.
from actor.
Related Issues (20)
- Raise an error if the :message option is missing on checks HOT 9
- Feature request: use other input values in default HOT 4
- alias_input is documented but unavailable HOT 1
- What about improving the README about testing? HOT 1
- Get "TypeError: exception class/object expected" error when update from 3.1.3 to 3.6 HOT 2
- Question / feature request: hooks around call? HOT 6
- Invoking undefined methods on a result does not raise errors HOT 3
- Ruby 2.3 HOT 3
- Schema explorer HOT 2
- [Feature][Solution included] Allows boolean outputs to have `result.boolean?` accessors instead of `result.boolean` HOT 10
- Evaluate conditions only once HOT 1
- Feature: Promptable HOT 5
- Old bundler & deprecation warnings
- Dependency injection HOT 2
- Play symbols HOT 4
- [This is not an issue per se, rather a question] How to pass in positional arguments, and no keyword arguments? HOT 3
- Problem with `zeitwerk` after update to version 3.4.0 HOT 4
- Validating params or attributes HOT 4
- Problems between checks within the same `input` HOT 8
- warning: method redefined; discarding old orig_name= HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from actor.