当我尝试将我的应用程序部署到Heroku时,我收到500错误(它在我的localhost上工作正常)。不知道为什么会这样。
我该如何解决?错误详情如下......
错误详情
2012-01-03T10:33:49+00:00 app[web.1]: Started GET "/" for
2012-01-03T10:33:49+00:00 app[web.1]: Processing by PagesController#home as HTML
2012-01-03T10:33:49+00:00 app[web.1]:
2012-01-03T10:33:49+00:00 app[web.1]: Completed in 15ms
2012-01-03T10:33:49+00:00 app[web.1]:
2012-01-03T10:33:49+00:00 app[web.1]: app/controllers/pages_controller.rb:7:in `home'
2012-01-03T10:33:49+00:00 app[web.1]: ActiveRecord::StatementInvalid (PGError: ERROR: syntax error at or near "["
2012-01-03T10:33:49+00:00 app[web.1]: : SELECT "posts".* FROM "posts" WHERE (user_id IN ([]) OR user_id = 2) ORDER BY posts.created_at DESC LIMIT 30 OFFSET 0):
2012-01-03T10:33:49+00:00 app[web.1]:
2012-01-03T10:33:49+00:00 app[web.1]: LINE 1: ...sts".* FROM "posts" WHERE (user_id IN ([]) OR use...
2012-01-03T10:33:49+00:00 app[web.1]:
页面控制器
class PagesController < ApplicationController
def home
@title = "Home"
if signed_in?
@post = Post.new
@feed_items = current_user.feed.paginate(:page => params[:page])
end
end
用户模型
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
has_many :relationships, :foreign_key => "follower_id",
:dependent => :destroy
has_many :reverse_relationships, :foreign_key => "followed_id",
:class_name => "Relationship",
:dependent => :destroy
has_many :following, :through => :relationships, :source => :followed
has_many :followers, :through => :reverse_relationships, :source => :follower
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false}
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
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
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
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
def feed
Post.from_users_followed_by(self)
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
end
发布模型
class Post < ActiveRecord::Base
attr_accessible :content
belongs_to :user
validates :content, :presence => true, :length => { :maximum => 140 }
validates :user_id, :presence => true
default_scope :order => 'posts.created_at DESC'
scope :from_users_followed_by, lambda { |user| followed_by(user) }
def self.from_users_followed_by(user)
following_ids = user.following_ids
where("user_id IN (#{following_ids}) OR user_id = ?", user)
end
private
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
{ :user_id => user })
end
end
答案 0 :(得分:3)
这是一个代码问题,而不是Heroku问题。
问题在于您的用户模型中的Post.from_users_followed_by(self)
。无论它包含什么,都不是Postgres友好的,或者不受nil值的保护。
答案 1 :(得分:1)
你的问题在这里:
def self.from_users_followed_by(user)
following_ids = user.following_ids
where("user_id IN (#{following_ids}) OR user_id = ?", user)
#------------------^^^^^^^^^^^^^^^^
end
您的following_ids
将是一个数组,当您"#{array}"
时,您会收到[]
和[11, 23, 42]
之类的内容。因此where
最终会看起来像这样:
where("user_id IN ([]) OR user_id = ?", user)
where("user_id IN ([11, 23, 42]) OR user_id = ?", user)
这些都不包含有效的SQL。有些数据库可能会忽略偏离括号,但PostgreSQL不会。
您需要进行两项更改:
user_id IN (...)
为空,请不要包含following_ids
。执行c in ()
不是有效的SQL,因此您不希望这样做。同样,一些数据库是宽容和宽容的,PostgreSQL(谢天谢地)都没有。IN
提供值;就此而言,根本不要对你的SQL使用字符串插值(除非绝对没有其他方法,这很少见):我们不是在1999年编写PHP,我们现在应该知道更好。幸运的是你(以及我们其他人),如果你把一个数组交给占位符值,AR会做正确的事情。这样的事情会更好:
def self.from_users_followed_by(user)
following_ids = user.following_ids
if(following_ids.empty?)
where('user_id = ?', user)
else
where('user_id in (?) or user_id = ?', following_ids, user)
end
end
你也可以这样做:
def self.from_users_followed_by(user)
following_ids = user.following_ids
if(following_ids.empty?)
where('user_id = ?', user)
else
following_ids.push(user.id)
where('user_id in (?)', following_ids
end
end
或者,我最喜欢的,像这样:
def self.from_users_followed_by(user)
where('user_id in (?)', user.following_ids + [user.id])
end