所以我试图在模型中编写一个方法,允许我返回特定字段值大于0的帖子。
所以我的帖子中包含的字段基本上都是标签。基本上我发帖有四个字段,hiphop,electro,house和pop。每个字段的值介于0和10之间。
如果有人点击一个按钮,那么我就试图这样做。" Hip Hop"它将返回所有具有hiphop字段值大于0的帖子。
我知道这是错的,但我在想这样的事情
def self.tagSearch(query)
where("#{query} > 0")
end
在我的控制器中我会有类似的东西
def index
if params[:search]
@songs = Song.search(params[:search]).order("created_at DESC")
elsif params[:tag]
@songs = Songs.tagSearch(params[:tag]).order("created_at DESC")
else
@songs = Song.all
end
end
我不确定视图,但可能是一个传递标记值参数的按钮。问题是我只想把它当成一个按钮,我不需要它们输入任何东西。
我希望这不会让人感到困惑。
谢谢!
马特
答案 0 :(得分:2)
Rails支持"范围"它返回一个ActiveRecord::Relation
,这意味着你可以将它们链接在一起。
class Song
scope :tag_search, -> (something) { where(something > 0) }
scope :ordered, -> { order(created_at: :desc) }
end
class SongsController
def index
if params[:search]
@songs = Song.search(params[:search]).ordered
elsif params[:tag]
@songs = Songs.tag_search(params[:tag]).ordered
else
@songs = Song.all
end
end
end
我会想到这个的设计。
另外,tagSearch
功能非常危险。 SQL INJECTION!
答案 1 :(得分:2)
扩展RaVen帖子:
1)使用ruby命名约定tagSearch
应为tag_search
;方法是蛇形(带下划线的小写)。
2)where("#{query} > 0")
让你暴露于SQL注入攻击 - 建议安装制动器gem,这可能会暴露出像这样的安全问题:
3)您可以通过链接范围来简化代码,返回nil的范围不会影响查询
class Song
scope :search, -> (query) do
where("name LIKE ?", "#{query}%") if query.present?
end
scope :tag_search, -> (tag) do
where(tag > 0) if tag.present?
end
scope :ordered, -> do
order(created_at: :desc)
end
end
class SongsController
def index
@songs = Song.search(params[:search])
.tag_search(params[:tag])
.ordered
end
end
4)根据用户指定的列进行查询并避免sql注入:
这是一种方法,可能有其他更好的方法,比如使用模型arel_table
,无论如何这个很直接
scope :tag_search, -> (tag) do
where("#{self.white_list(tag)} > 0") if tag.present?
end
def self.white_list(column_name)
# if the specified column_name matches a model attribute then return that attribute
# otherwise return nil which will cause a sql error
# but it won't let arbitrary sql execution
self.attribute_names.detect { |attribute| attribute == column_name }
end