0

I've Rails 4.0 application with 'order' model which has a status field. While invoking a 'show' action to get 'order' object details, I want to add additional buttons on the 'Show page', in addition to 'Edit' and 'Back'. First one to mark 'update status' which will only update status of this order object to '1' and the second button to mark 'close order' which will only update status of this order object to 2. How can I achieve this without an 'Edit' action/view? Do I need to use form_tag to add these buttons and do I need to write 2 new methods in OrdersController to update the status?

Following is my show.html.erb with two buttons I want add...

<p>
  <strong>Name:</strong>
  <%= @order.name %>
</p>
<p>
  <strong>Status:</strong>
  <%= @order.status %>
</p>
<%= link_to 'Edit', edit_order_path(@order) %> |
<%= link_to 'Back', orders_path %> |
<%= link_to 'Shipped', '#', :name => 'shipped_button' %> |
<%= link_to 'Close',   '#', :name => 'close_button' %>

If I click on 'Shipped' or 'Close' button they both will be called on to 'OrdersController' as a 'GET' request as shown below,

.. Started GET "/orders/1?name=shipped_button" for 127.0.0.1 at 2014-11-21 15:40:38 -0800
Processing by OrdersController#show as HTML
Parameters: {"name"=>"shipped_button", "id"=>"1"}
Order Load (0.1ms) SELECT "orders".* FROM "orders" WHERE "orders"."id" = ? LIMIT 1 [["id", 1]]
Rendered orders/show.html.erb within layouts/application (1.9ms)
Completed 200 OK in 50ms (Views: 47.8ms | ActiveRecord: 0.1ms)

How can I update the model with appropriate status field update. 'status' is an integer field in the 'orders' model.

Atarang
  • 422
  • 1
  • 6
  • 22
  • I can't figure out what you want. really. Can you please explain it in more detail? However you can pass actions to the link_to function like described in that [question](http://stackoverflow.com/questions/5607155/ruby-on-rails-3-link-to-controller-and-action) – AME Nov 21 '14 at 23:58
  • Yes, that answer you pointed out looks like would work in this case. link_to just invokes an action in a controller with id or whole object as input parameter. – Atarang Nov 23 '14 at 07:23

1 Answers1

2

I would do that with ajax:

You need something like that in your routes.rb file.

resources :orders

orders/show.html.erb:

<div id="order" data-order-id="<%= @order.id %>"></div>

<p id="notice"><%= notice %></p>

<p>
  <strong>Status:</strong>
  <%= @order.status %>
</p>

<p>
  <strong>Name:</strong>
  <%= @order.name %>
</p>

<%= link_to 'Edit', edit_order_path(@order) %> |
<%= link_to 'Back', orders_path %>
<%= link_to 'Shipped', '',id: "ship" %> |
<%= link_to 'Close',   '', id: "close" %>



<script> 
$(function () {
    var orderId = $('#order').data("order-id");
    var shippButton = $('#ship');

    var closeButton = $('#close');
    alert(orderId);



    closeButton.on("click", function() {
        $.ajax({
            url: '/orders/'+orderId,
            type: 'PATCH',
            dataType: 'json',
            data: {"order": { "status": "4"}},
            complete: function (jqXHR, textStatus) {
                // callback
            },
            success: function (data, textStatus, jqXHR) {
                // inform user that it was a sucess like:
                alert("successfully changed the order to closed");
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // do something if the request fails
            }
        });
    });

    shippButton.on("click", function() {
        $.ajax({
            url: '/orders/'+orderId,
            type: 'PATCH',
            dataType: 'json',
            data: {"order": { "status": "3"}},
            complete: function (jqXHR, textStatus) {
                // callback
            },  
            success: function (data, textStatus, jqXHR) {
                // inform user that it was a sucess like:
                alert("successfully changed the order to shipped");
            },  
            error: function (jqXHR, textStatus, errorThrown) {
                // do something if the request fails
            }   
        }); 
    });
});

</script>
AME
  • 2,262
  • 6
  • 19
  • 39
  • @ auL5agoi, Thanks, I'll try this change and update my response. But since I've never done any Javascript before, where would I put these JS functions, in show.html.erb? Are they under some kind of html tag? – Atarang Nov 22 '14 at 00:53
  • @Atarang Ah ok you can wrap them in a script tag this is all inside your show.html.erb file. updated my answer. btw. Please describe which attributes you need to change: like: status: 1 when x, status: 2 when y so on. – AME Nov 22 '14 at 01:02
  • @ auL5agoi, I've not tried your suggestion yet. I've Order model, which has STATUSES Hash with { :new => 1, :open => 2, :shipped => 3, :close => 4 } and depending on click on 'shipped' or 'close' I need to set the appropriate value to the 'status' field in the model. Why your approach is considered 'bad'? What would be the Rails way of achieving the same thing without JS code? – Atarang Nov 22 '14 at 08:20
  • @Atarang I don't know about the Rails way - I try to solve problems. Could you please try my example? – AME Nov 23 '14 at 13:26
  • @ auL5agoi, After making changes as per your suggestion, I don't see ajax function getting called at all. In a statement <%= link_to 'Shipped', '#',id: "ship" %>, how does this invoke ajax function? – Atarang Nov 24 '14 at 07:07
  • Have you Jquery installed ? check out your Gemfile for jquery – AME Nov 24 '14 at 12:33
  • Yes, jquery-rails gem is installed. See below bundle snapshot, Using railties (4.0.0) Using coffee-rails (4.0.1) Using hike (1.2.3) Using jbuilder (1.5.3) Using jquery-rails (3.1.2) Using json (1.8.1) Using bundler (1.3.5) Using tilt (1.4.1) Using sprockets (2.11.3) – Atarang Nov 24 '14 at 16:42
  • @Atarang Then I don't know what's wrong here. All I can say is that I've actually tested all the stuff and it works. Have you created those products with scaffolding? – AME Nov 24 '14 at 16:50
  • Yes I created those with scaffolding. I''ll debug later tonight. Thanks for your time and help. BTW, does this ajax function supposed to update DB directly our does it supposed to call a method from 'OrdersController', if yes, which one? Can I specify another method which gets called and update only the status I need? – Atarang Nov 24 '14 at 16:57
  • @Atarang I edited the entire thing - just copy paste all that stuff into your orders/show.html.erb page. Just tested it again successfully. – AME Nov 24 '14 at 17:03