Ruby on Rails:如何将按钮与脚本关联实现点击执行
嘿,我来帮你把那个按钮和脚本关联起来!你之前搜到的思路完全没错——确实得通过路由、控制器来衔接前端按钮和后端脚本,咱们一步步来实操:
Rails默认不会自动加载app/scripts这个目录,直接放这儿后续可能会有加载问题。我建议把simple.rb移到lib/scripts/目录下(如果没有lib/scripts就手动新建一个),这样更符合Rails的规范。当然你要是不想移动,后面加载的时候写绝对路径也能行,但规范点总归没毛病~
修改后的脚本内容可以保留原样,要是想在Rails日志里看到输出,也可以换成日志输出(比puts更规范):
# lib/scripts/simple.rb # 用puts的话只会在终端显示,用Rails.logger.info能在Rails日志里看到 Rails.logger.info "hello from simple.rb!" puts "hello"
咱们需要一个控制器来接收按钮的点击请求,然后执行脚本。如果没有合适的现有控制器,直接新建一个就行:
在终端运行这条命令:
rails generate controller Scripts run
这个命令会生成ScriptsController,还有对应的run动作的视图文件(不过咱们大概率用不上这个视图,后面可以忽略它)。
接下来打开app/controllers/scripts_controller.rb,修改run方法,让它加载并执行脚本:
class ScriptsController < ApplicationController def run # 用load而不是require!因为require只会加载一次脚本,load每次都会重新执行 load Rails.root.join('lib', 'scripts', 'simple.rb') # 要是没移动脚本,就用这个路径:load Rails.root.join('app', 'scripts', 'simple.rb') # 执行完给前端一个反馈,比如跳回首页并显示提示 redirect_to root_path, notice: "脚本执行成功啦!" end end
打开config/routes.rb,添加一条路由,让前端的请求能找到咱们刚才写的run方法:
Rails.application.routes.draw do # 这里放你已有的其他路由... # 用POST请求更合适,因为是执行修改类的动作 post '/run_script', to: 'scripts#run' end
假设你的Bootstrap按钮在某个视图里(比如app/views/home/index.html.erb),咱们用表单把按钮包起来,让它提交到刚才配置的路由:
<!-- 用Rails的form_tag生成表单,按钮用Bootstrap样式 --> <%= form_tag '/run_script', method: :post do %> <%= button_tag "执行脚本", class: "btn btn-primary" %> <% end %>
要是想实现不刷新页面的异步执行,只需要给表单加个remote: true,然后写点JS处理反馈:
<%= form_tag '/run_script', method: :post, remote: true do %> <%= button_tag "执行脚本", class: "btn btn-primary" %> <% end %>
然后新建app/views/scripts/run.js.erb,写AJAX成功后的提示:
alert("脚本执行成功!"); // 也可以更新页面上的内容,比如: // document.querySelector('.script-status').textContent = "脚本已执行";
启动Rails服务器:
rails server
打开浏览器点击按钮,去终端看日志——你应该能看到hello或者hello from simple.rb!的输出啦~
- 安全问题:如果这个按钮是给公开用户用的,一定要加权限验证!比如用Devise的
before_action :authenticate_user!,防止陌生人随便执行脚本。 - 脚本逻辑:如果脚本里有复杂操作(比如读写文件、调用外部服务),最好把逻辑封装成方法,不要写裸代码,这样更易维护。
- 生产环境加载:如果把脚本放在
lib目录,生产环境默认不会自动加载lib下的文件,你可以在config/application.rb里加一行config.autoload_paths << Rails.root.join('lib'),不过用load带绝对路径的话,其实也不用加这个。
内容的提问来源于stack exchange,提问作者BrandoN

