Rails表单中模型布尔字段active?的问号为何被自动移除?
嘿,这个问题我之前也碰到过,其实是Rails表单助手的默认行为,完全符合框架的设计逻辑,我给你拆解清楚~
1. 为啥问号会被自动移除?
首先得明确Rails里布尔字段的约定:
- 数据库里的字段名是不带问号的,比如
active - 模型会自动给你生成俩东西:
active:用来读写数据库字段的属性(getter/setter方法)active?:专门的查询方法,返回布尔值,相当于!!active的快捷写法
当你在表单助手里传:active?当属性名时,Rails一眼就认出这是个查询方法,不是实际要提交的属性,所以自动把末尾的问号剥掉,映射到对应的active属性——这就是为啥生成的HTML里字段名变成singer[active]啦。
至于你在控制台能创建active?: true的实例,那是因为Rails的参数处理机制也会自动把带问号的键转成不带问号的版本,最终还是给active属性赋值,所以看起来好像是active?生效了,其实本质还是操作的active字段。
2. 正确的写法该咋改?
其实很简单,把表单里的:active?改成:active就行,其他地方按需调整:
<%= form_for @singer do |f| %> <%= f.label :active, "Active?" %> <!-- 这里手动指定label显示的文本,保持你想要的"Active?" --> <%= f.check_box :active, :checked => true %> <%= f.submit %> <% end %>
这样生成的HTML字段名还是singer[active],功能完全正常,还符合Rails的约定。
要是你想让label自动显示"Active?",不用每次手动写,也可以在模型里加个人性化名称配置:
# app/models/singer.rb class Singer < ApplicationRecord human_attribute_name :active, default: "Active?" end
之后直接写f.label :active就能显示"Active?"了,省事儿~
3. 非要保留带问号的参数名?(真心不推荐)
虽然不建议打破Rails的约定(毕竟约定大于配置是Rails的核心优势),但如果真有特殊需求,你可以手动指定check_box的name属性:
<%= f.check_box :active, :checked => true, name: "singer[active?]" %>
不过这么干的话,你还得在模型里手动处理这个参数,比如加attr_accessor :active?,或者在strong_params里把"active?"映射到active属性,反而给自己加活儿,所以还是乖乖遵循约定最省心。
内容的提问来源于stack exchange,提问作者thumbtackthief

