【问题标题】:Rails "Data too long for column" error after truncation截断后Rails“列的数据太长”错误
【发布时间】:2014-02-07 01:40:12
【问题描述】:

我有一个应用程序可以从输入到模型中的正文文本中创建文本摘录,它似乎工作正常,除非出于某种原因,当我尝试在正文中输入一个特定的字符串时。

在我的 blog_post 模型中

t.string   "excerpt",            limit: 114

在我的控制器中,我通过这样做来创建摘录字符串:

def create
  @blogpost = Blogpost.new(blogpost_params)
  @excerpt = @blogpost.body
  @blogpost.excerpt = truncate(@excerpt, :length => 114)
  respond_to do |format|
   if @blogpost.save
    etc,etc,
end

这似乎大部分时间都可以正常工作,但我输入了以下文本作为测试

 You know how they used to say It's #Sinatra's world, the rest of us are just living in it. - well, it's as true today as it was then. Check out Frank. When he gets out of a #chopper, dressed in a perfect lounge suit, #cocktail in hand, his #hat stays perfectly tilted. When I get out of a #chopper (and I'm not talking about once or twice but every single time I ever get out of a chopper) the spinning blades blow my hat all over the place. #Milliners should think about that and you should too the next time you're out hat shopping.

(抱歉有点长)我收到以下错误:

ActiveRecord::StatementInvalid in MoansController#create
Mysql2::Error: Data too long for column 'excerpt' at row 1....

似乎由于某种原因截断不起作用。是与此文本有关还是我错过了其他内容?

【问题讨论】:

  • 这个列在MySQL中是如何定义的?那里的最大长度是多少?
  • 您使用哪个版本的 Rails?
  • 它是 rails 4,用于添加列的迁移是 add_column(:blogposts, "excerpt", :string, :limit=>114)
  • 尝试截断为 111 个字符
  • @IvanDenisov 这应该不是问题,:limit => 114 确实将... 包含在限制计数中。

标签: ruby-on-rails exception controller truncate


【解决方案1】:

我认为您应该删除数据库限制并通过使用默认截断为所需长度的设置器来处理此问题。在您的模型中,将excerpt_setter 添加到attr_accessible 列表中。然后这样定义

def excerpt_setter=(str)
  self.excerpt = truncate(str, :length => 114)
end

def excerpt_setter
  self.excerpt
end

然后在控制器中

def create
  @blogpost = Blogpost.new(blogpost_params)
  @blogpost.excerpt_setter = truncate(@excerpt.body, :length => 114)
  respond_to do |format|
   if @blogpost.save
    etc,etc,
end

另一件事:您还可以在模型中定义 excerpt 方法,如果没有充分理由将正文的一部分存储在另一个字段中,则删除该字段。

include ActionView::Helpers::TextHelper  # this is needed to make the truncate method avaiable in model

...
...
...

def excerpt
  truncate(self.body, :length => 114)
end

如果您出于性能原因不需要存储在数据库中的数据,这将是我的首选解决方案。

【讨论】:

  • 哪种解决方案?
  • 我选择了在模型中定义摘录的第二个选项。我想我之前把事情复杂化了