Reputation: 1086
My 'frontend' is a JS script that loads a HTML5 canvas and draws a X * Y grid, it then draws an alien at some default (X,Y) coordinate in the grid.
I have some ruby classes that define how this alien moves. For now, it's just +- on the X,Y plane. I want to be able to click on a 'move forward' button in the browser, and for that to send a request to the ruby script which will then calculate the new position and send a response with the coordinates.
Could somebody point me in the right direction? I can't get the logic around doing this. I've read into Sinatra, AJAX, templates, and so on but nothing is helping.
Edit
app.rb
require 'sinatra'
require_relative 'alien'
get '/' do
haml :home
end
get '/new_alien' do
@alien = Alien.new 1,1,:N # create a new alien
@x = @alien.x # set the x coordinate
@y = @alien.y # set the y coordinate
%Q|{ "x":#{@x}, "y":#{@y} }| # return a string with the coordinates
end
home.haml
!!!
%html
%head
%link{:rel => :stylesheet, :type => :"text/css", :href => "/css/main.css"}
%body
.wrapper
%script(src="http://code.jquery.com/jquery-2.1.1.min.js")
%script(src="/js/grid.js")
When the /
path is loaded, home.haml should load and I would like for the x
and y
values to be passed to a JS script which uses these coordinates to draw an image. I'm not sure how to do this exactly.
Upvotes: 1
Views: 147
Reputation: 48599
1) Use javascript to intercept the button click by installing an onclick event handler
on the button.
2) The onclick event handler
function should use javascript(or jquery) to send an AJAX request to the server. The AJAX request should include any relevant data that your server side ruby script needs to produce its calculation. Your AJAX request will specify a certain url, e.g.
"/calculate_new_position?x=10&y=20"
3) Your Sinatra app, which is located on the server, can be as simple as this:
require 'sinatra'
get '/calculate_new_positon' do
x_coord = params[:x] #=> 10
y_coord = params[:y] #=> 20
#Do calculation here:
new_x = x_coord * 20
new_y = y_coord - 3
#The following string is the response:
%Q|{ "new_x":#{new_x}, "new_y":#{new_y} }|
end
When your server receives a GET request for the url /calculate_new_position?x=10&y=20
, it will cause the code above to execute. Sinatra will automatically insert any GET (or POST) variables in a Hash called params
. The return value of the block will be the response
that is sent back to the browser.
4) Your javascript AJAX code will include a function that is called when the response
from the server is received. The function will contain something like this:
obj = JSON.parse(json_str); //--> obj = {"new_x":22, "new_y":-3};
new_x = obj["new_x"];
new_y = obj["new_y"];
#Use javascript to move figures to new coordinates.
Here is an example:
~/ruby_programs/sinatra_4app$ tree
.
├── models
│ └── alien.rb
├── public
│ └── js
│ └── grid.js
├── routes.rb
└── views
└── home.haml
4 directories, 4 files
home.haml:
!!! 5
%html
%body
%button#forward_button Move forward
%script{:type => "text/javascript",
:src => "http://code.jquery.com/jquery-2.1.1.min.js"}
%script{:type => "text/javascript",
:src => "/js/grid.js"}
The result after sinatra executes home.haml:
<!DOCTYPE html>
<html>
<body>
<button id='forward_button'>Move forward</button>
<script src='http://code.jquery.com/jquery-2.1.1.min.js' type='text/javascript'></script>
<script src='/js/grid.js' type='text/javascript'></script>
</body>
</html>
routes.rb:
require 'sinatra'
require_relative 'models/alien'
get '/' do
haml :home, :format => :html5
#Sinatra automatically looks for templates in a 'views' directory, so the line above looks for the file: views/home.haml
end
get '/new_alien' do
alien = Alien.new 1,1,:N
alien.calculate_new_position
new_x = alien.x
new_y = alien.y
%Q|{ "new_x":#{new_x}, "new_y":#{new_y} }| #return a string in json format containing the new coordinates
end
alien.rb:
class Alien
attr_accessor :x, :y, :direction
def initialize(x, y, direction)
@x = x
@y = y
@direction = direction
end
def calculate_new_position
self.x += 2 #Changes @x using the accessor method rather than changing @x directly, which is considered good practice.
self.y -= 2
end
end
grid.js:
$(document).ready(function() {
#This function executes when all the html elements exist, i.e. when
#the document is 'ready'--you can't search for an element until it exists.
#Search for an element whose id="forward_button" and install an event handler function
#for its onclick event:
$("#forward_button").click(function() {
#This function executes when the button is clicked
#Get current x, y coords somehow....
var x = 10;
var y = 20;
var url = "/new_alien?x=" + x + "&y=" + y;
$.getJSON(url, function(js_obj) { #This is a specialized version of $.ajax()
#This function is called when the browser
#receives the response returned by the server
new_x = js_obj["new_x"];
new_y = js_obj["new_y"];
#Do something with new_x and new_y...
console.log( "Response received!" );
console.log( "new_x= " + new_x);
console.log( "new_y= " + new_y);
});
});
});
Note that js comments start with //, so the code above will cause errors if you don't replace the # with //. I'm using the # to get the light gray shading, which makes the code easier to read.
1) Start the server:
~/ruby_programs/sinatra_4app$ ruby routes.rb
2) Then enter the following url in your browser:
http://localhost:4567/
3) Then open the Console window for whatever browser you are using. In Firefox, the console window is under:
Tools>Web Developer>Web Console
In Chrome, it's:
View>Developer>Javascript Console
4) Click on the "Move forward" button; then check the output in the Console window.
Upvotes: 2