diff --git a/.travis.yml b/.travis.yml index 5190552..16d442a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,4 +46,4 @@ matrix: notifications: slack: - secure: MsPY8sUW5TVblcWc5NGkkWJlHxCMnhNa3IFPSVWthlk0fz+CLfOrLjQ+brQup/AJ7BRtyBKQ8udpqLj/R7CJKAiVVDAlUBcHqXk/WDusssGzJkDMrLVDefq++YCg5TdbcIaHt8WBVg6pD8H4kQJMJxmtcziQtiW1Qt0pwfuNJ+k= + secure: gpltVWntdKz0nSE6A5UvuX4qbN35uW51nsW+Ojgqm8Qsv8K240/NlZRYutFHr7GnJTe0rEEP2Oy3ZBnBtZKFn13RlTEAU/FCAxebr4H24rr29Ypwwp5xjiSE4MuoBEnroo4lw6ka3LsJnrY2PKRMiLJGsS0WsEPY4x8NUG/vyY8= diff --git a/CHANGELOG.md b/CHANGELOG.md index 243733c..760d574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## unreleased + + * fix: permissible states not respecting guard parameters (see [issue #388](https://github.com/aasm/aasm/issues/388)) with [pull-request #389](https://github.com/aasm/aasm/pull/389) + ## 4.11.0 * support `logger` configuration (see [issue #370](https://github.com/aasm/aasm/pull/370) for details, thanks to [@HoyaBoya](https://github.com/HoyaBoya)) @@ -329,4 +333,3 @@ * supporting i18n * supporting regular expressions for hash values and strings - diff --git a/README.md b/README.md index b85e242..cb08fca 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ class Job ... end - def notify_somebody(user) + def notify_somebody ... end @@ -418,6 +418,28 @@ SimpleMultipleExample.aasm(:work).states *Final note*: Support for multiple state machines per class is a pretty new feature (since version `4.3`), so please bear with us in case it doesn't work as expected. +### Auto-generated Status Constants + +AASM automatically [generates constants](https://github.com/aasm/aasm/pull/60) +for each status so you don't have to explicitly define them. + +```ruby +class Foo + include AASM + + aasm do + state :initialized + state :calculated + state :finalized + end +end + +> Foo::STATE_INITIALIZED +#=> :initialized +> Foo::STATE_CALCULATED +#=> :calculated +``` + ### Extending AASM AASM allows you to easily extend `AASM::Base` for your own application purposes. @@ -935,6 +957,9 @@ job.aasm.events(:reject => :sleep).map(&:name) # list states for select Job.aasm.states_for_select => [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]] + +# show permitted states with guard parameter +job.aasm.states({:permitted => true}, guard_parameter).map(&:name) ``` @@ -1055,6 +1080,7 @@ Feel free to * [Scott Barron](https://github.com/rubyist) (2006–2009, original author) * [Travis Tilley](https://github.com/ttilley) (2009–2011) * [Thorsten Böttger](http://github.com/alto) (since 2011) +* [Anil Maurya](http://github.com/anilmaurya) (since 2016) ## Contributing ## diff --git a/aasm.gemspec b/aasm.gemspec index 8dcb14f..5e49fc6 100644 --- a/aasm.gemspec +++ b/aasm.gemspec @@ -5,8 +5,8 @@ require "aasm/version" Gem::Specification.new do |s| s.name = "aasm" s.version = AASM::VERSION - s.authors = ["Scott Barron", "Travis Tilley", "Thorsten Boettger"] - s.email = %q{scott@elitists.net, ttilley@gmail.com, aasm@mt7.de} + s.authors = ["Thorsten Boettger", "Anil Maurya"] + s.email = %q{aasm@mt7.de, anilmaurya8dec@gmail.com} s.homepage = %q{https://github.com/aasm/aasm} s.summary = %q{State machine mixin for Ruby objects} s.description = %q{AASM is a continuation of the acts-as-state-machine rails plugin, built for plain Ruby objects.} diff --git a/gemfiles/rails_4.0_mongo_mapper.gemfile b/gemfiles/rails_4.0_mongo_mapper.gemfile index ab15ea2..707fd6b 100644 --- a/gemfiles/rails_4.0_mongo_mapper.gemfile +++ b/gemfiles/rails_4.0_mongo_mapper.gemfile @@ -1,7 +1,6 @@ source "https://rubygems.org" gem "sqlite3", :platforms => :ruby -gem "coveralls" gem 'rubysl', :platforms => :rbx gem 'rubinius-developer_tools', :platforms => :rbx gem "jruby-openssl", :platforms => :jruby diff --git a/gemfiles/rails_4.2_mongo_mapper.gemfile b/gemfiles/rails_4.2_mongo_mapper.gemfile index 62a8550..c113b26 100644 --- a/gemfiles/rails_4.2_mongo_mapper.gemfile +++ b/gemfiles/rails_4.2_mongo_mapper.gemfile @@ -1,7 +1,6 @@ source "https://rubygems.org" gem "sqlite3", :platforms => :ruby -gem "coveralls" gem 'rubysl', :platforms => :rbx gem 'rubinius-developer_tools', :platforms => :rbx gem "jruby-openssl", :platforms => :jruby diff --git a/lib/aasm/instance_base.rb b/lib/aasm/instance_base.rb index 63648fe..ec6b454 100644 --- a/lib/aasm/instance_base.rb +++ b/lib/aasm/instance_base.rb @@ -33,9 +33,9 @@ module AASM AASM::Localizer.new.human_state_name(@instance.class, state_object_for_name(current_state)) end - def states(options={}) + def states(options={}, *args) if options.has_key?(:permitted) - selected_events = events(:permitted => options[:permitted]) + selected_events = events({:permitted => options[:permitted]}, *args) # An array of arrays. Each inner array represents the transitions that # transition from the current state for an event event_transitions = selected_events.map {|e| e.transitions_from_state(current_state) } @@ -45,10 +45,10 @@ module AASM return nil if transitions.empty? # Return the :to state of the first transition that is allowed (or not) or nil - if options[:permitted] - transition = transitions.find { |t| t.allowed?(@instance) } + if options[:permitted] + transition = transitions.find { |t| t.allowed?(@instance, *args) } else - transition = transitions.find { |t| !t.allowed?(@instance) } + transition = transitions.find { |t| !t.allowed?(@instance, *args) } end transition ? transition.to : nil end.flatten.compact.uniq @@ -60,7 +60,7 @@ module AASM end end - def events(options={}) + def events(options={}, *args) state = options[:state] || current_state events = @instance.class.aasm(@name).events.select {|e| e.transitions_from_state?(state) } @@ -71,9 +71,9 @@ module AASM # filters the results of events_for_current_state so that only those that # are really currently possible (given transition guards) are shown. if options[:permitted] - events.select! { |e| @instance.send("may_#{e.name}?") } + events.select! { |e| @instance.send("may_#{e.name}?", *args) } else - events.select! { |e| !@instance.send("may_#{e.name}?") } + events.select! { |e| !@instance.send("may_#{e.name}?", *args) } end end diff --git a/spec/models/guard_with_params.rb b/spec/models/guard_with_params.rb new file mode 100644 index 0000000..a657bd4 --- /dev/null +++ b/spec/models/guard_with_params.rb @@ -0,0 +1,24 @@ +class GuardWithParams + include AASM + aasm do + state :new, :reviewed, :finalized + + event :mark_as_reviewed do + transitions :from => :new, :to => :reviewed, :guards => [:user_is_manager?] + end + end + + def user_is_manager?(user) + ok = false + if user.has_role? :manager + ok = true + end + return ok + end +end + +class GuardParamsClass + def has_role?(role) + true + end +end diff --git a/spec/models/guard_with_params_multiple.rb b/spec/models/guard_with_params_multiple.rb new file mode 100644 index 0000000..86532c0 --- /dev/null +++ b/spec/models/guard_with_params_multiple.rb @@ -0,0 +1,18 @@ +class GuardWithParamsMultiple + include AASM + aasm(:left) do + state :new, :reviewed, :finalized + + event :mark_as_reviewed do + transitions :from => :new, :to => :reviewed, :guards => [:user_is_manager?] + end + end + + def user_is_manager?(user) + ok = false + if user.has_role? :manager + ok = true + end + return ok + end +end diff --git a/spec/unit/guard_with_params_multiple_spec.rb b/spec/unit/guard_with_params_multiple_spec.rb new file mode 100644 index 0000000..abb7302 --- /dev/null +++ b/spec/unit/guard_with_params_multiple_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe "guards with params" do + let(:guard) { GuardWithParamsMultiple.new } + let(:user) {GuardParamsClass.new} + + it "list permitted states" do + expect(guard.aasm(:left).states({:permitted => true}, user).map(&:name)).to eql [:reviewed] + end +end diff --git a/spec/unit/guard_with_params_spec.rb b/spec/unit/guard_with_params_spec.rb new file mode 100644 index 0000000..a91b534 --- /dev/null +++ b/spec/unit/guard_with_params_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe "guards with params" do + let(:guard) { GuardWithParams.new } + let(:user) {GuardParamsClass.new} + + it "list permitted states" do + expect(guard.aasm.states({:permitted => true}, user).map(&:name)).to eql [:reviewed] + end +end