staying RESTful and triggering actions without saving a record.

Hey Frank,

state_machine actually provides support for executing events using a standard REST interface. Rather than calling the event method directly (such as "release!"), you can set an the machine's event attribute like so:

  station.state_event = 'release'   station.save!

Any event that gets set in "state_event" will be validated and fired when the record is saved. There's a full example (model, controller, and views) of this here: state_machine/examples/rails-rest at master · pluginaweek/state_machine · GitHub

Hope this helps!

-Aaron

I am not sure I see the problem. A form can have multiple buttons if you want all the buttons to go to the same action (the button name is passed in the params), or you can use button_to if you want them to go to different actions.

Perhaps I misunderstand the problem.

Colin

frankjmattia@gmail.com wrote:

i'll try another example, maybe it'll be a little clearer - also, ill take SM out of the equation.

suppose theres a job edit page... the page has all the job attributes, title, description... etc. but i dont want to change those. i want a button somewhere in the form called "mark & dupe".. what those actions do is irrelevant -- BUT -- i dont want to create a non-standard action.

[...]

Why not? It's honestly the most RESTful thing to do in your case, IMHO.

Likewise with state transitions: I don't believe there's anything wrong or unRESTful with URLs like http://server/accounts/9/release .

Best,

[Please quote when replying, so that it is clear what you are responding to.]

frankjmattia@gmail.com wrote:

a form can only direct to one action though, correct?

Absent JavaScript, yes.

i want these buttons to located inside of my form - and while ive never tried it, i'll assume that nesting forms leads to heartbreak and homelessness...

It leads to invalid HTML and unpredictable results.

But do these have to be submit buttons? Why not make them links?

if i have 20 different states... and am only going to need a user to chose 1 of 3 at any given point in time, it doesnt make sense to have 20 separate actions..

Why the hell would you have 20 different states? Perhaps you're abusing your state machine...

But if not, then yeah, maybe a go_to_state action would work better.

is there a way to pass put params in a button_to or link_to?

Sure, you can always have a query string in your URL, or play with your routes to pass the appropriate parameters. Query strings work just as well in Rails as anywhere else.

in my controllers update action, can i check if any specific params are specified and then delegate to the appropriate action?

Of course you can, though this will be messy if overdone.

the docs for button_to don't really help me too much.

You probably don't want button_to anyway -- there's generally no reason to use JavaScript for something this simple.

Best,

i want these buttons to located inside of my form - and while ive never tried it, i'll assume that nesting forms leads to ...

It leads to invalid HTML and unpredictable results.

But do these have to be submit buttons? Why not make them links?

But a form can have multiple submit buttons; only the value of the one clicked is passed as a parameter to your action...

FWIW,

so i can have a form submit to update, have the submit buttons have different values and then in the update action figure out which one was clicked?

Exactly.

what is necessary beyond f.submit in my view?

Just create multiple tags with different values, e.g.

<%= submit_tag 'Accumulate' %> <%= submit_tag 'Release' %> <%= submit_tag 'Tenderize' %> # etc....

here's what i ended up doing -- if anyone can find a technical flaw with it (like someone being able to trigger things just by messing with urls) let me know. hopefully this helps someone else.

in my view i have

<% unless @machine.new_record? %>   <%= link_to 'service', machine_path(@machine, :event => :service), :method => :put %>   <%= link_to 'release', machine_path(@machine, :event => :release), :method => :put %>   <%= link_to 'use', machine_path(@machine, :event => :use), :method => :put %> <% end %>

and in my controller (using rails 3 edge)

def update   @machine = Machine.find(params[:id])

  if params[:event]     flash[:notice] = "an event was triggered."

    ## do something with my @machine object here

    respond_with @machine and return   end

  flash[:notice] = "Machine successfully updated" if @machine.update_attributes(params[:machine])

  respond_with @machine end

thanks for the input and advice - it was much appreciated, - FJM

frankjmattia@gmail.com wrote:

where can i find the documentation for all of the action_controller_path functions?

multiple submits on a form are no longer a viable solution because the only way to tell which one was hit was to know the name "value" of the submit button.. when its in different languages it gets ugly.. im just going to try to use a link_to solution but i cant figure out how _path wants its arguments.

link_to 'release', station_path(@station, :state => :release), :method => :put

generates a url that looks right but doesnt work.

You should probably read the Rails routing guide.

Best,

frankjmattia@gmail.com wrote:

yeah, i've read it half a dozen times

Read *what*? Please quote when replying so it's clear what you're responding to.

- doesn't give me any insight on the argument list for the _path family of functions and apidock is less than helpful as well.

Are you talking about the routing guide?

In any case, the arguments are whatever is defined in that particular route. Run rake routes or look at your routes file to see what that would be.

