-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass previous and current state to the callback #31
base: master
Are you sure you want to change the base?
Changes from 1 commit
957aaf2
38ee5d1
c1e50f0
1a4bb71
b77fa37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,11 @@ def initialize(initial_state) | |
end | ||
|
||
def on(key, &block) | ||
if block.arity > 3 | ||
raise ArgumentError, | ||
"Callback for #{key} have #{block.arity} arguments, but only 3 allowed" | ||
end | ||
|
||
@callbacks[key] << block | ||
end | ||
|
||
|
@@ -44,9 +49,21 @@ def states | |
private | ||
|
||
def change(event) | ||
@state = transitions_for[event][@state] | ||
previous_state, @state = @state, transitions_for[event][@state] | ||
|
||
all_arguments = [event, previous_state, state] | ||
|
||
callbacks = @callbacks[@state] + @callbacks[:any] | ||
callbacks.each { |callback| callback.call(event) } | ||
callbacks.each do |callback| | ||
case callback.arity | ||
when -1 | ||
callback.call(*all_arguments) | ||
when 0..3 | ||
arguments = all_arguments.take(callback.arity) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the temporary variable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep. To reduce the number of array allocations during the Alternative is to expand the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah; I’d done exactly that for #27 (increased branching). You’re guaranteeing at least There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I'm thinking is if the feature could be solved by the application using this library by keeping the value of the previous state. The impression I have is that the use case is not very common, but of course I may be wrong! In any case, if the application side can solve it, maybe that's a good start and we can communicate that use case in the documentation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I was looking at this, @soveran, is that one couldn’t necessarily count on it being solvable in the application. If you are injecting micromachine in a Sequel model, you have That said, I think I was able to work around the problem…but it left me somewhat unsatisfied. Note that both #27 and this PR fix the problem I described in #26 in that the callback mechanism was broken for folks who upgraded. |
||
callback.call(*arguments) | ||
end | ||
end | ||
|
||
true | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn’t this be
@state
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope.
There interface to access the state:
state
method. Direct reads from the internal state representation are breaking encapsulation. Should the@state
representation change, for example, to hold integer values internally, it will break code that reads ivars directly.Speaking from the SOLID point of view, there too much responsibilities on the
change
method. Because not it only changes the state, but also notifies callbacks. Ideally, callback notification code should be extracted to the, um,notify
method.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm. I tend to be very skeptical of claims of SOLID in the way that I’m also skeptical of claims of POLS for Ruby.
I can buy your argument for a
notify
method that must be triggered bychange
…and that means you have to basically callnotify(event, previous_state, state)
).Your argument for the
state
reader means that the assignment at the top should beprevious_state, @state = state, transitions_for[event][state]
. I’m not sure there’s much increase in readability or reliability becausestate
is just anattr_reader
. IMO, direct access to an instance variable is exactly what aprivate
method likechange
should be allowed and expected to do.It doesn’t much matter to me, in the end, but there’s an inconsistency in use here.