Counter span on my like button not updating with ajax - javascript

I have followed the answers suggested on other questions on SO (this question and this question ), but for some reason I can't get my like button counter to work properly with ajax. My counter changes only after a refresh, any help is appreciated thanks!
meals_controller.rb
def upvote
#meal.upvote_from current_user
if request.xhr?
render json: { count: #meal.get_upvotes.size, id: params[:id] }
else
redirect_to meals_path
end
end
def unlike
#meal.unliked_by current_user
redirect_to meals_path
end
routes.rb
Rails.application.routes.draw do
devise_for :users
root 'home#index'
resources :meals do
member do
put "like" => "meals#upvote"
put "unlike" => "meals#unlike"
end
end
#upvote.coffee
$(document).on 'ajax:success', 'a.vote', (status,data,xhr)->
$(".votes-count[data-id=#{data.id}]").text data.count
return
#index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing Meals</h1>
<% #meals.each do |meal| %>
<%= meal.title %>
<br>
<%= meal.descriptionttext %>
<%= link_to like_meal_path(meal), class: "vote", method: :put, remote: true do %>
<button>
<span class="votes-count" data-id="<% meal.id %>"><%= meal.get_likes.size %></span>
</button>
<% end %>
<%= link_to unlike_meal_path(meal), method: :put do %>
<button type="button">
<span><%= meal.get_upvotes.size%></span>
</button>
<% end %>
<br>
<% end %>
<br>

Related

Rails 4 Ajax call only works once

I have an app where you can post Links. Each Link has_many Comments
I've set up ajax where a user can upvote a particular comment. Currently, a user can successfully upvote a comment via ajax the first time, but if the user then attempts to upvote a different comment on the same page then the ajax breaks and the value doesn't get updated until the page is refreshed.
comments_controller.rb:
def comment_upvote
#comment = Comment.find(params[:id])
#link = Link.where(id: #comment.link_id)
#comment.upvote_by current_user
respond_to do |format|
format.html {redirect_to link_path(#link)}
format.js {}
end
end
views/comments/_comment.html.erb:
<div class="well">
<h2><%= comment.title %></h2>
<p class="text-muted">Added by <strong><%= comment.author %> <%= comment.author_last_name %></strong> on
<%= l(comment.created_at, format: '%B, %d %Y %H:%M:%S') %></p>
<blockquote>
<p><%= comment.body %></p>
</blockquote>
<p><%= link_to 'reply', new_comment_path(parent_id: comment.id, link_id: #link.id) %></p>
<%= link_to pointup_comment_path(comment.id), method: :put, remote: true do %>
+
<% end %>
<div id="comment-votes">
Votes: <%= comment.get_upvotes.size %>
</div>
views/comments/comment_upvote.js.erb:
$('#comment-votes').html("<%= j render "upvotes", locals: { #comment => #comment } %>")
views/comments/_upvotes.html.erb:
Votes: <%= #comment.get_upvotes.size %>
Is there an easy way to fix this? Let me know if you need extra detail.
The problem here is that there are many divs with id comment-votes. When you try to get the element by id, it always get the same div.
To solve this problem you need to make the id unique per comment.
views/comments/_comment.html.erb:
<div id="comment-votes-<%= comment.id %>">
Votes: <%= comment.get_upvotes.size %>
</div>
After setting the unique comment ids. You just need to change the ajax call.
views/comments/comment_upvote.js.erb:
$("#comment-votes-<%= #comment.id %>").html("<%= j render "upvotes", locals: { #comment => #comment } %>")

The action 'show' could not be found for CommentsController

I'm all new, and I'm trying to create a blog using Ruby on rails on windows 8.1.
I've made most of it, but it gives me "The action 'show' could not be found for CommentsController".
I've read several places it might be a lack of a javascript, but I have no idea where to post it.
<h1><%= #post.title %> </h1>
<%= #post.text %>
<h2>Comments</h2>
<% #post.comments.each do |comment| %>
<p><%= comment.text %></p>
<p><%= time_ago_in_words comment.created_at %></p>
<p><%= link_to "Delete comment", [#post, comment], :method => :delete, :confirm => "Are you sure?" %></p>
<% end %>
<%= form_for [#post, #post.comments.build] do |f| %>
<p><%= f.text_area :text, :size => '40x10' %></p>
<p><%= f.submit "Post comment" %></p>
<% end %>
<p>
<%= link_to "Tilbage", posts_path %>
|
<%= link_to "Rediger", edit_post_path(#post) %>
|
<%= link_to "Slet", #post, :method => :delete, :confirm => "Er du sikker?" %>
</p>
This is my code in question. Any help is appreciated :)
Edit: If there is other parts you need, just let me know
Edit:
CommentController
class CommentsController < ApplicationController
def create
params.permit!
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
#comment.save
redirect_to #post
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to #comment.post
end
end
Routes
Rails.application.routes.draw do
get 'comments/create'
get 'comments/destroy'
resources :posts do
resources :comments
end

Button doesn't update in Ajax on Users Index page - Rails Tutorial 4

TLDR: Trying to add a follow/unfollow button to the Users#Index action but when clicking on the button nothing happens.
I have followed Michael Hartl's Rails Tutorial app and now that it's complete I want to add extra functionality for the Follow/Unfollow button. Currently, you can only follow/unfollow a user after visiting their profile page thru the Users Show action. I've attempted to expand this functionality to the Index page of the Users controller so that instead of having to visit each user's profile page in order to follow/unfollow them, a follow button will also appear next to their name in the Index view.
The code that works initially for the follow/unfollow button on the Users Show action:
users_controller.rb
https://gist.github.com/anonymous/9602598
show.htlm.erb for users view
https://gist.github.com/anonymous/9602616
_follow_form.htlm.erb partial for users view
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
_follow.html.erb partial for users view
<%= form_for(current_user.relationships.build(followed_id: #user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
_unfollow.html.erb partial for users view
<%= form_for(current_user.relationships.find_by(followed_id: #user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
create.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
index.html.erb inside of the users view
<%= render #users %>
_user.html.erb partial inside of users view
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
I've tried a few different approaches that so far have been fruitless
First I tried simply rendering the follow_form partial inside of the _user partial just like it's done for the User Show view
_user.html.erb partial inside of users view
<%= render 'follow_form' if signed_in? %>
this resulted in the following error: NoMethodError in Users#index "undefined method `id' for nil:NilClass" and it hilights the following line of code inside of the follow_form partial
<% if current_user.following?(#user) %>
After mucking around with the variables and the controller for a few hours I finally managed to get the buttons to show properly on the index page with the following code inside of the _user.html.erb partial
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(#current_user.relationships.find_by(followed_id: #users),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: #users),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
This code however, only shows the correct follow/unfollow buttons for each user but when you click a button nothing happens. I also attempted to edit the JS files with the following code
create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#user").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#user").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
This didn't have any effect.
The more I tinker with different parts of the code the more it's confusing me. Here is my relationships controller for good measure.
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
I know it's alot but if anyone can help shed some light on my situation I would be very grateful. This is my first venture outside of tutorials and I figured it would be a good idea to try and add features to an already working project instead of start something from scratch.
Just in case anybody was on this question and was still looking for the correct Ajax code. This works with the existing controller and nothing else will have to be changed.
create.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/unfollow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
destory.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/follow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
_user.html.erb
<div class="col-md-2">
<% unless current_user?(user) %>
<% form_id = user.id.to_s %>
<div id="follow_form_<%= form_id %>">
<% if current_user.following?(user) %>
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
<% else %>
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
</div>
This is my first post. Yay! Hope it helps someone!
Use the following code in _user.html.erb partial:
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
I made couple of changes to the code in form_for method call in 2 places:
#current_user should be current_user.
Secondly, followed_id: #users should be followed_id: user.id

has_many and accepts_nested_attributes_for with nested forms and jquery/ajax

I'm trying to create a nested form where there is a "+" button which adds fields via jquery and ajax. I am doing it adding a step at once, so untill now I am able to add a simple text pushing the "+" button, but, as I have just said, I want to add some fields.
I have the followings:
new.html.erb
<h1>New Campaign</h1>
<%= form_for #campaign, html: { multipart: true } do |f| %>
....
<div class="goods">
<%= render "goods/good", f: f, child_index: Time.now.to_i %>
</div>
<div class="actions">
<%= link_to '+', add_good_row_path(params[:campaign]=#campaign, params[:f] = f), remote: true, class: 'btn btn-large btn-success' %>
<%= f.submit 'Crea', class: 'btn btn-large btn-warning' %>
</div>
<% end %>
goods/_good.html.erb
<%= f.fields_for :goods, #campaign.goods.build, child_index: child_index do |good| %>
<%= good.text_field :name, placeholder: 'Nome' %>
<%= good.text_area :description, placeholder: 'Descrizione' %>
<%= good.text_field :cost, placeholder: 'Costo' %>
<% end %>
campaigns_controller.rb
class CampaignsController < ApplicationController
....
def add_good_row
respond_to do |format|
format.js
end
end
end
add_good_row.js.erb
$('.goods').append("hello");
I think that I understood the problem, it is to pass a f variable, a #campaign variable and a child_index to the partial, but how can I do that via jquery?
Hope I was clear...
Have a look at this gem.
I think it's what you are looking for
https://github.com/nathanvda/cocoon

In my comment app when i refresh the page comments disappears

My comment app works ,but the only problem is whenever i refresh the page the comments disappear.In the log it shows the body is inserted in the comments table(it is saved).What am i doing wrong here?Any help will be appreciated.Thank you in advance.
View#show
<div id="comments"></div>
<%= form_for :comment,:remote => true,:url=> {:controller=>"comments",:action=>"create"},:html => { :id => 'new-comment'} do |f| %>
<%= f.text_area(:body) %>
<div class="errors"></div>
<%= f.submit "post" %>
<% end %>
Comment controller
class CommentsController < ApplicationController
respond_to :js
def create
#deal=Deal.find(1)
#comment =#deal.comments.build(params[:comment])
#comment.save
respond_with( #comment, :layout => !request.xhr? )
end
def show
#comment=Comment.all
#deal=Deal.find(1)
#comment=#deal.comments
end
end
create.js.erb
$('#comments').append("escape_javascript(#comment.body)");
I don't see where your comments are being display in your show template.
How about something like this?
<div id="comments">
<% #comments do |comment| %>
<%= comment.body %>
<% end %>
</div>
<%= form_for :comment,:remote => true,:url=> {:controller=>"comments",:action=>"create"},:html => { :id => 'new-comment'} do |f| %>
<%= f.text_area(:body) %>
<div class="errors"></div>
<%= f.submit "post" %>
<% end %>
Note, you need to set #comments in the controller or use another method of getting comments, e.g. #view = View.find(params[:id]) and <%= #view.comments.each do |comment| %>...
I guess the comment has a belongs_to relationship with the post that is not assigned.
In your form you should add
<%= f.hidden_field :post_id, #post.id %>
If you want to play by the book, post_id should be attr_protected and instead assign it manually in the comments controller
#comment = Comment.new(params[:comment])
#comment.post_id = params[:comment][:post_id]
#comment.save

Categories

Resources