4

問題があるかどうかさえわかりませんが、 text_fields と text_areas が のempty string代わりにデータベースに保存されるのが好きではありませんnil

null オブジェクト パターンで遊んでいますが、プロファイルを作成しても場所フィールドに入力<%= @user.profile.location.upcase %>せずに呼び出すと、場所が空であっても文字列であるため、爆発しないことに気付きました。

これは、このようにするためのレールの慣例ですか?もしそうなら、なぜですか?number_of_petsプロファイルに属性があり、次のようなものを呼び出そうとするので、少し奇妙です

<% 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' %>
  ......
4

2 に答える 2

4

最も簡単な回避策は、ここにある「strip_attributes」のような宝石を使用することです。https://github.com/rmm5t/strip_attributes

カスタムの回避策はbefore_save、モデルにコールバックを追加することで実行できます。このコールバックは、空白の値を取り、それらを nil に戻します。

たとえば、あなたのモデルでは:

before_save :my_nil_maker_method_lol

[...]

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

アップデート:

空白のフィールドが保存されないようにするには、上記の方法や、データベースにヒットする前にコントローラーの空白のパラメーターを削除するなど、いくつかの方法があります。

データベースの整合性を維持するときの Rails のやり方は、常にこのロジックをモデル内に保持することです。これにより、メンテナンスがはるかに簡単になり、受信パラメーターを別の場所で変更した場合のような驚きの余地がはるかに少なくなります。

モデルでそれをどのように行うかは、開発者が入力に対して何を期待するかの問題です。上記のコールバックを追加して、適切と思われるデータベースを維持するvalidates_presence_ofか、そのフィールドが空白のままになっている場合にユーザーにエラーを返す検証を追加できます。

空の文字列がデータベースにまったく挿入されないようにする必要があるかどうかを尋ねている場合は、その情報が必要な場合があるかもしれないので、実際には開発者としてのあなた次第ですが、この場合は次のように聞こえます空の文字列を制限しようとしています。

于 2016-05-13T12:13:46.763 に答える
1

私が観察したことから話していますが、必ずしもRailsの慣習とは限りません。

rails g post title content:textたとえば、default: ''タイトル(文字列)とコンテンツ(テキスト)の両方がないことを覚えているかもしれません。これは、これに関してRailsの慣習がないこと、または具体的に言えば、デフォルトですべての属性がNULLまたはnilになることが許可されていることのヒントです。

NULL を使用する利点は、これらの属性が設定されているレコードを識別できることです。

API サーバーがあるとします。クライアントが API サーバーへの投稿を作成すると、どの属性が値を持つことを意図しているかがわかります。次のようなことを言ってみましょう。

client-1 の POST パラメータ:

post: {title: 'Foo bar'}
  • NULL が許可されている場合、Post(title: 'Foo bar', content: nil)
  • デフォルト: '' の場合、Post(title: 'Foo bar', content: '')

client-2 の POST パラメータ:

post: {title: 'Foo bar', content: ''}
  • NULL が許可されている場合、Post(title: 'Foo bar', content: '')
  • デフォルト: '' の場合、Post(title: 'Foo bar', content: '')

上記から、default: '' がある場合、クライアントが実際に空のcontent値を持つことを意図しているかどうかを知ることができないことに注意してくださいcontent。 (空)とにかく。ただし、NULL を許可する属性がある場合でもcontent、パラメータで属性を渡さないことで、クライアントが値を持たないことを意図しているかどうかを識別できます。これは重要な使用例です。

プロジェクトと属性の目的に応じて、NULL 許可を使用するか、その属性にデフォルトの空の文字列を設定することができます。

ここで、遭遇した NULL-allowed の主な問題の 1 つは、すべての値が であることを保証できないことですString。したがって、is NULL または nil<%= @user.profile.location.upcase %>の場合にエラーが発生します。location

これは、例のような一連のメソッドがある場合は特に、少し面倒になる可能性があります

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

エラーが発生しないことを適切に確認する必要があるため、これは nil の場合に問題になり@user.profile.locationます。また、これが nil の場合も問題になります@user.profile(nil を許可しているとだけ言っておきましょう@user.profile)。通常、これを機能させるには、次のようなことを行います。

<% if !@user.profile.nil? && !@user.profile.location.nil? %> 
  <%= @user.profile.location.upcase.downcase %>
<% end %>

エラーが発生しないことを適切に保証するためにチェーンされたメソッドが長いため、このif状態は非常に長く続く可能性があります。

を使用.try()すると、これが「クリーン」になる可能性があります。特にテンプレートファイルでこれを何度も使用します。知らない人にとっては混乱を招く可能性がありますが、解決策は以下のようにきれいになります。

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

or のいずれ.location.upcaseが nil の場合、nil を返し、それ以上レイズしませundefined method ... for NilClassん。

于 2016-05-13T13:49:42.603 に答える