views:

45

answers:

4

I have a shop application and another site thats for a special promotion. I've used Active Resource to import products from the shop in to the promo site and added a shopping cart to add the products. However, to actually order the products I need to send the items to the shop application, creating a new cart there to finish the order.

I've made a demo 'RESTful' application to practice using xml to send data back and forth, so I'm trying to use the principles of REST for the real app. However, I need to send the products to a non-RESTful controller. Just to give you an idea of the Cart controller in the shop, here are its actions:

def index…
def add…
def checkout…
def update…
def remove…
def empty…
def apply_discount…
def remove_discount…
def apply_credits…
def remove_credits…
def stock_check…

# My action to accept items from carts in other apps
def cart_import…

And in routes.rb, the only route relating to the cart is currently

  map.cart              'cart/:action/:id',       :controller => 'shop/cart'

I've inherited the shop application from a previous developer, so I'd probably try to make it more RESTful if I was to make it from scratch.

Anyway, I'm pretty confident that I can get the cart to respond to XML, even without being defined with map.resources. My problem is how to send a hash of the cart items and quantities from the promo app.

To group the cart items and quantities I've collected the item's product id and quantity in to a hash:

<% @items = Hash.new %>
<% @cart.items.collect {|i| @items[i.product_id] = i.quantity} %>

Which when inspected gives the following output:

<%= Rails.logger.info @items.inspect %>
{1144=>2, 1143=>1}

So I figured to send them to the shop I could pass them in a posted link_to:

<%= link_to 'Export Cart', "http://shop.example.com/cart/cart_import", :items => @items, :method => :post %>

That doesn't seem to do anything, whereas omitting the first field appends the items to the URL in a format that looks sensible, but appears as a relative link on the promo application:

<%= link_to "http://shop.example.com/cart/cart_import", :items => @items, :method => :post %>

http://promo.example.com/cart?items[1143]=1&amp;items[1144]=2&amp;method=post

I'm sure the clue is in that the @items object needs to be passed in with the url, but since I can't use a named route I don't really know how to get it in there so that it is posted in the correct format.

Thanks for the help,

Gareth

A: 

the way you are passing in the parameters for the link_to method is assuming that :items is one of the link_to options, not one of the url options. this is an order of precedence issue and if you wrap your url inside parens then you can use the options available for the url_for method on your url, to build the path: http://apidock.com/rails/ActionView/Helpers/UrlHelper/url_for

Jed Schneider
I tried with url_for but get a "wrong number of arguments (2 for 1)" error:<%= link_to "export", url_for("http://shop.example.com/cart/cart_import", :items => @items), :method => :post %>
ghr
A: 

You can't use a link to generate a POST request. It is turning to a GET request. Better use javascript to generate a post request on click of a button or some other event.

Suman Mukherjee
I'm under the impression that you can. See the :method option here: http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
ghr
I guess that is to handle http verbs not supported by the browsers like the :delete, :put verb. Rails handles it internally as a parameter, and submits it as a post by JS(so much for the sake of REST). You may try something like this btw... <%= link_to "export", "http://shop.example.com/cart/cart_import?items=#{xyz}", {:method => :post} %> .... convert the @items hash to a url readable format.
Suman Mukherjee
A: 

I also tried

<%= link_to "export", {"http://shop.example.com/", {:items => @items}}, :method => :post %>

but that gives the following URL:

http://promo.example.com/cart?http://shop.example.com/cart/cart_import/[items][1141]=1&amp;http://shop.example.com/cart/cart_import/[items][1143]=1

Mad!

ghr
what does your items hash look like, and what should the resulting url look like?
Jed Schneider
A: 

In the end I made a helper:

def hash_to_params(items)
  result = ""
   i = 0
   items.each do |item|
     i > 0 ? result += "&" : result += ""
     result += "items[#{item[0]}]=#{item[1]}"
     i += 1
   end
  return result
end

Then for the link I called the helper:

<%= link_to "export", "http://shop.example.com/cart/cart_import?#{hash_to_params(@items)}", :method => :post %>

Pretty ugly way of doing it, but I really can't think of anything better?

Cheers,

Gareth

ghr