我有一个activerecord模型,其中validates:body, presence: true。当填写并提交表单时,我得到{:body=>["can't be blank"]},即使主体实际上不是空白的。如果我从模型中删除验证,并重新提交,记录就成功创建了。为什么当体字段不是空的时候,验证说它是空的?
控制器。
class SqlTemplatesController < ApplicationController
def create
@sql_template = SqlTemplate.new(sql_template_params)
respond_to do |format|
if @sql_template.save
format.html { redirect_to @sql_template, notice: 'Sql template was successfully created.' }
end
end
private
def sql_template_params
params.require(:sql_template).permit(:body, :path, :format, :locale, :handler, :partial)
end
end
模型class SqlTemplate < ActiveRecord::Base
validates :body, :path, presence: true
validates :format, inclusion: Mime::SET.symbols.map(&:to_s)
validates :locale, inclusion: I18n.available_locales.map(&:to_s)
validates :handler, inclusion: ActionView::Template::Handlers.extensions.map(&:to_s)
def to_liquid
SqlTemplateDrop.new(self)
end
def body=(text)
if self[:handler] == 'liquid'
@template = Liquid::Template.parse(text)
self[:body] = Marshal.dump(@template)
end
end
def render(options = {})
template.render options
end
private
def template
return @body unless @body.nil?
@body = Marshal.load(self[:body])
end
end
在rails控制台如果创建一个新记录并将body字段设置为字符串body =>"消息体"或液体标记,例如body =>"{{body}},它将引发错误{:body=>["can't be blank"]},但如果删除验证它们工作
。irb(main):016:0> a = SqlTemplate.create(:body => "{{body}", path => "mail/liquid_database_template", :format => "html", :locale => "en", :handler => "liquid", :partial => false)
(0.1ms) begin transaction
(0.1ms) rollback transaction
irb(main):016:0> a.errors.messages
=> {:body=>["can't be blank"]}
如果我删除验证并提交表单,一切都可以正常工作,如下所示:
Started POST "/sql_templates" for 127.0.0.1 at 2014-03-11 15:28:14 +0000
Processing by SqlTemplatesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"GVsRbsCKSlcEMiL1AzXE0tT8LBCNhhoK6wSGzvnB80A=", "sql_template"=>{"body"=>"{{body}}", "path"=>"customer_mail/liquid_database_template", "format"=>"html", "locale"=>"en", "handler"=>"liquid", "partial"=>"0"}, "commit"=>"Create Sql template"}
#<SqlTemplate id: nil, body: nil, path: "customer_mail/liquid_database_template", format: "html", locale: "en", handler: "liquid", partial: false, created_at: nil, updated_at: nil>
(0.1ms) begin transaction
SQL (9.4ms) INSERT INTO "sql_templates" ("created_at", "format", "handler", "locale", "path", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["created_at", "2014-03-11 15:28:14.869619"], ["format", "html"], ["handler", "liquid"], ["locale", "en"], ["path", "customer_mail/liquid_database_template"], ["updated_at", "2014-03-11 15:28:14.869619"]]
(621.4ms) commit transaction
Redirected to http://localhost:3000/sql_templates/7
Completed 302 Found in 662ms (ActiveRecord: 630.9ms)
Started GET "/sql_templates/7" for 127.0.0.1 at 2014-03-11 15:28:15 +0000
Processing by SqlTemplatesController#show as HTML
Parameters: {"id"=>"7"}
SqlTemplate Load (3.1ms) SELECT "sql_templates".* FROM "sql_templates" WHERE "sql_templates"."id" = ? LIMIT 1 [["id", 7]]
Rendered sql_templates/show.html.erb within layouts/application (11.4ms)
Completed 200 OK in 52ms (Views: 46.0ms | ActiveRecord: 3.1ms)
如果我添加验证并提交,它会失败,如下所示:
Started POST "/sql_templates" for 127.0.0.1 at 2014-03-11 14:34:22 +0000
ActiveRecord::SchemaMigration Load (0.3ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by SqlTemplatesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"GVsRbsCKSlcEMiL1AzXE0tT8LBCNhhoK6wSGzvnB80A=", "sql_template"=> {"body"=>"{{body}}", "path"=>"customer_mail/liquid_database_template", "format"=>"html", "locale"=>"en", "handler"=>"liquid", "partial"=>"0"}, "commit"=>"Create Sql template"}
#<SqlTemplate id: nil, body: nil, path: "customer_mail/liquid_database_template", format: "html", locale: "en", handler: "liquid", partial: false, created_at: nil, updated_at: nil>
(0.2ms) begin transaction
(0.2ms) rollback transaction
Rendered sql_templates/_form.html.erb (32.6ms)
Rendered sql_templates/new.html.erb within layouts/application (57.1ms)
Completed 200 OK in 208ms (Views: 143.0ms | ActiveRecord: 1.4ms)
您的body
setter在handler
的setter之前被调用。因此self[:handler]
在进入body=
方法时将为nil
你可以试试这些
i)改变你的哈希
的顺序a = SqlTemplate.create(:handler => "liquid", :body => "{{body}", path => "mail/liquid_database_template", :format => "html", :locale => "en", :partial => false)
ii)设置处理程序后再设置主体
a = SqlTemplate.new(:handler => "liquid", path => "mail/liquid_database_template", :format => "html", :locale => "en", :partial => false)
a.body = "{{body}}"
a.save
我自己解决了。问题出在body字段的setter方法上。通常,rails会自动定义这个,但如果它被覆盖来做一些额外的事情,这里就是这种情况,我仍然需要在顶部设置self[:body] = text。注意,text是通过表单传递给字段的值。如果没有验证存在,将失败。
def body=(text)
self[:body] = text
end