2016-05-13 82 views
0

我甚至不确定是否有问题,但我不喜欢我的text_fields和text_areas作为empty string保存在数据库中,而不是nilrails text_field/text_ara空字符串vs零

我正在玩空对象模式,只是实现了,如果我创建一个配置文件,但不填写位置字段,然后调用<%= @user.profile.location.upcase %>然后它不爆炸,因为位置是一个字符串,即使它是空的。

这是轨道公约有这种方式吗?如果是这样,那为什么?这很奇怪一点,因为我们说有一个number_of_pets ATTR上的配置文件,然后我打电话像

<% if user.profile.number_of_pets.odd? %> 
    <%= @user.profile.first_name %> has odd number of pets 
<% end %> 

然后炸毁的以来我不能叫nil.odd?

形式像往常一样,所以它会保存为空,如果不填

<%= form_for @profile, url: user_profile_path do |f| %> 
    <%= f.label :city %> 
    <%= f.text_field :location, class: 'form-control' %> 
    ...... 
+0

你可以写这个 –

+0

Amol的验证,谢谢你的回答,但这不是我的问题。我想知道什么是约定和原因。 –

+0

这也一直困扰着我。对于更多可预测的数据(空白为NULL),我总是使用'nilify_blanks'宝石。我知道这并不能回答你的问题,但它更像是一种协议。 –

回答

2

一个快速的解决方法可以通过增加模型中的before_save回调需要为空的任何值来完成,并将他们带回到零。

在你的模型,例如:

before_save :my_nil_maker_method_lol 



    def my_nil_maker_method_lol 
     if self.whatever_attribute.blank? 
     self.whatever_attribute=nil 
     end 
    end 

更新:

保持被保存的空白字段可以有多种方式,如上述,甚至删除空白PARAMS在控制器中他们打了前数据库,但Rails的方式,当保持数据库的完整性时,总是将这个逻辑保存在你的模型中。它使维护变得更容易,并且留下更少的空间,例如,如果要在其他地方修改传入参数。至于在模型中应该如何完成,实际上只是您作为开发人员希望得到的输入的问题。您可以添加一个回调,如上所示,它可以维护您的数据库,或者您可以添加一个“validates_presence_of”验证,如果该字段留空,则会向用户返回错误。如果您问是否应该将空字符串插入到数据库中,那么开发人员确实应该接受您,因为可能存在您可能需要该信息的情况,但在这种情况下,听起来好像您正在寻找限制空弦。

+0

bkunzi01感谢您的回答,但这不是我的问题。我问什么是约定和原因。 –

+0

道歉我会更新我的答案。 – bkunzi01

+1

我会暂时保持它的状态。目前我不需要任何特殊的东西,只是以为我错过了一些东西。 –

1

我是从我观察到的情况来讲的,可能并不一定是Rails惯例。

例如,当我们做rails g post title content:text例如,你可能记得它没有default: ''为标题(字符串)和内容(文本)。这已经暗示我没有关于这个的Rails约定,或者具体地说默认情况下每个属性都被允许为NULL或零。

使用NULL的好处是您可以识别哪些记录具有这些属性设置。

假设我们有一个API服务器。如果客户向我们的API服务器创建一个帖子,我们知道哪些属性有意为其创造价值。比方说,像下面这样:

客户-1的post数据:

post: {title: 'Foo bar'} 
  • 如果NULL允许的,将创建一个Post(title: 'Foo bar', content: nil)
  • 如果默认: '',将创建一个Post(title: 'Foo bar', content: '')

客户-2的post数据:

post: {title: 'Foo bar', content: ''} 
  • 如果NULL允许的,将创建一个Post(title: 'Foo bar', content: '')
  • 如果默认:“”,将创建一个Post(title: 'Foo bar', content: '')

从以上,请注意,如果我们有默认:“”,那么我们就无法知道如果客户实际上打算有一个空的content值,因为对于客户端1和客户端2,邮件的结果值content无论如何都将具有“(空)”。但是,如果我们具有允许NULL的属性,那么我们仍然可以通过未传入参数中的属性来识别客户端是否打算不具有content值。这是一个重要的用例。

根据您的项目和属性的用途,您可以为该属性使用NULL允许或设置默认空字符串。

现在,随着一个主要问题NULL,允许作为您遇到的是,你不能保证每个值将是一个String,因此您<%= @user.profile.location.upcase %>会引发错误的情况下,location为空或零。

这可能是一个有点讨厌,特别是如果你有喜欢你的实例方法

<%= @user.profile.location.upcase.downcase %> 

这将是一个问题,如果@user.profile.location是无链,因为你必须优雅地确保它赢得了”不会产生错误。如果@user.profile为零(我们假设你允许@user.profile为零),这也会是一个问题。而通常情况下,你会做类似于下面的东西,使这项工作:

<% if [email protected]? && [email protected]? %> 
    <%= @user.profile.location.upcase.downcase %> 
<% end %> 

if条件仍然可以在很只要你有较长链的方法,以确保正常也不会提出任何错误。

使用.try()可能会“清理”这一点。我特别在模板文件中使用了很多次。解决方案将清洁像下面,虽然有可能混淆对于那些不知道是谁:

<%= @user.profile.try(:location).try(:upcase).try(:downcase) %> 

如果任.location.upcase为零,它将返回零,并没有提出任何undefined method ... for NilClass了。

+0

感谢Jay-Ar,我不喜欢使用'if'或'try',这就是为什么我在'null object pattern'中玩弄的原因。但是我会为字段保留默认的'''''设置。 –

+0

不客气!祝你好运 :) –