我创建了一个简单的网络表单,用户可以在其中输入一些搜索条件来查找场地,例如价格范围。当用户点击“查找”时,我使用活动记录来查询数据库。如果填写了所有字段,这一切都很有效。当一个或多个字段保持打开状态时出现问题,因此值为null。
如何在我的控制器中解决这个问题?我应该首先检查一个值是否为null并根据它创建一个查询?我可以想象我最终得到了许多不同的查询和大量的代码。必须有更快的方法来实现这一目标吗?
控制器:
def search
@venues = Venue.where("price >= ? AND price <= ? AND romance = ? AND firstdate = ?", params[:minPrice], params[:maxPrice], params[:romance], params[:firstdate])
end
答案 0 :(得分:11)
您可能希望过滤掉随请求一起发送的所有空白参数。
这是一个快速干燥的解决方案,用于过滤空白值,仅触发数据库的一个查询,并使用Rails&#39;来构建where子句。 ActiveRecord ORM。
正如@DanBrooking所指出的,这种方法可以防止SQL注入。 Rails 4.0+提供了强大的参数。&#34;您应该使用该功能。
class VenuesController < ActiveRecord::Base
def search
# Pass a hash to your query
@venues = Venue.where(search_params)
end
private
def search_params
params.
# Optionally, whitelist your search parameters with permit
permit(:min_price, :max_price, :romance, :first_date).
# Delete any passed params that are nil or empty string
delete_if {|key, value| value.blank? }
end
end
答案 1 :(得分:1)
尝试以下代码,它将忽略那些不存在的参数
conditions = []
conditions << "price >= '#{params[:minPrice]}'" if params[:minPrice].present?
conditions << "price <= '#{params[:maxPrice]}'" if params[:maxPrice].present?
conditions << "romance = '#{params[:romance]}'" if params[:romance].present?
conditions << "firstdate = '#{params[:firstdate]}'" if params[:firstdate].present?
@venues = Venue.where(conditions.join(" AND "))
答案 2 :(得分:0)
我建议在Venue中制作方法
import bottle
from bottle import run, get, post, request, route, error, default_app
from socket import *
import serial
host = ''
port = 7000
@route('/system')
def login():
return '''
<form action="/system" method="post" class="pure-form pure-form-aligned">
<button type="submit" class="pure-button pure-button-primary">Connect</button>
</form>
'''
@route('/system', method='POST')
def syson():
our_socket = socket(AF_INET, SOCK_STREAM)
our_socket.connect((host, port))
message = "go"
our_socket.send(bytes(message,'UTF-8'))
reply = our_socket.recv(1024)
message = "go"
our_socket.send(bytes(message,'UTF-8'))
reply = our_socket.recv(1024)
return bottle.redirect("/system")
run(host='localhost', port=8000)
并在您的控制器中使用它
def self.find_by_price(min_price, max_price)
if min_price && max_price
where("price between ? and ?", min_price, max_price)
else
all
end
end
def self.find_by_romance(romance)
if romance
where("romance = ?", romance)
else
all
end
end
def self.find_by_firstdate(firstdate)
if firstdate
where("firstdate = ?", firstdate)
else
all
end
end
答案 3 :(得分:0)
这个问题的另一个解决方案,我认为更优雅,是使用具有条件的范围。 你可以做点什么
class Venue < ActiveRecord::Base
scope :romance, ->(genre) { where("romance = ?", genre) if genre.present? }
end
然后你可以链接那些,如果没有参数,它将作为AND工作,然后它不是链的一部分。
http://guides.rubyonrails.org/active_record_querying.html#scopes