How can I emulate PUT/DELETE for Rails and GWT? - ruby-on-rails

I would like to make my application somewhat REST compliant. I am using Rails on the backend and GWT on the frontend. I would like to do updates and deletes. I realize I can do something like mydomain.com/:id/delete (GET) and accomplish the same thing. However, as I stated previously, I would like to have a REST compliant backend. Thus, I want to do mydomain.com/:id (DELETE) and have it implicitly call my delete method.
Now, it's my understanding that if a browser (my browser is GWT RequestBuilder) doesn't support DELETE/GET, Rails somehow accomplishes this task with a POST and some other url parameter. So, how can I accomplish this with a GWT RequestBuilder?

Rails does this with hidden attributes. The easiest way to figure this out would be to create a new rails application, generate a scaffold and have a look at the HTML in a browser.
Try this:
rails jp
cd jp
./script/generate scaffold RequestBuilder name:string
rake db:migrate
./script/server
Then navigate to http://localhost:3000/request_builders, click on New and have a look at the HTML. You'll see something like:
<form action="/request_builders" class="new_request_builder"
id="new_request_builder" method="post">
<div style="margin:0;padding:0">
<input name="authenticity_token" type="hidden" value="e76..." />
</div>
This is a creation, method is POST. Enter a name, save then Edit:
<form action="/request_builders/1" class="edit_request_builder"
id="edit_request_builder_1" method="post">
<div style="margin:0;padding:0">
<input name="_method" type="hidden" value="put" />
<input name="authenticity_token" type="hidden" value="e76..." />
</div>
Of course the form is sent with POST, but Rails hads a hidden field to simulate a PUT request. Same for deletion, but the scaffold will do it with a bit of Javascript:
var m = document.createElement('input');
m.setAttribute('type', 'hidden');
m.setAttribute('name', '_method');
m.setAttribute('value', 'delete');
To have this work with another front-end, you'll have to both:
Use the same style URL such as /request_builders/1 (RESTful URLs)
Include the hidden fields (Rails trick)

Like #skrat said, the _method=PUT workaround doesn't work for any kind of body where Content-Type is not x-www-form-urlencoded, e.g. XML or JSON. Luckily, there is a header workaround as well:
https://zcox.wordpress.com/2009/06/17/override-the-http-request-method-in-jersey/
So to update a REST resource, just do a POST to its address and add the header X-HTTP-Method-Override: PUT. Rails will interpret this as a PUT to the address.

Related

The action path of a form in Rails

The explanation below is big, but the question is really simple.
I'm doing a simple form project in https://www.theodinproject.com/paths/full-stack-ruby-on-rails/courses/ruby-on-rails/lessons/forms.
The first part where I am, I need to build a form manually - so that I can see how Rails does a lot for me when I use its helper methods.
I'm stuck in this point:
Specify the method and the action attributes in your tag (use $ rails routes to see which HTTP method and path are being expected based on the resource you created).
The routes.rb file looks like this:
resources :users, only: [:create, :new]
I don't know how to determine which method should I use for the form - post or get.
I don't know how to determine which action path I should use.
I've gone into the internet, Rails guides and etc, and have solved the other topics so far, but for this one I can't get through it.
My form so far:
<form action='/create' method="post" accept-charset="UTF-8">
<label for="username"></label>
<input type="text" id="username" name="username"><br>
<label for="email"></label>
<input type="text" id="email" name="email"><br>
<label for="password"></label>
<input type="text" id="password" name="password"><br>
<input type="submit" id="submit" value="Submit" >
</form>
Once I run it in the server and then submit the form - which I did - I should get:
"Submit your form and view the server output. Oops, we don’t have the right CSRF authenticity token (ActionController::InvalidAuthenticityToken) to protect against cross site scripting attacks and form hijacking. If you do not get an error, you used the wrong method from step 1."
Yes, Rails is smart) When u are sending the request to your server, Rails must know from where this request is coming. In short, if your form sending the CSRF token then Rails understand that u send this request, otherwise someone else on your behalf (CSRF attack).
To fix this bug u need to set <%= form_authenticity_token %> in your .erb view. It will generate this input that is below
<input type="hidden" name="authenticity_token" value="your_token_generate_by_rails">
Or for your testing purposes, u can use this in your controller which is processing your request. But never use it in future if you are don't know what are u doing)
skip_before_action :verify_authenticity_token
Hi there fellow Odin student!
It looks like you're doing this lesson. Me too!
It sounds like you're asking about what value to use with action attribute in the form.
When I created a form using the Rails formHelper methods, I inspected the HTML that Rails created when I was previewing the app/website (rails s). By opening up the Developer tools (F12 key, or right click the mouse and choose inspect)I was able to see that the form Rails created had an action equal to the name of the resource, with a forward slash in front of it.
So for your example, the resource created is "users". So the action attribute would be /users
to be complete, the solution would be something like: <form action="/users"...
Hope this helps!

run ruby file from ajax or on button click event