searching through google led to some obscure blog that said i could do:   link_to 'do something', station_path(@station, :station => { :attribute => :value }), :method => :put

but why does this work and why aren't the _path functions clearly documented?

Because they're generated from your routes, and so will be different for each Rails app. This is pretty clearly explained in the routing guide, as well as in the documentation for ActionController::Routing and ActionController::Resources . Perhaps you should read those again.

maybe someone who knows could point me to where these functions are defined in the source tree (preferably in master)?

Best,

> yeah, i've read it half a dozen times

Read *what*? Please quote when replying so it's clear what you're responding to.

I have read the rails routing guide a dozen times.

> - doesn't give me any insight on > the argument list for the _path family of functions and apidock is > less than helpful as well.

Are you talking about the routing guide?

Yes.

In any case, the arguments are whatever is defined in that particular route. Run rake routes or look at your routes file to see what that would be.

That doesn't make any sense. My output of rake routes does not show a function name for put requests. What I've discovered (through trial and error) is that when using a _path function the arguments can either be in the form of

_path(:id => @station) _path(@station) _path(@station, :attribute_not_on_the_model => :value) _path(@station, :station => { :this_attribute_is_on_model => :value})

where in the guide is that explained? if it's even in there it most certainly is not clear unless you already have a very good grasp of the subject. I don't believe that it's "typical" for someone reading the guides (mostly beginners I'll assume) to want to pass params in their links and send them off as put requests.

> searching through google led to some obscure blog that said i could > do: > link_to 'do something', station_path(@station, :station => > { :attribute => :value }), :method => :put

> but why does this work and why aren't the _path functions clearly > documented?

Because they're generated from your routes, and so will be different for each Rails app. This is pretty clearly explained in the routing guide, as well as in the documentation for ActionController::Routing and ActionController::Resources . Perhaps you should read those again.

ActionController::Resources is the only one of those that even hints at the proper form for the _path functions and that's only in the very first example which doesn't even say that it can be used for those functions - it only says "this is what a so-and-so request looks like". http://rails.rubyonrails.org/classes/ActionController/Resources.html

to quote the docs a little further down it says: Named Route Helper message message_url(id), hash_for_message_url(id), message_path(id), hash_for_message_path(id)

that would lead me to believe that the only argument available to those functions is id...

> maybe someone who knows could point me to where these functions are > defined in the source tree (preferably in master)?

This is all I'm really interested in now. Simply for curiosities sake... The rest I've figured out and is all moot.

frankjmattia@gmail.com wrote: [...]

In any case, the arguments are whatever is defined in that particular route. �Run rake routes or look at your routes file to see what that would be.

That doesn't make any sense.

Whether it makes sense or not, it is the case. :slight_smile: The arguments are the :parameters in the route.

My output of rake routes does not show a function name for put requests.

No, but if you're using map.resources, the paths for PUT requests are the same as for named GET requests.

Using a link to a PUT request, though, is *extremely* smelly. Links should practically always be GET.

[...]

as well as in the documentation for ActionController::Routing and ActionController::Resources . �Perhaps you should read those again.

ActionController::Resources is the only one of those that even hints at the proper form for the _path functions and that's only in the very first example which doesn't even say that it can be used for those functions - it only says "this is what a so-and-so request looks like". http://rails.rubyonrails.org/classes/ActionController/Resources.html

There's also the stuff about named routes in ActionController::Routing.

to quote the docs a little further down it says: Named Route Helper message message_url(id), hash_for_message_url(id), message_path(id), hash_for_message_path(id)

that would lead me to believe that the only argument available to those functions is id...

Again, it depends on how your routes are defined.

> maybe someone who knows could point me to where these functions are > defined in the source tree (preferably in master)?

This is all I'm really interested in now. Simply for curiosities sake... The rest I've figured out and is all moot.

I suspect looking at the source for the resources function would be a good place to start.

Best,

>> In any case, the arguments are whatever is defined in that particular >> route. Run rake routes or look at your routes file to see what that >> would be.

> That doesn't make any sense.

Whether it makes sense or not, it is the case. :slight_smile: The arguments are the :parameters in the route.

But I've never explicitly defined any parameters - and the notion of the arguments simply being a params-like hash had never occurred to me. I never saw it done.

> My output of rake routes does not show a > function name for put requests.

No, but if you're using map.resources, the paths for PUT requests are the same as for named GET requests.

also a point that was not being connected in my head.

Using a link to a PUT request, though, is *extremely* smelly. Links should practically always be GET.

not that i would do something so "ugly" as set a links appearance to button - but does that make it any more acceptable? I've read plenty of religious war associated with this concept and believe that it's best evaluated on a need by need basis. In the workflow of my application a link that is styled a certain way most certainly conveys to the user that it "does something important". With xss protection in rails and good testing it should be perfectly safe.

