在 Rails 中.where() 正在构建一些要在数据库上调用的 SQL。所以代码正在按照你的要求做:它会进入数据库并询问 image_url 不是 nil 的所有记录。
您在模型上定义的方法是:
在数据库中查找 image_url
如果有则返回
如果没有则返回 'http://someplaceholderimage.com'
为了实现您的既定目标:
我希望它返回所有产品,即使数据库中的 image_url 为 nil
您只需拨打Product.all
如果您不希望这是一个条件,我不确定您为什么要添加 .where.not()。
真正把要点带回家:期望数据库返回 :image_url 为 nil 或非 nil 的记录:
Product.where(image_url: nil).or(Product.where.not(image_url: nil)) 等同于调用Product.all
如果你想确保每条记录都有一个在数据库中定义的 URL,你可以在模型中做一个 before_validation 回调:
class Product < ActiveRecord::Base
validates :image_url, presence: true
before_save :default_image_url, if: ->{ image_url.blank? }
# def image_url
# super || 'http://someplaceholderimage.com'
# end
private
def default_image_url
image_url ||= 'http://someplaceholderimage.com'
end
end
如果您想知道哪些记录返回默认的:image_url,哪些记录在数据库中保存了:image_url,则需要重命名该方法,使其不会与数据库列名冲突:
class Product < ActiveRecord::Base
validates :image_url, presence: true
def image
image_url || 'http://someplaceholderimage.com'
end
end
现在调用 @product.image_url 将返回数据库中的任何内容,调用 @product.image 将返回 dB 值或占位符值。
但是,还有另一个问题:
您的
validates :image_url, presence: true 表示如果
:image_url 为空白,则该记录将永远不会保存。
因此,当您已经确保每条记录都不能有 nil 值时,让数据库查找潜在的 nil 值有点让人头疼。
终切线:
如果你必须让方法名和数据库列名匹配,我认为super不是一个好的选择。
我认为你应该使用这个:
def image_url
read_attribute(:image_url) || 'http://someplaceholderimage.com'
end
如果没有别的,它比super 更清楚发生了什么。