i am new in ruby.
so i have html code which includes one input field and button and i want when user click on that
button i have to run one ruby file which has system() method.
index.html
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<form method="post" action="/runMethod">
<input type="text" name="name" value="whatever">
<input class='btn btn-primary' type='submit' value='click'>
</form>
</body>
app.rb
system("wayback_machine_downloader userInput")
this is my two files code. i just want that if i click on button app.rb file should run with given input. is it possible?
Technically, you can by writing JS code which executes the ruby file as a script by first using shell, and given the computer has ruby installed you can simply run something like this:
var w = new ActiveXObject("WScript.Shell");
w.run('ruby Scripts\\test.rb');
This is however not a good way to do it as you don't get any response or error messages from the executed file, it might cause some security issues and you're executing business logic in the frontend, which is always bad.
The correct way to do it is to make the ajax call to a endpoint, where you can control the access to the information, set business logic in the backend and give proper response. I'm not sure if you're using rails, but if you're you should just create a new path in routes.rb and create a controller method for it.

Ruby - Set of inputs to array

I'm trying to have a dynamic set of inputs in a form, that start with just one, where you can add or remove them with add/delete buttons. Then upon submission of a form, it turns the values of the inputs into a hash then that hash into a string for storing. I really have no idea where to start. So any tips will be helpful.
If using javascript would help, I can go that route, but i'm not sure how to make the javascript and ruby talk.
Depending on your use-case, there are a few options you might want to use. Since you've tagged this with rails, I'm assuming you have access to JQuery. Here's one (very simple) example of how you might go about adding fields to the page dynamically using it:
https://jsfiddle.net/3Lyvw0jm/
If you plan on storing these fields in one of your models, you may want to take a look at implementing nested attributes.
As pretty much a common web thing (not Rails-specific), you would make the name value look like some_name[].
So instead of having multiple inputs with different names like this:
<input type='text' id='my_input_1' name='my_input_1' value='string_1' />
<input type='text' id='my_input_2' name='my_input_2' value='string_2' />
<input type='text' id='my_input_3' name='my_input_3' value='string_3' />
...where on the server you get:
params :my_input_1 # 'string_1'
params :my_input_2 # 'string_2'
params :my_input_3 # 'string_3'
You would have:
<input type='text' id='my_input_1' name='my_inputs[]' value='string_1' />
<input type='text' id='my_input_2' name='my_inputs[]' value='string_2' />
<input type='text' id='my_input_3' name='my_inputs[]' value='string_3' />
...where on the server you get:
params :my_inputs # ['string_1','string_2',string_3']

Refactoring HTML Markup from POST to GET

I have the following mark up in an ASP.NET MVC view (this is a Twitter Bootstrap search box):
<form action="#Url.Action("Results", "Search")" method="post">
<input type="text" class="search-query" id="SearchTerm" name="SearchTerm" />
</form>
This code works as expected, but using a post here is causing problems.
How can I change this markup to pass the search query as a URL argument instead? I'm not really sure how to even approach this short of keeping the existing markup and then redirecting from the controller. I'm thinking there must be a more efficient way than that.
You should be able to change method="post" to method="get" and get the desired result. The form, with a get method setting, pushes the fields in the form to the querystring by its default behavior.
As a workaround, if the default behavior doesn't suit you, you could catch the submit event of the form, and do:
window.location = form.action + "?SearchTerm=" + document.getElementById("SearchTerm").value
Something like that, where form is a reference to the form element. You can build the link and redirect using javascript, which is a get request.

Insert cakephp POST params into URL

I have this form below which contains two checkboxes to sort some products:
<form id="FiltreExtraForm" action="" method="post" name="FiltreExtraForm">
<input id="ProductsDeliveryPrice" type="checkbox" value="1" name="data[Products][delivery_price]"/>
<input id="ProductsPicture" type="checkbox" value="1" name="data[Products][picture]"/>
</form>
After POST I do the filtering but I also want to add received parameters to URL E.g: /products/index/delivery_price:1/picture:0 . Is this possible. How can I do that?
Note: I don't want to use GET to send form info.
Sounds like you are looking to do a Post/Redirect/Get.
Here are two examples of doing this in CakePHP:
Searching on surname
Searching on multiple fields
The two main advantages of redirecting a POST to a GET request are:
Users don't get the "Do you want to resubmit?" dialog if they refresh
The resulting page/query can be bookmarked
In the action to which you post, you could simply prepare the GET url and then redirect to this url. The action for that url then does the filtering.
If I understand you correctly (and I'm not sure that I do), you can pass additional variables on the query string of the form's action quite easily. Conventionally, that might look like this:
<form id="FiltreExtraForm" action="/products/index?delivery_price=1&picture=0" method="post" name="FiltreExtraForm">
Using Cake, you should be able to do the same without the traditional query string if you'd rather (though the traditional method above will also work):
<form id="FiltreExtraForm" action="/products/index/delivery_price:1/picture:0" method="post" name="FiltreExtraForm">
I would recommend looking at the form helper or at least constructing the action URI using helpers, but this should get you what you're after.

Resources