views:

201

answers:

2

I am new to rails so go easy on me. I have built a blog and I am attempting to add a "vote up" type feature to the /posts/index.html.erb page. Kind of like Facebooks's like feature. I have can successfully get the vote form to work. I have successfully been able to get the posts rendererd out through the <% @posts.each do |post| %> call. Here is where I have the problem. I then tell index, in the above, to also render for each post the vote form and also the <%= post.votes.count %> to display the total votes for each post and allow for submitting the form for each post. I am using AJAX to allow this all to work together.

Because of the way my /votes/create.js.rjs works it send the result to div id="votes", and in the <% @posts.each do |post| %> I wrap <%= post.votes.count %> in the votes div tag. But when create.js.rjs sends the data, it only updates the first div tag on the rendered html page.

So if you can imagine, like on facebook, when you click that you like something, the update happens not on the post you just clicked but back at the top of the page on another post, the first post. The vote count is represented from the element you clicked but it is on the wrong record.

Here is the code:

POSTS/INDEX.HTML.ERB

<% @posts.each do |post| %>
  <%= render :partial => post %>
  <%= render :partial => @post %>
 <div id="beltcomments">
  <div id="beltcommenttext">
    <div id="votebutton">
    <% remote_form_for [ post, Vote.new] do |f| %>
    <%= f.hidden_field :vote, :value => '1' %>
    <%= submit_tag '', :class => 'voteup' %>

    </div>
   <div id="vote"><br/>

     <%= post.votes.count %> People like the above BattleCry. <br/>

    <%= link_to "Comments (#{post.comments.count})", post %>
   </div>

   </div>
</div>

<br/>
<br/>
<br/>
<br/>

<% end %>
<% end %>

<div id="commenttime">
Copyright 2009, My Life BattleCry, LLC. 
</div>

/POSTS/CREATE.JS.RJS

page.replace_html  :votes, :partial => @vote
page[@vote].visual_effect :highlight

/POSTS/_VOTE.HTML.ERB

<% div_for vote do %>
  <%= @post.votes.count %> with your vote. Awesome!!!
  <div id="commenttime">
   Thanks for your vote. <br/>
   </div>

 <% end %>
+1  A: 

Check the actual rendered html first to see if there are unique ids for each of the elements. If not (and there are multiple elements with the same id), JS will default to update the first element in the list. You will need someway to uniquely identify which element you want to update. You can always do a simple

<% @posts.each_with_index do |post, i| %>

and then tag each element with

<%= f.hidden_field "vote-#{i}", :value => '1' %>

and then pass i to your rjs so it knows which field it is updating the count for.

Lukas
This is exactly what is happening. I think I might lead a little more navigational help with where to put the above. For instance, do I replace the current <% @posts.do each |post| %> with the code above, or do I add it underneath? Furthermore, do I have to then change the /votes/create.js.rjs to represent "vote-#{i}" and what is the correct syntax for that. Lastly, do I need to add something to the votes_controller.rb to pass this as you say? I was hoping there was something that did this. Thanks and let me know on the above if you can.
bgadoci
Correct, you would replace the current <% @posts.do each |post| %>. Correct, You would need to check in the rjs to look for something like "vote-#{i} (but see the next paragraph first).Correct, you would need to pass this to the controller, to pass to the rjs.This can be achieved by adding a :with => i to the form_remote_for or creating another hidden field that holds the value of i for each div. It will then get submitted with the form and you can just use "vote-#{params[:i]}" to get the value
Lukas
A: 

I don't fully understand the question. You're saying that when you click vote, it updates the count on the wrong post?

Assuming that's the case, I think your problem is that you're not uniquely identifying each post in your html. Side note, those divs etc shoudl be classes, that's not valid html. Anyway, you want each post to have a div with a unique identifying id say post_1, post_2 etc, and that should be sent with your ajax request, so the response knows which div to update.

One tip here, not related to your question, is to put that whole loop into a partial and render it with :collection. Makes for much nicer code.

brad
Thanks for the tip. The answer from Lukas seems like it will work...just need a little more detail about where to put everything. Since I am new to all this it takes me a little to figure things out.
bgadoci