我已经自己搜索了Rails 4应用程序。现在我需要为用户提供不同的列进行搜索。我在视图的搜索表单中创建了一个下拉菜单,如下所示:
<%= form_tag manage_accounts_administrator_path, :method => 'get', :id => "search-form" do %>
<%= text_field_tag :search, params[:search], placeholder: 'Search Accounts' %>
<%= select_tag("search_criteria", options_for_select([['by account number', '1'],['by customer id', '2'],['by customer name (ex: Jane Doe)', '3']])) %>
<%= submit_tag "Search", :name => nil %>
<% end %>
然后在相应的控制器方法中,我正在这样做:
def manage_accounts
# criteria from the "Search by" select menu
if params[:search]
case (params[:search_criteria])
when 1
@criteria = id
when 2
@criteria = customer_id
when 3
@criteria = customer.firstname + ' ' + customer.lastname
end
@accounts = Account.where("#{@criteria} LIKE ?", "%#{params[:search]}%").page(params[:page]).per(15)
@table_heading = "Account Search Results"
else
@accounts = Account.order('id').page(params[:page]).per(15)
@table_heading = "Listing All Accounts"
end
respond_to do |format|
format.js
format.html {render 'manage_accounts'}
end
end
上面事例块中@criteria变量的三个可能值表示"帐户"模型的字段。如您所见,我期望发生的是使用"where"方法执行查询。这个语法是错误的,我得到错误:
ActiveRecord::StatementInvalid in Administrators#manage_accounts Mysql2::Error:您的 SQL 语法有错误;请查看手册 与您的MySQL服务器版本相对应,语法正确 在第 1 行的"类似 '%722586388%'("附近使用:从
accounts
WHERE ( 如 '%722586388%"(
显然我做错了。如何插入 @criteria 变量,类似于插入搜索参数的方式?错误告诉我的是变量被完全转义。我已经尝试(猜测(了数十种不同的标点符号组合,但无济于事。我觉得如果我的语法正确,这将起作用。
另外,我读到这是不好的做法,因为它使应用程序容易受到SQL注入的影响。那么,我应该如何以安全的方式写这个声明呢?
谢谢
它是带有 MySQL2 gem 的 rails 4.1.8,我是菜鸟。
你忘了用引号括住你的变量。当执行命中时
@accounts = Account.where("#{@criteria} LIKE ?", "%#{params[:search]}%").page(params[:page]).per(15)
@criteria
仍然会nil
.因此,例如,由 activerecord 生成的 sql 将被SELECT COUNT(*) FROM accounts WHERE ( LIKE '%722586388%')
而不是SELECT COUNT(*) FROM accounts WHERE (id LIKE '%722586388%')
。
因此,在您的案例中,您必须执行以下操作:
if params[:search]
case (params[:search_criteria])
when 1
@criteria = 'id'
when 2
@criteria = 'customer_id'
when 3
@criteria = 'customer.firstname'
end
if params[:search]
case (params[:search_criteria])
when 1
@criteria = "id"
when 2
#assuming you have a customer_id column in your accounts table
@criteria = "customer_id"
when 3
#assuming you have a customer_name column in your accounts table
@criteria = "customer_name"
end