-1

This has been asked a few times, however, there seems to be no good answer on the web. To avoid replies or links which do not answer this question, I will rephrase it. A page has only a form with input text (and button). We post text to the server and want it just sent back and alerted. In other words, the view should have the line:

$.post(...,$("form").serialize(),function(reply){alert(reply);}); 

With PhP, the answer is an "echo" one-liner. Can this be done in Sinatra - I understand that backend frameworks are built around handling DOM manipulation themselves. I am asking this question because it would be nice to use a more expressive language such as Ruby also just for db interface/backend logic.

Edit: This is the /views/index.erb (with "/reply" in place of "reply.php" - otherwise index.html/index.php) part:

<script src="jquery"></script>

<form action="reply.php" method="post"><input type="text" name="t"></form> 

<script>
$(document).ready(function(){
   $("form").submit(function(event){
      event.preventDefault();
      $.post("reply.php",$("form").serialize(),function(reply){alert(reply);});
   });
});
</script>

Note that with event.preventDefault() we stay at / route and don't go into /reply.php, which would remove the form and print just the submitted text. In other words, this is what enables Ajax and we get a reply (only in alert) from the server with reply.php:

echo $_POST["t"];

With Sinatra, we need to have a routes.rb controller:

require 'sinatra'

get '/' do
  erb :index
end

post '/reply' do
  ...
end

Question: With index.html/reply.php we get an alert with posted text. How can index.erb/routes.rb be modified also to get an alert with posted text?

Mark Thomas
  • 37,131
  • 11
  • 74
  • 101
observer
  • 1
  • 1

1 Answers1

2

Yes, this can be done with Sinatra. Any route can return data from the server to the client; by default this is sent with a text/html mime type, but you can also return plain text with an appropriate mime type:

post "/reply.php" do
  content_type :text
  params['t']
end

If you want to echo more than just one value back, you can see all the request values by using the code from this question.

This will send the value of your variable back from the server, and the client-side JavaScript code that you have in your question will cause an alert() to show up.

Community
  • 1
  • 1
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • Thanks for the reply! The block you suggested works, but a route is required which overrides passing the reply to the alert. How to make the alert pop out? – observer Sep 21 '14 at 18:33
  • 1
    @observer you appear to be confused as to what happens on the browser vs the server. The "echo" above is the route, and can be anything, e.g. "/api/v1/echo". The alert happens in the browser. Whatever JS calls the backend echo service can trigger an alert in the browser. – Mark Thomas Sep 21 '14 at 18:48
  • @Mark Thomas I understand we have post "/route" do ... end with
    and $.post("/route",...,...). My question is: what is a possible echo service to trigger the alert or is it not possible because framework is a rigid structure with routes?
    – observer Sep 21 '14 at 19:06
  • 1
    @observer Are you asking how to poll the echo service or are you saying you want server-sent events? This has nothing to do with the framework, BTW. – Mark Thomas Sep 21 '14 at 19:10
  • @Mark Thomas My question is how to construct the PhP example with alert using Sinatra. Without this it is not possible to use Sinatra with complicated Single Page Applications, which BTW, can handle routing well since IE10 with HTML5 History API. The view .erb file contains the form and submit callback with only event.preventDefault(); and $.post(...alert(reply));. – observer Sep 21 '14 at 20:33
  • 1
    @observer This answer does what you want. In fact, you can even change "echo" to "/reply.php" and the javascript that you used with "PhP" will just work with your complicated Single Page Application ;) – ian Sep 23 '14 at 03:52
  • @iain It does indeed work, also with params[:t] instead of request['t']. My mistake was that the js part has to go into the layout.erb file, otherwise if it is in index.erb as above it is just not read. – observer Sep 23 '14 at 19:37
  • @observer if it's not being read are you sure you have `yield` somewhere in the layout? Look at the layout [here](http://www.sinatrarb.com/intro.html#Inline%20Templates) – ian Sep 24 '14 at 00:04