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: http://github.com/pluginaweek/state_machine/tree/master/examples/rails-rest

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,