Rails如何根据表单访问来源实现提交后跳转至不同路径
差异化重定向实现方案
不要依赖request.referer做判断,这个值来自浏览器请求头,很容易被隐私插件、跨域安全策略拦截篡改,稳定性很差,优先选下面两种可落地的方案:
方案1:表单携带来源标识(生产环境首选)
不需要额外加数据库字段,直接在两个入口的表单里加一个不入库的隐藏参数标记来源即可:
- 两个页面渲染复用表单时,分别加不同的来源标记:
<!-- 提交后需要跳转到x_path的入口页面表单 --> <%= form_with model: @item do |f| %> <%= hidden_field_tag :form_source, "entry_x" %> <!-- 原有表单项保持不变 --> <% end %> <!-- 提交后需要跳转到y_path的入口页面表单 --> <%= form_with model: @item do |f| %> <%= hidden_field_tag :form_source, "entry_y" %> <!-- 原有表单项保持不变 --> <% end %>
- 控制器里直接根据参数判断跳转即可,修改后的create动作代码:
def create @item = Offer.new(offer_params) authorize @item if @item.save params[:form_source] == "entry_x" ? redirect_to(x_path) : redirect_to(y_path) else render :new end end
如果希望把来源标识存在Offer记录里做后续统计,就把隐藏字段换成模型字段f.hidden_field :source, value: "entry_x",同时在offer_params的白名单里加上:source即可。
方案2:Session暂存返回路径
如果不想改表单结构,可以在用户访问两个表单入口时,提前把要跳转的路径存在session里:
- 两个表单入口的action里提前写入session:
# 对应x路径的表单入口 def new_for_x session[:offer_redirect_path] = x_path @item = Offer.new render :new end # 对应y路径的表单入口 def new_for_y session[:offer_redirect_path] = y_path @item = Offer.new render :new end
- create动作里读取session值跳转,读完立刻删除避免残留:
def create @item = Offer.new(offer_params) authorize @item if @item.save redirect_path = session.delete(:offer_redirect_path) || y_path # 加默认兜底路径 redirect_to redirect_path else render :new end end
临时方案(不推荐生产用)
如果只是临时测试不想改现有逻辑,可以直接匹配请求来源:
if @item.save request.referer&.match?(/your_x_page_route_pattern/) ? redirect_to(x_path) : redirect_to(y_path) else render :new end
注意:该方案兼容性极差,部分现代浏览器默认的隐私保护策略、用户安装的广告拦截/隐私插件都会剥离Referer请求头,会导致判断完全失效,仅适合本地快速调试使用。
内容的提问来源于stack exchange,提问作者Cram-sallimra
相关产品推荐
相关产品推荐

