rails - how to change database values with a link
I am making a website using rails and I am in desperate need of help of how do I create a link that when clicked on it will update an attribute in the database but only when clicked on.I have this code:
<%= link_to (myproperty_path) do %>
<% @player.updat开发者_JS百科e_attribute("energy", @player.energy + 2) %><span>Take a Nap</span>
<%end%>
but the problem with this is that whenever I refresh the page it updates the attribute and when I go to another page on the website it updates the attribute again. It works when I click on it but I want it to work only when clicked on and that's it. Also, if I have two of these links on the same page, clicking on one link will act as if I'm clicking on both of the links at the same time. Here is what I have for the myproperty page:
<%= render 'sidebar' %>
<div id="yui-main" class="yui-b">
<h2>My Property</h2>
<br \>
<p><b>Property: </b><%= @player.property %><br \><br \>
<%= link_to (myproperty_path) do %>
<span>Take a Nap</span>
<% if @player.energy <= 98 && @player.energy != 100 %>
<% @player.update_attribute("energy", @player.energy + 2) %>
<% end %>
<% end %>
<br \>
<%= link_to (myproperty_path) do %>
<span>Sleep</span>
<% if @player.energy <= 96 && @player.energy != 100 %>
<% @player.update_attribute("energy", @player.energy + 4) %>
<% end %>
<% end %>
<% if @player.property != "My Car" %>
<b>Rent: </b><br \>
<br \>
<b>Bedroom</b><br \>
<% end %>
When I click on one of the links it adds 6 to the player's energy instead of just 2 or 4. enter code here
The link is on the myproperty page and I want it to go back to the myproperty page when clicked.
I haven't found a solution anywhere, I would really appreciate it if someone could help me out with this.
You are going about this in a fundamentally incorrect way. Rails is not designed to have business logic in your views - especially logic that updates records!
What you want is something like
<%= link_to "Take a nap", {:controller => "player_actions", :action => "nap", :id => @player.id} %>
<%= link_to "Sleep", {:controller => "player_actions", :action => "sleep", :id => @player.id } %>
in your view, and a corresponding controller action in your PlayerActionsController, or whatever you want to call it
def nap
player = Player.find(params[:id])
player.update_attribute(:energy, player.energy + 2)
end
def sleep
player = Player.find(params[:id])
player.update_attribute(:energy, player.energy + 4)
end
This way the actions only happen when the user clicks the link. Of course you will need to handle any redirects or ajax rendering as well, as well as validation, etc. But this is generally how your Rails code should be structured.
You should never use a GET
do any change to the server. Some browsers even "pre-fetch" data linked on the page, so it can make changes on the server without the user knowing it.
Always use a POST
whenever any change is to be made on the server, and browser will ask the user again whether the request is to be submitted again.
In CRUD - Create, Retrieve, Update, and Delete, only Retrieve should be done used GET
, the others are done through POST
. There is saying about using PUT
and DELETE
, but in practice, it is done through a POST
using a _method
param or a similar name.
See: Why Ruby on Rails books or references always say Update is by PUT and Destroy is by DELETE when it is not?
However you proceed with the HTTP verbs, your code has a concept flaw:
<%= link_to (myproperty_path) do %>
<% @player.update_attribute("energy", @player.energy + 2) %><span>Take a Nap</span>
<%end%>
When you open this page, the @player.update_attributes call will fire once while generating the link. The actual database change has to take place within a controller (in this case the routing target for myproperty_path).
Additionally I totally agree that you should use a POST request.
精彩评论