Giter Site home page Giter Site logo

workflow's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

workflow's Issues

Does not work with Ruby 1.9

ruby -e "puts RUBY_VERSION; require 'workflow'"

1.9.1
/usr/local/lib/ruby/gems/1.9.1/gems/workflow-0.6.0/lib/workflow.rb: /usr/local/lib/ruby/gems/1.9.1/gems/workflow-0.6.0/lib/workflow.rb:182: Invalid return (SyntaxError)

Event triggers state update but not invokes method

Using workflow in an ActiveRecord model, when an event is raised the workflow state is updated, however the method model (with the same name) is not invoked.

I use RVM with ruby-1.9.2-p320 and rails 3.2.12.

My model :

class Assembly < ActiveRecord::Base
include Workflow
...
workflow do
state :fresh_aln_assembly do
event :submit_aln_transcripts_on_dataset, :transitions_to => :aln_transcripts_on_dataset
end
state :aln_transcripts_on_dataset do
event :aln_transcripts_on_dataset_check, :transitions_to => :aln_transcripts_on_dataset_checking
end
etc...
...
def aln_transcripts_on_dataset
do some stuff
end
...

Call on_*_entry before saving model

Could you modify workflow to call on_*_entry callbacks before saving ActiveRecord models? That way the callbacks can modify object state without having to call save() a second time, improving usability and performance.

Transition saves without validation

Perhaps this is intended but it's definitely not something I want in my app. Any state transition saves the object without validation because it uses update_attribute. This is true even if the object is not yet persisted.

If for example in your controller you have:

@user = User.new
@user.email = "someinvalidemail"
@user.registered!
if @user.save
..

The user will be saved with the invalid email. You will have invalid data the bug will be hard to find. This could manifest in some terribly more subtle ways if you've modified an object and then call a transition method. I prefer validation be performed, as sometimes validation could depend on state, so I'm trying out this monkey patch:

module Workflow
  module ActiveRecordInstanceMethods
    def persist_workflow_state(new_value)
      send "#{self.class.workflow_column}=".to_sym, new_value
      save!
    end
  end
end

It's probably better to return false and halt in the caller however. I was going to hack up a new version but the gemspec is not checked in and I'm not all that familiar with publishing gems, and this makes it hard to develop directly on a path with bundler.

Question: Isolating workflows to module

Great job on this -- it is working really well for me. But to my question / issue: I am trying to externalize my workflows to my lib so I can re-use them. For example, a lot of my models use a common state of new, pending, active, etc. So what I am trying to do is define a couple of common workflows that a class can mix in. In my lib, I have myco/workflows/life_cycle, for example. In that module, I have a constant for the possible states (array) and the "workflow do..." logic. But, I can't seem to get everything to pick up my method. Any suggestions or tips? I've tried doing it as instance methods, class methods, and both, and I tried creating a method to wrap the "workflow do..." in then invoking that in my class def, but no luck. FYI, when I move the logic back in to my class, it works fine. Any thoughts are appreciated, and I'm happy to contribute my library of what I think are practical, common workflows.

How to change the state manually?

I need to change the state of an object manually without triggering the state machine and any hooks. e.g. model.current_state = :closed

This is because I need to set up an initial state that can be any of the possible states.

Is this possible? How?

Thanks

Document the initial state

The README does a great job with describing Workflow but one important detail appears to be missing. How to define which state is the initial state for the object. The example of article = Article.new; article.new? => true implies that if the state is named with :new, that is the initial state. Could this be stated explicitly in the docs, and what happens if the workflow does not define a state called :new?

Updating other object's states from a event transition method

Hello,
I'm having an interesting problem:
I have a request order with many sales. I want to transit the ro (request order) to 'completed' once the sum of all the sales' items equal to the ro items.
So each time I transit a sale to 'completed', I want to invoke a transition ('sell_partially') on the ro to control if all requested items have been sold.
My issue is:
Since I'm STILL in the sale's transition to 'completed', this very sale is NOT selected when the ro method iterating over all the related sales to control if the ro should be transited to 'completed' therefore it will wrongly assess that the ro is not yet completed and the ro will never be marked as 'completed' even though it is...
I could call it from the sales controller after having transited the sale but I feel it's not its business and this logic should belong to ro...
Anybody has a similar problem or suggestion?
Thanks in advance!

Gam

PS: Is there a way of nicely add this scopes to all the classes that uses Workflow:

makes all the named scoped for each state! [don't use :new as a state, it doesn't work with this]

workflow_spec.states.keys.each do |state|
named_scope state, :conditions => ['workflow_state = ?', state.to_s]
end

Inheritance

I have some classes which are inherited, however the initial state on the parent class is not the default state on the child class.

This should be configurable or default.

class Animal < AR::Base
  include Workflow

  workflow do

    state :conceived do
      event :birth, :transition_to => :born
    end

    state :born do

    end
  end
end

class Cat < Animal
  include Workflow

  workflow do

    state :upset do
      event :scratch, :transition_to => :hiding
    end

    state :hiding do

    end
  end
end

As you can see, my Cat should still start at :conceived, in fact all classes derived from Animal should.

Obviously this is a very simplified example, to illustrate a point!

Steps

Hi,

We'd like to use workflow to create a wizard. Is there any way to get the current step and the total number of steps in the workflow?

Thanks

Invoking halt! within a transaction destroys rollback action

If I use the helper halt! (with AR) within a event handler method (here 'load') where there is an transaction, halt! exception doesn't rollback the transaction leaving DB in a unsafe state.
In the following example, if I replace the halt! by raise, the rollback occurs properly.
Am I doing something wrong? or there is a bug somewhere...

def load
  Shipment.transaction do
    shipping_items.each do |si|
        si.prepare_for_shipment
        si.unit_price = 99.9          
        si.save!
    end
    # raise  # rollback properly
    halt! 'An error occured'   # raise exception but doesn't rollback properly
  end
