Reputation: 149
First post on here, so I apologize if some things are off (how I put in the code, if I'm not including enough, or if my question is too vague).
I am very, very new to RoR, and I'm starting by building a tic tac toe game. I already built it to work on the command line, and now I am trying to make it web-based. I have a clickable board, with X and O images that pop up. This is tied to a form below (which I will make invisible once I have everything working) that registers which player clicked which position.
At the moment, I'm having an issue of trying to switch players after the page is submitted. I am using jQuery for the click. I have each space pop up as "X" when clicked, I just can't figure out how, after the submit, to have the player changed to "O". Should I be doing that through jQuery, or Ruby? And, how would I do that?
To clarify, I realize that my code might not be the cleanest, but at the moment I'm worried more about functionality, and will later make it more presentable.
jQuery:
$(document).ready(function(){
$(".square").click(function(){
// Gather the position that was clicked
var number = $(this).data("position");
// Locate the game form
var form = $("form");
// Locate the input field corresponding to that position
var input = $("input[data-position='" + number + "']");
// Set the value of that input field to "X" or "O"
input.val("X");
// Submit the form
form.submit();
});
});
Ruby:
def create
@game = Game.new(game_params)
@game.save
redirect_to @game
end
def update
@game = Game.find(params[:id])
@game.update(game_params)
redirect_to @game
end
def show
@game = Game.find(params[:id])
end
private
def game_params
params.require(:game).permit(:player_1, :player_2, moves_attributes: [:player, :id])
end
HTML form:
<%= nested_form_for @game do |f| %>
<%= f.fields_for :moves do |move_form| %>
<p>
<%= move_form.label :position %><br>
<%= move_form.text_field :player, data: {position: move_form.object.position} %>
<%= move_form.hidden_field :id %>
</p>
<% end %>
<input type="Submit">
<% end %>
HTML game board:
<div id="board" align = center>
<table>
<tr>
<td data-position="0" class="square <%= class_for_move(0)%>"></td>
And it's the same for each one of the 9 squares on the board.
Link to the next blocker for those following: jQuery .click function is not working without a string
Upvotes: 2
Views: 181
Reputation: 3898
You're going to need to keep the current player state somewhere between form submits.
There are a number of ways you can do this. One way (maybe not the best way) is to store the current player in the session hash and set it with each form submit. Something like (in game_controller.rb):
def switch_player
session[:current_player] = session[:current_player] == 'X' ? 'O' : 'X'
end
Make a call to switch_player
at the end of your form submit action in the controller
Then just add it to your board (which right now is a <p>
tag, probably should be a div
) like:
<p id="board" data-current-player: <%=session[:current_player] %> >
<%= move_form.label :position %><br>
<%= move_form.text_field :player, data: {position: move_form.object.position} %>
<%= move_form.hidden_field :id %>
</p>
Then you can just pull it out with jQuery:
$(document).ready(function(){
var currentPlayer = $(#board).data("current-player");
$(".square").click(function(){
// Gather the position that was clicked
var number = $(this).data("position");
// Locate the game form
var form = $("form");
// Locate the input field corresponding to that position
var input = $("input[data-position='" + number + "']");
// Set the value of that input field to "X" or "O"
input.val(currentPlayer);
// Submit the form
form.submit();
});
});
As an aside, it looks like your practicing with Rails, utilizing CRUD, REST and form updates and the like. This works best with more data intensive applications, where the model represents some table in a database and you use forms to manipulate the models and, thus, the database. I bring this up because a tic-tac-toe game may not be the best domain to get to know basic Rails functionality. Something like a todo list might be more appropriate.
If I could give you a little more unasked advice, I would suggest using something like Sinatra. Tic-tac-toe doesn't really need a database backend, and Sinatra will give you some good exposure to routing, templating, handling URLs, without the overhead of Rails. You could think of it as Rails lite. And much of what you learn there will transfer over when you start working with Rails.
Upvotes: 1
Reputation: 23939
It looks like you're comfortable with data attributes, you could stash the next symbol in your page somewhere logical, and find it when the form is clicked.
So instead of:
input.val("X");
You would do:
input.val($('#some-id').data('next-symbol'));
Looking at your code, it seems like you're basically trusting the browser to send you the right symbols for the entire game every time. Consider changing this to having the form only submit the position of the selected square, and have more logic in your Game
class to keep track of who made the move and update the game world accordingly.
I think you'll find everything gets simpler this way, and bonus I can't cheat by changing the underlying DOM and submitting a game where I have all 9 squares filled with X's and none of your O's!
Upvotes: 0