Reputation: 439
I'm trying to add twitter-esque feeds into my application by modifying the guide from Michael Hartl's book: https://www.railstutorial.org/book/following_users
There is a "follow" button that should turn into "unfollow" or vice versa when pressed. The form is submitting successfully (If I refresh the page, it changes the button to the correct version, and the relationships are being created in the database), but the button simply fails to change to the correct version without a full page refresh.
_follow_form.html.erb (partial loaded by main view page)
<div id="follow_form">
<% if current_user.following?(@restaurant) %>
<%= render 'restaurants/unfollow' %>
<% else %>
<%= render 'restaurants/follow' %>
<% end %>
</div>
_follow.html.erb (follow button)
<%= bootstrap_form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, @restaurant.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
_unfollow.html.erb (unfollow button)
<%= bootstrap_form_for(current_user.active_relationships.find_by(followed_id: @restaurant.id),
html: { method: :delete }, remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
Relevant controller
class RelationshipsController < ApplicationController
before_action :authenticate_user!
def create
restaurant = Restaurant.find(params[:followed_id])
current_user.follow(restaurant)
respond_to do |format|
format.html { redirect_to @restaurant }
format.js
end
end
def destroy
restaurant = Relationship.find(params[:id]).followed
current_user.unfollow(restaurant)
respond_to do |format|
format.html { redirect_to @restaurant }
format.js
end
end
end
create.js.erb
$("#follow_form").html("<%= escape_javascript(render('restaurants/unfollow')) %>");
$("#followers").html('<%= @restaurant.followers.count %>');
destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('restaurants/follow')) %>");
$("#followers").html('<%= @restaurant.followers.count %>');
Here is the error I am getting according to Chrome:
NoMethodError in Relationships#destroy
Showing /home/ubuntu/workspace/suburblia/app/views/restaurants/_follow.html.erb where line #2 raised:
undefined method `id' for nil:NilClass
Trace of template inclusion: app/views/relationships/destroy.js.erb
Rails.root: /home/ubuntu/workspace/suburblia
Upvotes: 1
Views: 62
Reputation: 10507
That's because @restaurant
is a class instance variable and as such it is available in your views, but restaurant
is a local variable, only available within the method (i.e. action) it is defined.
Your view calls for that variable in <%= @restaurant.followers.count %>
but since you were defining a local variable restaurant
, it wasn't available to your view and you got a undefined method 'id' for nil:NilClass
error; that is @restaurant
returned nil
instead of a Restaurant
object.
But when you changed it to @restaurant
you made it available to your view, so no more nil
values.
Upvotes: 1
Reputation: 439
I needed to change restaurant in the controller to @restaurant. Not sure why, but this worked. Any explanations would be cool!
Upvotes: 1