I am getting the below error for line 8. Learning from ch.11/12 of the railstutorial.org. I am using rails 3.1.3 and ruby 1.9.3 instead of what was suggested from the tutorial. I've looked around for others with the same error and haven't been able to find another example of this problem. Still a newbie to rails and this is my first post. Please help! Teach me what I missed. Thanks!
NoMethodError in Users#show
undefined method `following' for #<User:0xab068f0>
Extracted source (around line #8):
5: <td>
6: <a href="<%= following_user_path(@user) %>">
7: <span id="following" class="stat">
8: <%= @user.following.count %> following
9: </span>
10: </a>
11: </td>
Trace of template inclusion: app/views/users/show.html.erb
app/views/shared/_stats.html.erb:8:in `_app_views_shared__stats_html_erb__794775909_89084750'
app/views/users/show.html.erb:32:in `_app_views_users_show_html_erb__961188432_91976190'
Full Trace:
activemodel (3.1.3) lib/active_model/attribute_methods.rb:385:in `method_missing'
activerecord (3.1.3) lib/active_record/attribute_methods.rb:60:in `method_missing'
app/views/shared/_stats.html.erb:8:in `_app_views_shared__stats_html_erb__794775909_89084750'
show.html.erb
31: <%= render 'shared/stats' %>
32: <%= render 'shared/user_info' %>
_stats.html.erb
<% @user ||= current_user %>
<div class="stats">
<table summary="User stats">
<tr>
<td>
<a href="<%= following_user_path(@user) %>">
<span id="following" class="stat">
<%= @user.following.count %> following
</span>
</a>
</td>
<td>
<a href="<%= followers_user_path(@user) %>">
<span id="followers" class="stat">
<%= pluralize(@user.followers.count, "follower") %>
</span>
</a>
</td>
</tr>
</table>
</div>
models/relationship.rb
class Relationship < ActiveRecord::Base
attr_accessible :followed_id
belongs_to :follower, :class_name => "User"
belongs_to :followed, :class_name => "User"
validates :follower_id, :presence => true
validates :followed_id, :presence => true
end
db/migrate/..._create_relationships.rb
class CreateRelationships < ActiveRecord::Migration
def self.up
create_table :relationships do |t|
t.integer :follower_id
t.integer :followed_id
t.timestamps
end
add_index :relationships, :follower_id
add_index :relationships, :followed_id
add_index :relationships, [:follower_id, :followed_id], :unique => true
end
def self.down
drop_table :relationships
end
end
Edit: Here is the user.rb file
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :first_name, :last_name, :email, :password,
:salt, :password_confirmation, :zip_id,
:country, :birthdate, :gender, :photo
#paperclip
has_attached_file :photo,
:default_url => ":rails_root/public/images/default.png",
:url => "/images/user_photos/:id/:style/:basename.:extension",
:path => ":rails_root/public/images/user_photos/:id/:style/:basename.:extension",
:styles => {
:thumb => "150x150",
:small => "250x250" }
validates_attachment_size :photo, :less_than => 5.megabytes
validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png']
# associates microposts to users. The second part will destroy all posts by this user if you destroy the user
has_many :microposts, :dependent => :destroy
def feed
Micropost.from_users_followed_by(self)
end
has_many :reverse_relationships, :foreign_key => "followed_id",
:class_name => "Relationship",
:dependent => :destroy
has_many :followers, :through => :reverse_relationships, :source => :follower
def following?(followed)
relationships.find_by_followed_id(followed)
end
def follow!(followed)
relationships.create!(:followed_id => followed.id)
end
def unfollow!(followed)
relationships.find_by_followed_id(followed).destroy
end
email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :first_name, :presence => true,
:length => { :maximum => 30 }
validates :last_name, :presence => true,
:length => { :maximum => 30 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false },
:length => { :maximum => 50 }
validates :zip_id, :presence => true,
:length => { :within => 5..5 }, :numericality => true
validates :password, :presence => true,
:length => { :within => 6..40 },
:confirmation => true
before_save :encrypt_password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
end
Here is the following/followers from: controllers/users_controller.rb
def following
@title = "Following"
@user = User.find(params[:id])
@users = @user.following.paginate(:page => params[:page])
render 'show_follow'
end
def followers
@title = "Followers"
@user = User.find(params[:id])
@users = @user.followers.paginate(:page => params[:page])
render 'show_follow'
end
Firstly, 3.1.3 is the Rails Version and 1.8.7 seems to be Ruby Version rather than Rails. You should correct it. And there isn't following
method in the user
model according to what you've posted in the question. There is only following?(followed)
method and other methods but not following
method.
I think you're missing this part in your User class:
class User < ActiveRecord::Base
.
has_many :following, :through => :relationships, :source => :followed
.
end
See section 12.11 of the online book for more details.
After adding that line, and since now @user
will have #following
method to call to you can say @user.following.count
and it won't throw an error.