Sinatra中如何通过路由URL变量引用数据库列?
解决Sinatra中通过URL动态指定数据库列更新的问题
嘿,我看你现在的问题是想通过URL里的:column参数动态更新数据库列对吧?你当前的代码里有个小坑——update(column: params[:value])里的column是个固定的符号,不是你从URL里拿到的动态列名,所以肯定不会生效。我来给你修正一下,顺便加个安全防护:
第一步:修正动态列名的引用方式
在Ruby里,如果你想用动态变量作为哈希的键,需要把字符串转成符号,然后用哈希键的动态写法。把原来的update(column: params[:value])改成下面这样:
get '/users/update/:id/:column/:value' do # 把URL里的column参数转成符号,作为哈希的键 update_params = { params[:column].to_sym => params[:value] } User.where(id: params[:id]).update(update_params) redirect back end
这样就能正确识别你从URL里传过来的列名(比如status)了。
第二步:加个安全白名单(非常重要!)
直接允许用户通过URL指定任意列名是很危险的——万一有人构造个URL修改password或者admin权限列怎么办?所以一定要加个白名单,只允许更新你指定的列:
get '/users/update/:id/:column/:value' do # 定义允许更新的列白名单 allowed_columns = [:status, :name, :email] # 换成你实际允许的列 column = params[:column].to_sym if allowed_columns.include?(column) update_params = { column => params[:value] } User.where(id: params[:id]).update(update_params) else # 可以加个错误提示,比如flash消息 flash[:error] = "不允许修改该列" end redirect back end
第三步:你的HTML代码可以保持不变
你原来的HTML链接写法是没问题的,它会正确传递id、column和value参数:
<a href="/users/update/<%= user.id %>/status/3">更新状态为3</a>
额外小提示
如果你的ORM是ActiveRecord(看起来是的),update方法如果找不到对应的用户不会报错,你可以加个判断来处理用户不存在的情况:
user = User.find_by(id: params[:id]) if user && allowed_columns.include?(column) user.update(update_params) else flash[:error] = "用户不存在或不允许修改该列" end
这样整个流程就既实现了你的需求,又保证了安全性~
内容的提问来源于stack exchange,提问作者jneusteter
相关产品推荐
相关产品推荐