end

PS: I checked the code but being new to Ruby, I'm not sure... maybe it's due to the exception type raised (TransitionHalted)?!?

Question: parallelisation state

since there is no forum, I use the issue tracker for asking a question.

I would like to know if the workflow fit with my requirement

I have n tasks to complete. A same task need to be parallelised and done by k non-experts , then to aggregated by a reviewer. I would like to design this kind of workflow though the use of this workflow gem as a potential help but I am not sure to understand how to design the parallelisation step.

To get more insights. I need to design a "task assigner" method so that when a non-experts wants a task he can choose on the available tasks that are still in the "parallelised" state ( less than k non-experts have completed the task)

nicolas

Defining global transitions?

I'm wondering if it makes sense to have a way of defining a global transition that applies to all states? For example, if we have a long process with a lot of steps, it would be good to declare a global 'stop' transition that will go to :cancelled state.
I see a potential issue as we could then transit from :cancelled to :cancelled which is not good.

Anyone has a better idea?

Allow providing an instantiated Specification to the "workflow" method in lieu of a block

It would be nice if the "workflow" method accepted a Specification OR a block, or possibly both. I am wrapping your state machine DSL with a proxy to enable my own DSL more specific to my problem domain. To do that, I wanted to have a WorkflowProxy that would intercept my own methods and convert them to method calls to your DSL, which is the Specification object. To do this I instantiate a Specification and my proxy uses method missing to pass method calls through, but can define custom methods to. In any case, I had to fork the project to allow this to work. I would submit a pull request, but I suspect my implementation may not be the right ultimate solution. (http://github.com/PlasticLizard/workflow)

Setting state on after_initialize instead of before_validation

Is there any problem with setting the initial state upon object instantiation? currently...

> d = MyModel.new
=> <MyModel....>
> d.state
=> nil
> d.valid?
=> false
> d.state
=> "created"

preferred way

> d = MyModel.new
=> <MyModel...>
> d.state
=> "created"

Is there a problem with calling write_initial_state as a callback for after_initialize?

"Cannot update on a new record object" in created! method

After creating new record I get the following error

"can not update on a new record object"

My versions of ruby and rails:
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
Rails 3.2.12

My logs:

activerecord (3.2.12) lib/active_record/persistence.rb:195:in update_column'
workflow (1.0.0) lib/workflow.rb:348:inpersist_workflow_state'
workflow (1.0.0) lib/workflow.rb:214:in process_event!'
workflow (1.0.0) lib/workflow.rb:154:inblock (4 levels) in workflow'
vendor/engines/ads/app/controllers/ads/postings_controller.rb:46:in create'
actionpack (3.2.12) lib/action_controller/metal/implicit_render.rb:4:insend_action'
actionpack (3.2.12) lib/abstract_controller/base.rb:167:in process_action'
actionpack (3.2.12) lib/action_controller/metal/rendering.rb:10:inprocess_action'
actionpack (3.2.12) lib/abstract_controller/callbacks.rb:18:in block in process_action'
activesupport (3.2.12) lib/active_support/callbacks.rb:459:inblock in run_725368758838839659__process_action__1844081299291344106__callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:215:in block in _conditional_callback_around_830'
activesupport (3.2.12) lib/active_support/callbacks.rb:326:inaround'
activesupport (3.2.12) lib/active_support/callbacks.rb:310:in _callback_around_785'
activesupport (3.2.12) lib/active_support/callbacks.rb:214:in_conditional_callback_around_830'
activesupport (3.2.12) lib/active_support/callbacks.rb:447:in _run__725368758838839659__process_action__1844081299291344106__callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in__run_callback'
activesupport (3.2.12) lib/active_support/callbacks.rb:385:in _run_process_action_callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:81:inrun_callbacks'
actionpack (3.2.12) lib/abstract_controller/callbacks.rb:17:in process_action'
actionpack (3.2.12) lib/action_controller/metal/rescue.rb:29:inprocess_action'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:30:in block in process_action'
activesupport (3.2.12) lib/active_support/notifications.rb:123:inblock in instrument'
activesupport (3.2.12) lib/active_support/notifications/instrumenter.rb:20:in instrument'
activesupport (3.2.12) lib/active_support/notifications.rb:123:ininstrument'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:29:in process_action'
actionpack (3.2.12) lib/action_controller/metal/params_wrapper.rb:207:inprocess_action'
activerecord (3.2.12) lib/active_record/railties/controller_runtime.rb:18:in process_action'
actionpack (3.2.12) lib/abstract_controller/base.rb:121:inprocess'
actionpack (3.2.12) lib/abstract_controller/rendering.rb:45:in process'
actionpack (3.2.12) lib/action_controller/metal.rb:203:indispatch'
actionpack (3.2.12) lib/action_controller/metal/rack_delegation.rb:14:in dispatch'
actionpack (3.2.12) lib/action_controller/metal.rb:246:inblock in action'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:73:in call'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:73:indispatch'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:36:in call'
journey (1.0.4) lib/journey/router.rb:68:inblock in call'
journey (1.0.4) lib/journey/router.rb:56:in each'
journey (1.0.4) lib/journey/router.rb:56:incall'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:601:in call'
railties (3.2.12) lib/rails/engine.rb:479:incall'
railties (3.2.12) lib/rails/railtie/configurable.rb:30:in method_missing'
journey (1.0.4) lib/journey/router.rb:68:inblock in call'
journey (1.0.4) lib/journey/router.rb:56:in each'
journey (1.0.4) lib/journey/router.rb:56:incall'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:601:in call'
warden (1.2.1) lib/warden/manager.rb:35:inblock in call'
warden (1.2.1) lib/warden/manager.rb:34:in catch'
warden (1.2.1) lib/warden/manager.rb:34:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/best_standards_support.rb:17:in call'
rack (1.4.5) lib/rack/etag.rb:23:incall'
rack (1.4.5) lib/rack/conditionalget.rb:35:in call'
actionpack (3.2.12) lib/action_dispatch/middleware/head.rb:14:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/params_parser.rb:21:in call'
actionpack (3.2.12) lib/action_dispatch/middleware/flash.rb:242:incall'
rack (1.4.5) lib/rack/session/abstract/id.rb:210:in context'
rack (1.4.5) lib/rack/session/abstract/id.rb:205:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/cookies.rb:341:in call'
activerecord (3.2.12) lib/active_record/query_cache.rb:64:incall'
activerecord (3.2.12) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in call'
actionpack (3.2.12) lib/action_dispatch/middleware/callbacks.rb:28:inblock in call'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in _run__4503270357500974277__call__1321220018304606217__callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in__run_callback'
activesupport (3.2.12) lib/active_support/callbacks.rb:385:in _run_call_callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:81:inrun_callbacks'
actionpack (3.2.12) lib/action_dispatch/middleware/callbacks.rb:27:in call'
actionpack (3.2.12) lib/action_dispatch/middleware/reloader.rb:65:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/remote_ip.rb:31:in call'
actionpack (3.2.12) lib/action_dispatch/middleware/debug_exceptions.rb:16:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/show_exceptions.rb:56:in call'
railties (3.2.12) lib/rails/rack/logger.rb:32:incall_app'
railties (3.2.12) lib/rails/rack/logger.rb:18:in call'
actionpack (3.2.12) lib/action_dispatch/middleware/request_id.rb:22:incall'
rack (1.4.5) lib/rack/methodoverride.rb:21:in call'
rack (1.4.5) lib/rack/runtime.rb:17:incall'
activesupport (3.2.12) lib/active_support/cache/strategy/local_cache.rb:72:in call'
rack (1.4.5) lib/rack/lock.rb:15:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/static.rb:62:in call'
rack-cache (1.2) lib/rack/cache/context.rb:136:inforward'
rack-cache (1.2) lib/rack/cache/context.rb:143:in pass'
rack-cache (1.2) lib/rack/cache/context.rb:155:ininvalidate'
rack-cache (1.2) lib/rack/cache/context.rb:71:in call!'
rack-cache (1.2) lib/rack/cache/context.rb:51:incall'
railties (3.2.12) lib/rails/engine.rb:479:in call'
railties (3.2.12) lib/rails/application.rb:223:incall'
rack (1.4.5) lib/rack/content_length.rb:14:in call'
railties (3.2.12) lib/rails/rack/log_tailer.rb:17:incall'
rack (1.4.5) lib/rack/handler/webrick.rb:59:in service'
/home/aslyusarchuk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:138:inservice'
/home/aslyusarchuk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:94:in run'
/home/aslyusarchuk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/server.rb:295:inblock in start_thread'

ActiveRecord Transactions

What I would like is for the event transition and the transition event handler to be executed within the same ActiveRecord transaction to guarantee that the state is properly represented.

I'm using Workflow along with ActiveRecord in an order processing application. I have an event, "confirm", that relieves available inventory and changes the order state from "Processing" to "Shipped". I know if there is a problem confirming inventory I can use halt! to prevent the state from updating to "Shipped". But, what I am concerned of is the rare case in which the error occurs in updating the state itself. If this were to happen, the inventory would confirm but the state would remain "Processing". Then, the same order would be confirmed again the next time the rake task runs which would double-relieve inventory.

I know I could try and catch the exception and try and reverse the effects, but things can start to get complicated when doing that. Is there currently a solution to run the entire event sequence in an ActiveRecord transaction?

Thank you for your help, and btw thanks for this gem... it's almost exactly what I was looking for.

Workflow::create_workflow_diagram problems

Hello,
I've detected a few issues with Workflow::create_workflow_diagram and since I'm not experienced enough (yet) to do the fork/merge thing I will write them here, I hope you can incorporate them into the gem:

Docs

  1. Workflow::create_workflow_diagram expects a class, not a instance as stated in the doc:
    Workflow::create_workflow_diagram(Order) instead of Workflow::create_workflow_diagram(Order.new)
  2. To be able to use it with rake, the rake task must get access to the environment and not on its own like in the doc:
    task :workflow => :environment do instead of task :workflow do
  3. Lastly, it would be good to indicate that the dot library might be downloaded bundled with a viewer at http://www.graphviz.org/

Code

  1. When the dir path for the generated files has a space in it, it doesn't work, either Ruby (with the ) or dot (without the ), at least on MacOS X 10.5. It would be good change to the following line escaping the spaces at least on UNIXes:
    dot -Tpdf -o#{fname.gsub(/ /,'\ ')}.pdf #{fname.gsub(/ /,'\ ')}.dot

I hope it helps,
Gam

on workflow 0.8.0, ree and rails 2.3.11, I added a new "first state", but the code in on_entry isn't being executed

I have the following workflow configuration:

# scheduled_change.rb
  workflow do
                    # "The initial state of a workflow is the first state defined"
    state :planning do
      event :advance, :transitions_to => :planning_approved
      event :skip_to_complete, :transitions_to => :completed

      on_entry do
                   # send a "scheduled_change has been created" email
        @subject = "A new Scheduled Change has been created. [not yet started]."
        @subject += " '" + name + "'"
        @subject += " planned on " + target_date.strftime('%m/%d/%Y')
        @subject += " at " + target_time + " "  + time_zone.name
        @subject += ". Expected duration: " + duration.to_s + " hours."
        @recipient = creator.email
        send_email(@subject, @recipient, "created")
                     # send a "scheduled_change needs your approval" email
        @subject = "A new Scheduled Change has been created NEEDING YOUR APPROVAL."
        @subject += " '" + name + "'"
        @subject += " planned on " + target_date.strftime('%m/%d/%Y')
        @subject += " at " + target_time + " "  + time_zone.name
        @subject += ". Expected duration: " + duration.to_s + " hours."
        @recipient = carrier.advocates.size > 0 ? carrier.advocates.map(&:email) : creator.email
        logger.info "Sending NEEDING YOUR APPROVAL to #{@recipient.inspect}"
        send_email(@subject, @recipient, "requesting_approval")
      end
    end

    state :planning_approved do
      event :advance, :transitions_to => :running

      on_entry do
                         # send a "scheduled_change approved" email
        @subject = "A new Scheduled Change has been approved."
        @subject += " '" + name + "'"
        @subject += " planned on " + target_date.strftime('%m/%d/%Y')
        @subject += " at " + target_time + " "  + time_zone.name
        @subject += ". Expected duration: " + duration.to_s + " hours."
        @recipient = carrier.advocates.size > 0 ? carrier.advocates.map(&:email) << creator.email : creator.email
        send_email(@subject, @recipient, "created")
      end
    end

    state :running do
      event :advance, :transitions_to => :completed

      on_entry do
                      # send a "scheduled_change has started" email
        @recipient = SCHEDULED_CHANGE_BROADCAST_ADDRESS_EOS
        @subject = "Scheduled Change #{name} has started"
        @subject += ". Expected duration: " + duration.to_s + " hours."
        send_email(@subject, @recipient, "status")
      end
    end

    state :completed do
      event :reset, :transitions_to => :planning

      on_entry do
                 # send a "scheduled_change has completed" email
        @recipient = SCHEDULED_CHANGE_BROADCAST_ADDRESS_EOS
        @subject = "Scheduled Change #{name} has completed"
        if scheduled_change_outcome
          @subject += ". Result: " + scheduled_change_outcome.name.upcase + "."
        end
        status="completed"
        send_email(@subject, @recipient, "status")
      end
    end

  end

  def send_email(_sub, _to, _type)
    case _type
      when "created"
        ScheduledChangeMailer::deliver_scheduled_change_created_mail(_to, _sub, id)
      when "requesting_approval"
        ScheduledChangeMailer::deliver_scheduled_change_requesting_approval_mail(_to, _sub, id)
      when "status"
        ScheduledChangeMailer::deliver_scheduled_change_state_mail(_to, _sub, id)
    end
  end

But the code in :planning on_entry is no being executed. Can you please look over and see if you can tell me why?

Thanks! I appreciate your plugin!

Jason

"Cannot update on a new record object" in created! method

After creating new record I get the following error

"can not update on a new record object"

My versions of ruby and rails:
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
Rails 3.2.12

My logs:

activerecord (3.2.12) lib/active_record/persistence.rb:195:in update_column' workflow (1.0.0) lib/workflow.rb:348:inpersist_workflow_state'
workflow (1.0.0) lib/workflow.rb:214:in process_event!' workflow (1.0.0) lib/workflow.rb:154:inblock (4 levels) in workflow'
vendor/engines/ads/app/controllers/ads/postings_controller.rb:46:in create' actionpack (3.2.12) lib/action_controller/metal/implicit_render.rb:4:insend_action'
actionpack (3.2.12) lib/abstract_controller/base.rb:167:in process_action' actionpack (3.2.12) lib/action_controller/metal/rendering.rb:10:inprocess_action'
actionpack (3.2.12) lib/abstract_controller/callbacks.rb:18:in block in process_action' activesupport (3.2.12) lib/active_support/callbacks.rb:459:inblock in _run__725368758838839659__process_action__1844081299291344106__callbacks'
activesupport (3.2.12) lib/active_support/callbacks.rb:215:in block in _conditional_callback_around_830' activesupport (3.2.12) lib/active_support/callbacks.rb:326:inaround'
activesupport (3.2.12) lib/active_support/callbacks.rb:310:in _callback_around_785' activesupport (3.2.12) lib/active_support/callbacks.rb:214:in_conditional_callback_around_830'
activesupport (3.2.12) lib/active_support/callbacks.rb:447:in _run__725368758838839659__process_action__1844081299291344106__callbacks' activesupport (3.2.12) lib/active_support/callbacks.rb:405:in__run_callback'
activesupport (3.2.12) lib/active_support/callbacks.rb:385:in _run_process_action_callbacks' activesupport (3.2.12) lib/active_support/callbacks.rb:81:inrun_callbacks'
actionpack (3.2.12) lib/abstract_controller/callbacks.rb:17:in process_action' actionpack (3.2.12) lib/action_controller/metal/rescue.rb:29:inprocess_action'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:30:in block in process_action' activesupport (3.2.12) lib/active_support/notifications.rb:123:inblock in instrument'
activesupport (3.2.12) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (3.2.12) lib/active_support/notifications.rb:123:ininstrument'
actionpack (3.2.12) lib/action_controller/metal/instrumentation.rb:29:in process_action' actionpack (3.2.12) lib/action_controller/metal/params_wrapper.rb:207:inprocess_action'
activerecord (3.2.12) lib/active_record/railties/controller_runtime.rb:18:in process_action' actionpack (3.2.12) lib/abstract_controller/base.rb:121:inprocess'
actionpack (3.2.12) lib/abstract_controller/rendering.rb:45:in process' actionpack (3.2.12) lib/action_controller/metal.rb:203:indispatch'
actionpack (3.2.12) lib/action_controller/metal/rack_delegation.rb:14:in dispatch' actionpack (3.2.12) lib/action_controller/metal.rb:246:inblock in action'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:73:in call' actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:73:indispatch'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:36:in call' journey (1.0.4) lib/journey/router.rb:68:inblock in call'
journey (1.0.4) lib/journey/router.rb:56:in each' journey (1.0.4) lib/journey/router.rb:56:incall'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:601:in call' railties (3.2.12) lib/rails/engine.rb:479:incall'
railties (3.2.12) lib/rails/railtie/configurable.rb:30:in method_missing' journey (1.0.4) lib/journey/router.rb:68:inblock in call'
journey (1.0.4) lib/journey/router.rb:56:in each' journey (1.0.4) lib/journey/router.rb:56:incall'
actionpack (3.2.12) lib/action_dispatch/routing/route_set.rb:601:in call' warden (1.2.1) lib/warden/manager.rb:35:inblock in call'
warden (1.2.1) lib/warden/manager.rb:34:in catch' warden (1.2.1) lib/warden/manager.rb:34:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/best_standards_support.rb:17:in call' rack (1.4.5) lib/rack/etag.rb:23:incall'
rack (1.4.5) lib/rack/conditionalget.rb:35:in call' actionpack (3.2.12) lib/action_dispatch/middleware/head.rb:14:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/params_parser.rb:21:in call' actionpack (3.2.12) lib/action_dispatch/middleware/flash.rb:242:incall'
rack (1.4.5) lib/rack/session/abstract/id.rb:210:in context' rack (1.4.5) lib/rack/session/abstract/id.rb:205:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/cookies.rb:341:in call' activerecord (3.2.12) lib/active_record/query_cache.rb:64:incall'
activerecord (3.2.12) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in call' actionpack (3.2.12) lib/action_dispatch/middleware/callbacks.rb:28:inblock in call'
activesupport (3.2.12) lib/active_support/callbacks.rb:405:in _run__4503270357500974277__call__1321220018304606217__callbacks' activesupport (3.2.12) lib/active_support/callbacks.rb:405:in__run_callback'
activesupport (3.2.12) lib/active_support/callbacks.rb:385:in _run_call_callbacks' activesupport (3.2.12) lib/active_support/callbacks.rb:81:inrun_callbacks'
actionpack (3.2.12) lib/action_dispatch/middleware/callbacks.rb:27:in call' actionpack (3.2.12) lib/action_dispatch/middleware/reloader.rb:65:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/remote_ip.rb:31:in call' actionpack (3.2.12) lib/action_dispatch/middleware/debug_exceptions.rb:16:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/show_exceptions.rb:56:in call' railties (3.2.12) lib/rails/rack/logger.rb:32:incall_app'
railties (3.2.12) lib/rails/rack/logger.rb:18:in call' actionpack (3.2.12) lib/action_dispatch/middleware/request_id.rb:22:incall'
rack (1.4.5) lib/rack/methodoverride.rb:21:in call' rack (1.4.5) lib/rack/runtime.rb:17:incall'
activesupport (3.2.12) lib/active_support/cache/strategy/local_cache.rb:72:in call' rack (1.4.5) lib/rack/lock.rb:15:incall'
actionpack (3.2.12) lib/action_dispatch/middleware/static.rb:62:in call' rack-cache (1.2) lib/rack/cache/context.rb:136:inforward'
rack-cache (1.2) lib/rack/cache/context.rb:143:in pass' rack-cache (1.2) lib/rack/cache/context.rb:155:ininvalidate'
rack-cache (1.2) lib/rack/cache/context.rb:71:in call!' rack-cache (1.2) lib/rack/cache/context.rb:51:incall'
railties (3.2.12) lib/rails/engine.rb:479:in call' railties (3.2.12) lib/rails/application.rb:223:incall'
rack (1.4.5) lib/rack/content_length.rb:14:in call' railties (3.2.12) lib/rails/rack/log_tailer.rb:17:incall'
rack (1.4.5) lib/rack/handler/webrick.rb:59:in service' /home/aslyusarchuk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:138:inservice'
/home/aslyusarchuk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:94:in run' /home/aslyusarchuk/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/server.rb:295:inblock in start_thread'

Multiple simultaneous workflows

I like this workflow module, however I'm concerned that it locks me into one state machine per model. The multiple workflow demo appears to be for alternate workflows, not parallel work flows. It's quite possible I would want to add a second unrelated workflow to a model and as far as I can tell this is not possible.

Would love to see:

workflow :billing_state do ...

workflow :activity_state do ...

Not a great example, but basically I like the syntax of this module but may end up using another (such as https://github.com/pluginaweek/state_machine) because this seems like an unnecessary restriction. I haven't looked at the code to see how feasible this would be.

Correct way to check object.halted? from controller?

I have a conditional halt in my model

def approve
  halt! 'The invoice must be linked to a project' unless self.project
end

And in the controller I want to write something like below, so that it doesn't show the standard Workflow::TransitionHalted error page. (It doesn't work because @received_invoice.approve! is always called) I know about the halted? method but was wondering what the recommended way was to implement this in the controller.

def approve
  @received_invoice = ReceivedInvoice.find(params[:id])
  if @received_invoice.approve!
    redirect_to received_invoice_url(@received_invoice), notice: 'Invoice approved'
  else
    redirect_to received_invoice_url(@received_invoice), notice: @received_invoice.halted_because
  end
end

Persistence without AR

Is there some trick for non-active record persistence that I am missing?

I am using mongomapper and have added the :workflow_state attribute. I have also tried hooking on_transition and persist_workflow_state to preform a save manually, which actually does persist the state value but workflow does not seem to read that value on load of a record.

thanks,
chris

Previous step

Looking through the code, I don't see any way to reference the last step. For example, I've got a branched workflow, and I'd like to be able to call reject at a step and have it go back to the previous step, which might be one of two possible things. I'm thinking that the best way to handle this might be to add another column called previous_workflow_state, and then update this using the on_transition hook. Sound reasonable?

Thanks!

Access to the current_event object in event method?

If you have a workflow

workflow do
    state :open do
      event :archive, :transitions_to => :completed
      event :order, :transitions_to => :ordered
    end
    state :ordered do
      event :archive, :transitions_to => :completed
    end
    state :completed
end

def archive
     #object event?
end

My question is can I have access of the object 'event' in the archive method? I would like to check the origin state from which the event was fired (ordered or open) and possibly the destination state and the event meta info.

Name space pollution

class Registration < ActiveRecord::Base

has_many :reservations, dependent: :destroy

has_many :events, through: :reservations, source: :event # Not work with workflow.

has_many :events, through: :reservations, class_name: '::Event' # Works with Workflow

include Workflow

end

class Reservation < ActiveRecord::Base

belongs_to :registration

belongs_to :event

end

class Event < ActiveRecord::Base

has_many :reservations, dependent: :destroy

has_many :registrations, :through => :reservations

end

reg = Registration.find_by_id(267); reg.events

NoMethodError: undefined method quoted_table_name' for Workflow::Event:Class from /usr/local/lib/ruby/gems/1.9.1/gems/activerecord-2.3.8/lib/active_record/reflection.rb:187:inquoted_table_name'
from /usr/local/lib/ruby/gems/1.9.1/gems/activerecord-2.3.8/lib/active_record/associations/has_many_through_association.rb:142:in construct_select' from /usr/local/lib/ruby/gems/1.9.1/gems/activerecord-2.3.8/lib/active_record/associations/has_many_through_association.rb:79:infind_target'
from /usr/local/lib/ruby/gems/1.9.1/gems/activerecord-2.3.8/lib/active_record/associations/association_collection.rb:354:in load_target' from /usr/local/lib/ruby/gems/1.9.1/gems/activerecord-2.3.8/lib/active_record/associations/association_proxy.rb:140:ininspect'
from /usr/local/bin/irb:12:in `

'

Using "class_name: '::Event'" works around this bug.

does anyone see dynamically formulated workflows fly at all?

Back on 1.2 and 2.0.3 I used AASM and fellows - lately I've been trying out state_machine - but then I googled 'dynamic state machine' and Mountain View 'coughed up' this gem!

Pitch

I'd like to allow users to setting up workflows themselves, selecting from a bunch of available events/transistions, and in the proces I18n'ifying the body of the work :)

One use case would be several groups of users processing workflows on the same codebase - but with totally different workflow use cases (multi-site)

One other use case would be users adjusting workflows to changes to business policies - like: we at Corp XYZ are now 'green' and thus our SourcingOrders should not print before they are emailed/faxed to our suppliers - unless the Order Total exceeds 1,000,000...

UI design

I'm working off of a generic abstract_action_base.rb model which gets inherited by models like Project, Product, Item, Partner, etc. and then (as STI models) like Partner being inherited by models like Customer, Supplier, Bank, etc

Ideally I'd like my abstract_action_base to provide the workflow_states as a Hash

{ sourcing: :requested, selling: :ordered, stock: :backlogged }

and all state_questions to work like Product.find(419).sourcing_requested? and persisted to ActiveRecord (AR) in a quasi-searchable fashion - something along the lines of:

workflow_states = '----1R--2O--3B----'

which would allow quick searches on workflow states like:

Product.where{ workflow_states.like_all [ '-1R-','-3B-'] }.where( "workflow_states like '%-2O-% " )

Workflow transitions

Workflow transitions would - again ideally - be persisted to AR as something like:

t.string :transition_label  # what to label the transition and use as key for I18n.translations
t.text :guard               # code to eval true/false guarding the transition on an instance
t.text :from_to             # hash of transition like { drafted: { requested: :some_condition_attribute_or_method, archived: :other_condition_or_method }, requested: {} }
                                    # persisted as serialized object

Epilogue

Am I totally loosing it here? Or does you (the reader) see dynamically formulated workflows fly at all?

Change state on halt

I can't found any way to easily change state on a halt

class Model < AR::Base
  include Workflow 

  workflow do
    state :new do
      event :process,  :transitions_to => :ready
    end
    state :ready
    state :fail
  end

  def process
    if process_works_whell?
       :ok
    else
      change_state :to => :fail
  end
end

Is any way to do this?

Maybe an option as:
event :process, :transitions_to => :ready, :on_halt => :fail

Or more advanced:
event :process, :transitions_to => [:ready, :fail]
and in the code
halt(:to => :fail)

Or may i doing something wrong?

Operator to determine the relative state...

It would be very useful if there were operators able to respond about the overall state.
For example, having this:
class C
workflow do
state :a do
event :to_b, :transitions_to => :b
end
state :b do
event :to_c, :transitions_to => :c
end
state :c
end
...
end

And these instances:

inst_a.a? #=> true
inst_b.b? #=> true
inst_c.c? #=> true

It would be useful to have a method overcame?(state) like this:
inst_a.overcame?(:a) #=>false
inst_a.overcame?(:b) #=>false
inst_a.overcame?(:c) #=>false

inst_b.overcame?(:a) #=>true
inst_b.overcame?(:b) #=>false
inst_b.overcame?(:c) #=>false

inst_c.overcame?(:a) #=>true
inst_c.overcame?(:b) #=>true
inst_c.overcame?(:c) #=>false

and its counterpart to_reach?(state)
inst_a.to_reach?(:a) #=>false
inst_a.to_reach?(:b) #=>true
inst_a.to_reach?(:c) #=>true

inst_b.to_reach?(:a) #=>false
inst_b.to_reach?(:b) #=>false
inst_b.to_reach?(:c) #=>true

inst_c.to_reach?(:a) #=>false
inst_c.to_reach?(:b) #=>false
inst_c.to_reach?(:c) #=>false

of course this is a simple case in which these two methods would be deterministic since the diagram produced by the workflow is a tree and not a graph, but even just for those simple case, it would be useful to have these methods.
If the response cannot be determined, it could be thrown an exception.
These methods should be boolean, to be useful, not three-state, because the are intended to use with tree workflow...

minor typos in application using workflow - better error messages?

Hi - beginner error here... but an uninformative diagnostic error message. I accidentally typed "transition_to" instead of "transitions_to". Which provokes a message about an undefined method "to_sym" for nil.Class. Not very obvious that there's a missing required parameter...
Can I suggest a one liner enhancement to the initialize function?

def initialize(name, transitions_to, meta = {}, &action)
  raise "missing 'transitions_to' from workflow for '#{name}'" if transitions_to == nil 
  @name, @transitions_to, @meta, @action = name, transitions_to.to_sym, meta, action
end

Recommendation for undoing an event..

Hi, I'm wondering what is the most appropriate way for handling 'undo' using workflow, for example using your 'article' illustration:

from 'being_reviewed' we can either accept or reject an article. If we choose to accept but we want to revert back to 'being_reviewed' is it better to?

1 give's each state an extra event for reverting, ex:

    state :new do
      event :submit, :transitions_to => :awaiting_review
    end
    state :awaiting_review do
      event :review, :transitions_to => :being_reviewed
      event :revert_new, :transitions_to => :new
    end
    state :being_reviewed do
      event :accept, :transitions_to => :accepted
      event :reject, :transitions_to => :rejected
      event :revert_awaiting_review, :transitions_to => :awaiting_review
    end
    state :accepted do
      event :revert_being_reviewed, :transitions_to => :being_reviewed
    end

2 make use of external gem for handling undo, such as papertrail
3 some other way?

Using strings instead of symbols

If I try to use strings instead of symbols for defining the events Workflow doesn't work properly.

e.g.

state 'new' do
    event 'publish', ...
end

Then

object.can_publish? 

always returns false where it should return true. When using symbols this works fine.

However using string is useful for validation:

validates :state, :presence => true, :inclusion => STATUSES

where STATUSES is the array of possible valid states

When the object is first created the state is a symbol so validation passes. Then when the saved and retrieved back again state is a string so it doesn't validate anymore.

I would be good to have full support for using strings as well as symbols.

NameError: undefined local variable or method `c' for #<Article>, Ruby 1.9.1

I have Ruby 1.9.1
I commented four lines of code (it begins at the line 180), as you recommended.
Need some help with this:

$ irb
irb(main):001:0> require 'rubygems'
=> false
irb(main):002:0> require 'workflow'
=> true
irb(main):003:0> class Article
irb(main):004:1> include Workflow
irb(main):005:1> workflow do
irb(main):006:2* state :new do
irb(main):007:3* event :submit, :transitions_to => :awaiting_review
irb(main):008:3> end
irb(main):009:2> state :awaiting_review do
irb(main):010:3* event :review, :transitions_to => :being_reviewed
irb(main):011:3> end
irb(main):012:2> state :being_reviewed do
irb(main):013:3* event :accept, :transitions_to => :accepted
irb(main):014:3> event :reject, :transitions_to => :rejected
irb(main):015:3> end
irb(main):016:2> state :accepted
irb(main):017:2> state :rejected
irb(main):018:2> end
irb(main):019:1> end
=> [#<Workflow::State:0x000000023bc040 @name=:new, @events={:submit=>#<Workflow::Event:0x000000023bbe10 @name=:submit, @transitions_to=:awaiting_review, @meta={}, @action=nil>}, @meta={}>, #<Workflow::State:0x000000023bbc88 @name=:awaiting_review, @events={:review=>#<Workflow::Event:0x000000023bba58 @name=:review, @transitions_to=:being_reviewed, @meta={}, @action=nil>}, @meta={}>, #<Workflow::State:0x000000023bb908 @name=:being_reviewed, @events={:accept=>#<Workflow::Event:0x000000023bb6d8 @name=:accept, @transitions_to=:accepted, @meta={}, @action=nil>, :reject=>#<Workflow::Event:0x000000023bb5c0 @name=:reject, @transitions_to=:rejected, @meta={}, @action=nil>}, @meta={}>, #<Workflow::State:0x000000023bb4a8 @name=:accepted, @events={}, @meta={}>, #<Workflow::State:0x000000023bb208 @name=:rejected, @events={}, @meta={}>]
irb(main):020:0> article = Article.new
=> #Article:0x000000023b0ce0
irb(main):021:0> article.accepted?
NameError: undefined local variable or method c' for #<Article:0x000000023b0ce0> from /usr/lib/ruby/gems/1.9.1/gems/workflow-0.6.0/lib/workflow.rb:188:inspec'
from /usr/lib/ruby/gems/1.9.1/gems/workflow-0.6.0/lib/workflow.rb:135:in current_state' from /usr/lib/ruby/gems/1.9.1/gems/workflow-0.6.0/lib/workflow.rb:115:inblock (3 levels) in workflow'
from (irb):21
from /usr/bin/irb:12:in `

'

I also tried to use Workflow in Rails project, through script/console, but it shows me the same error.
Sorry, if I misunderstood something.

Discussion of how best to do state transition validations

I have a requirement to do state-based validations. This keeps all of the form code tidy, since it can use the standard ActiveRecord error discovery.

I've been looking at the southdesign modification to do state-based validations, which is a good start, but for my purposes there are a few shortcomings:

1 - It always throws an exception - I can see why, because new_state! is already the "!" operator which would normally raise an exception in ActiveRecord, but in the workflow nomenclature it does not raise an exception under normal circumstances. I think it is preferable that halted? or valid? return false in the normal case (where, for validation purposes, invalid input should be considered a normal case).

2 - It does not take advantage of the new ActiveModel Validators (http://api.rubyonrails.org/classes/ActiveModel/Validations.html). This causes a deprecation warning in Rails 3, but also I think it doesn't capture the existing validation classes. No reason to be writing more of them!

So I think this is all easily managed, but my questions for discussion are:
1: Is there a reasonable syntax for indicating when to not throw/throw an exception for validation? I am thinking new_state! and new_state!(true), respectively, but this seems slightly kludgy. Comments?

2: Is there a good syntax for defining validations so they can follow the Rails3 validator syntax:
# validates :name, :presence => {:if => :foo?}, :length => {:maximum => 200, :minimum => 100}

For consistency, I am inclined to use:

event :accept, :transitions_to => :accepted do
  validates :title, :presence
end

But I see in the README "that mixing the list of events and states with the blocks invoked for particular transitions leads to a bumpy and poorly readable code due to a deep nesting" so I am conflicted about the right way to handle this. Advice/comments?

Transitions not working with ActiveRecord

Hi there,

I have ActiveRecord 3.2.10 with ruby 1.9.2-p290 and trying to get this working with workflow gem version 0.8.6.

Without active record, the transitions work fine, as soon as I add in ActiveRecord to the mix, it only created the initial object and records the initial state in the DB correctly, but any transition (whether it's a new instance or trying to resume it from the DB) fails. No error message provided, the object state stays in the original one.

I even tried to run your Booking class example (https://github.com/geekq/workflow/blob/master/test/multiple_workflows_test.rb) and that didn't work either.

Could you look into this please and/or advise what am I doing wrong?

Thanks and regards.
Máté

Feature request: Ability to compare workflow states

It would be great if we could test if a workflow is 'bigger/smaller or egal' than another according to the specification.

Example:

Workflow do
  state :one do
    event :next, :transitions_to => :two,
  end
  state :two do
    event :back, :transitions_to => :one,
    event :next, :transitions_to => :three,
  end
  state :three
end  

We could check:
my_object.current_state > Object.workflow_spec.states[:two]

Semantic

bigger ( state1 > state2): true if state2 cannot be reached (through any number of events/charges) from state1 BUT NOT the opposite (eg, :three > :one => true)

smaller ( state1 < state2): true if state2 can be reached from state1 BUT NOT the opposite (eg, :one > :three => true)

equal ( state1 == state2): true if state2 can be reached from state1 AND state1 can be reached from state2 (eg, :two == :one => true)

What do you think?

workflow_state persistence for multiple_workflows example

bowsersenior reported:

The per-object workflow has some issues, even on ruby 1.8.7!

Let me explain with reference to the working example:
http://github.com/geekq/workflow/blob/master/test/multiple_workflows_test.rb

The Booking class is an ActiveRecord model, but in fact, the ActiveRecordInstanceMethods are never loaded. The workflow_state is persisted only in a variable. I am not sure why this is happening, but it seems to be related to the use of metaclass.

Now on Ruby 1.9.2, where the bug referenced above has been fixed, the test fails, because ActiveRecordInstanceMethods ARE loaded, and no class method name workflow_column is found.

I fiddled around with this for a while trying to find a solution, but couldn't get anywhere. It seems like there should be a straightforward solution...

Diagram generation fails for models in modules

We have an Orders::RetailerOrder model and create_workflow_diagram tries to put the dot file in a sub folder + the dot file is invalid.

I was able to fix the problem by modifying the workflow_name :

workflow_name = "#{klass.name.tableize}_workflow".gsub(/\//, '')

Conflicting method and event names

In a Rails application of mine a model has a state :created with an event :open, :transition_to => :opened declaration.
A method of the model triggers the state change calling open!. That worked well with the 0.8.1 gem but doesn't work anymore with the 0.8.6 one. Instead it ends up calling the open method of open-uri, which happens to have been included somewhere by the framework and has a different number of arguments and returns an error which I saw in the browser.

An easy workaround would be to change the state name to something else but I set "0.8.1" in the Gemfile to be sure I have no other problems I still didn't find out. Furthermore, what if the next version of another gem "steals" one or more of my state names? (inadvertently, obviously, I don't think this is an attack vector). Devising perfectly safe state names is impossible.

The ideal solution is that the Workflow state prevails over any method name. That should make sense because a locally defined workflow should be expected to be in the local scope. Calling a far away method probably violates the least surprise principle.

undefined method `find' for Workflow::Event:Class

Hi,

I have the following classes on my system:


class Event < ActiveRecord::Base

  has_many :event_approval_requests

  belongs_to :user

  include Workflow  
  workflow do
    state :pre_registered do
      event :submit, :transitions_to => :awaiting_approval
    end
    
    state :awaiting_approval do
      event :approve, :transitions_to => :approved
      event :reject, :transitions_to => :rejected
    end

    state :approved do
      event :submit, :transitions_to => :awaiting_approval
    end

    state :rejected do
      event :submit, :transitions_to => :awaiting_approval
    end
  end

 ...

end
class EventApprovalRequest < ActiveRecord::Base
  belongs_to :user
  belongs_to :department
  belongs_to :event

  include Workflow  

  workflow do
    state :pending do
      event :approve, :transitions_to => :approved
      event :reject, :transitions_to => :rejected
    end

    state :approved
    state :rejected
  end

  ...

end

Note that the two classes have workflow definitions and one have a relationship with the other. In a view, when I try to access the event from the event_approval_request like below:


<%=h event_approval_request.event.title %>

I got the following error: NoMethodError in Event_approval_requests#index undefined method `find' for Workflow::Event:Class

this error doesn't occur if I access a non-workflow class, like below:


<%=h event_approval_request.user.first_name %>

I'm using JRuby 1.5.1, Linux Fedora 11, Rails 2.3.8 and workflow 0.6.0.

Could anyone help me? Is it really an issue?

Thanks in advance,
Gustavo

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.