Ruby on Rails实现仅允许用户周日创建帖子 其余时段禁止
实现方案
要做三层校验,避免用户绕开前端限制直接发请求创建:前端入口提示、控制器拦截、模型层兜底校验,三层都做才稳妥。
先修复你现有代码的基础bug
首先你控制器里的前置方法名拼错了:before_action 调用的是find_team_member,实际定义的方法是find_tem_member(少了字母a),这个会导致show/edit/update/destroy动作直接报错,先改对。
另外你的create动作有冗余逻辑:@team = Team.create(team_params) 这行已经执行了入库操作,后面再写@team.save是重复执行,而且没做创建失败的分支处理,后续优化时一起调整。
1. 核心兜底:模型层加创建校验
这层是最关键的,不管用户从哪个入口发创建请求,非周日都会被拦截,完全绕不开。
打开app/models/team.rb,修改为如下代码:
class Team < ApplicationRecord has_many :team_employees has_many :employees, through: :team_employees belongs_to :employee # 仅创建动作时触发日期校验 validate :only_allow_create_on_sunday, on: :create private def only_allow_create_on_sunday # 用Time.current会自动读取项目配置的时区,不要用Time.now避免时区偏差 unless Time.current.sunday? errors.add(:base, "仅每周日允许创建团队") end end end
2. 控制器层加前置拦截
给new、create两个动作加前置判断,非周日直接不让进入新建页面、也不处理创建请求,同时补上创建失败的返回逻辑。
打开app/controllers/teams_controller.rb,修改为如下代码:
class TeamsController < ApplicationController # 修正之前拼写错误的方法调用 before_action :find_team_member, only: [:show, :edit, :update, :destroy] # 给新建、创建动作加时间权限拦截 before_action :check_create_permission, only: [:new, :create] def index @teams = Team.all end def new @team = Team.new end def create @team = Team.new(team_params) # 主表校验通过再处理关联数据,避免主表创建失败生成无效关联记录 if @team.save params[:team][:team_employees].each do |emp_id| @team.team_employees.create(employee_id: emp_id) end redirect_to teams_path, notice: "团队创建成功" else # 校验失败返回新建页,展示错误信息 render :new end end private # 修正之前拼写错误的查找方法 def find_team_member @team = Team.find(params[:id]) end # 新增创建时间权限校验方法 def check_create_permission unless Time.current.sunday? redirect_to teams_path, alert: "仅每周日允许创建团队,请周日再操作" end end def team_params params.require(:team).permit(:employee_id,:name,:restaurant_name) end end
3. 视图层优化体验
首先在新建表单顶部加错误信息展示块,不然校验触发时用户看不到报错原因。在你写表单的app/views/teams/对应erb文件的表单最前面加:
<% if @team.errors.any? %> <div class="alert alert-danger"> <ul> <% @team.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %>
另外可以在团队列表页的新建按钮处加判断,非周日直接隐藏按钮加文字提示,减少无效点击。找到列表页跳转到新建页的链接,修改为:
<% if Time.current.sunday? %> <%= link_to "新建团队", new_team_path, class: "btn btn-primary" %> <% else %> <span class="text-muted">仅每周日开放团队创建</span> <% end %>
注意事项
- 所有时间判断统一用
Time.current,不要用Time.now,前者会读取项目config/application.rb里配置的时区,后者取服务器系统时间,容易因为时区不匹配出现判断错误。 - 模型层的校验必须保留,不然用户可以跳过页面直接发POST请求到创建接口,绕开前端和控制器的限制,模型校验是最后一道无法绕过的关卡。
内容的提问来源于stack exchange,提问作者adarsh
相关产品推荐
相关产品推荐