>> as well as in the documentation for ActionController::Routing and >> ActionController::Resources . Perhaps you should read those again.

> ActionController::Resources is the only one of those that even hints > at the proper form for the _path functions and that's only in the very > first example which doesn't even say that it can be used for those > functions - it only says "this is what a so-and-so request looks > like". >http://rails.rubyonrails.org/classes/ActionController/Resources.html

There's also the stuff about named routes in ActionController::Routing.

> to quote the docs a little further down it says: > Named Route Helper > message message_url(id), hash_for_message_url(id), > message_path(id), hash_for_message_path(id)

> that would lead me to believe that the only argument available to > those functions is id...

Again, it depends on how your routes are defined.

That sentence should be added to the docs somewhere.

>> > maybe someone who knows could point me to where these functions are >> > defined in the source tree (preferably in master)?

> This is all I'm really interested in now. Simply for curiosities > sake... The rest I've figured out and is all moot.

I suspect looking at the source for the resources function would be a good place to start.

Thank you kindly for the tip in that direction.

frankjmattia@gmail.com wrote:

>> In any case, the arguments are whatever is defined in that particular >> route. Run rake routes or look at your routes file to see what that >> would be.

> That doesn't make any sense.

Whether it makes sense or not, it is the case. :slight_smile: �The arguments are the :parameters in the route.

But I've never explicitly defined any parameters - and the notion of the arguments simply being a params-like hash had never occurred to me. I never saw it done.

I've definitely seen examples, but I couldn't find them when I went looking.

> My output of rake routes does not show a > function name for put requests.

No, but if you're using map.resources, the paths for PUT requests are the same as for named GET requests.

also a point that was not being connected in my head.

Using a link to a PUT request, though, is *extremely* smelly. �Links should practically always be GET.

not that i would do something so "ugly" as set a links appearance to button - but does that make it any more acceptable?

No. It has *nothing* to do with appearance. PUT is for updating an existing resource (generally through a form).

I've read plenty of religious war associated with this concept and believe that it's best evaluated on a need by need basis.

I think that the need for a PUT link does not exist, period. If your app is telling you that it wants a link, then it's telling you that it wants a GET, perhaps with a custom verb or extra parameter.

Just never do PUT links (if you even *can* -- I'm not sure :method works on links; I hope it does not).

In the workflow of my application a link that is styled a certain way most certainly conveys to the user that it "does something important". With xss protection in rails and good testing it should be perfectly safe.

There's also the stuff about named routes in ActionController::Routing.

Again, it depends on how your routes are defined.

That sentence should be added to the docs somewhere.

It's pretty clear if you read the class doc.

Best,

No. It has *nothing* to do with appearance. PUT is for updating an existing resource (generally through a form).

and i am updating a resource... i'm not using #update_attributes, but in my controller I am saving.

I think that the need for a PUT link does not exist, period. If your app is telling you that it wants a link, then it's telling you that it wants a GET, perhaps with a custom verb or extra parameter.

Destroy links are still the default in rails - destroy and put are similar in that they both change data.

Just never do PUT links (if you even *can* -- I'm not sure :method works on links; I hope it does not).

It does -- and from what I've read - the implementation is sound. I have a confirmation dialog on the link further narrowing the scope of things that could go wrong.

It's pretty clear if you read the class doc.

That's a matter of opinion.

Thanks for your help.

frankjmattia@gmail.com wrote:

No. It has *nothing* to do with appearance. PUT is for updating an existing resource (generally through a form).

and i am updating a resource... i'm not using #update_attributes, but in my controller I am saving.

That's an irrelevant implementation detail. update_attributes is just a shorthand for save anyway.

I think that the need for a PUT link does not exist, period. If your app is telling you that it wants a link, then it's telling you that it wants a GET, perhaps with a custom verb or extra parameter.

Destroy links are still the default in rails - destroy and put are similar in that they both change data.

Nothing view-related is the default in Rails. Or do you mean that Rails puts them in the scaffolds it generates?

In any case, DELETE and PUT have some important differences, the most fundamental being the inclusion of additional data in the PUT.

A state change may be *implemented* as a field update, but it is not conceptually the same thing as, say, changing a name. Therefore, PUT is inappropriate, and you want a custom GET action instead.

Against this I'd set the fact that such a GET action wouldn't be idempotent no matter how you look at it. Hmmm....

Just never do PUT links (if you even *can* -- I'm not sure :method works on links; I hope it does not).

It does -- and from what I've read - the implementation is sound. I have a confirmation dialog on the link further narrowing the scope of things that could go wrong.

The confirmation is strictly a UI refinement. It won't work if JavaScript is turned off. It might prevent a user from doing something in error. Might.

It's pretty clear if you read the class doc.

That's a matter of opinion.

Thanks for your help.

Best,