1

次のような application.html.erb にリンクされたヘッダー部分があります。

<header class="unselectable">
  <h2 class="float_left">
    <% if @user.try(:errors).present? %>
      <%= render 'shared/error_messages' %>
    <% else %>
      <%= @title %>
    <% end %>
  </h2>

  <nav class="round">
    <ul>
        <% if logged_in? %>
          <li><%= link_to "Home", current_user %></li>
          <li><%= link_to "Settings", edit_user_path %></li>
          <li><%= link_to "Log out", logout_path %></li>
        <% else %>
          <li><%= link_to "Log in", login_path %></li>
        <% end %>
    </ul>
  </nav>
</header>

ロードするページに @user 変数 (about または logout ページなど) がない場合を除き、これはすべて問題ありません。この場合、次のようになります。

undefined method `errors' for nil:NilClass

どうすればこれを機能させることができますか?ロジックを変更してタイトルをレンダリングしようとしましたunless @user.errors.any?が、それもうまくいきませんでした。これは簡単な修正だと思いますが、わかりません!

EDITは提案された修正を追加し(上記のヘッダーの部分で更新されました)、次のエラーが発生しました:

No route matches {:action=>"edit", :controller=>"users"}から来ているようですedit_user_path

4

3 に答える 3

3

メソッドを使用できます.try(:something)

<% if @user.try(:errors).present? %>
  <%= render 'shared/error_messages' %>
<% else %>
  <%= @title %>
<% end %>
  • の場合、@userはエラーを発生させません。nil.try(:errors)

  • この.present?方法は次の場合にも機能しnilます。

.

>> nil.present?
#=> false
>> false.present?
#=> false
>> [].present?
#=> false
>> ''.present?
#=> false
>> 'bonjour'.present?
#=> true
>> ['bonjour'].present?
#=> true
  • .present?.nil?ANDの組み合わせ.empty?
  • .present?は実際には逆の結果です.blank?
于 2013-06-03T16:51:47.170 に答える
1

次のように再定式化できます。

<header>
  <h2 class="float_left">
    <% if @user.try(:errors).try(:any?) %>
      <%= render 'shared/error_messages' %>
    <% else %>
      <%= @title %>
    <% end %>   
  </h2>
...
</header>

errors_any?またはモデルに追加:

class User
  def errors_any?
    self.try(:errors).try(:any?)
  end
end

そしてこれに:

<header>
  <h2 class="float_left">
    <% if @user.try(:errors_any?) %>
      <%= render 'shared/error_messages' %>
    <% else %>
      <%= @title %>
    <% end %>   
  </h2>
...
</header>
于 2013-06-03T17:03:56.327 に答える
1

@userアプリケーションのレイアウトでレンダリングされるパーシャルでの必要性を強く疑問に思っているため、アプリケーションのすべてのページで必要です。アプリケーションのすべてのビューでグローバル変数に依存しているため、これはまったく良い設計ではないと私は主張します。

あなたが本当に使うのはフラッシュだと思います。その場合、 でこのようなものが必要ですapplication.html.erb

<% flash.each do |key, value| %>
  <%= content_tag :div, value, class: key %>
<% end %>

これは、ビューがレンダリングされる前に適切なコントローラー アクションで設定する必要があります。これにより、作成されたばかりの要求に従ってエラー メッセージが表示されます。

エラー メッセージがモデルに由来する場合、これは実際にこれらのエラー メッセージを生成するものの一部である必要があります。通常、これはコントローラ内のcreateまたはupdateアクションの呼び出しです。その場合error_messages、検証がパスせず、フォームがモデル オブジェクトで再度レンダリングされるときに、フォームで部分的にレンダリングする必要があります。

<%= form_for @user do |f| %>
  <%= render 'shared/error_messages', :object => f.object %>
  <!-- and so on -->
<% end %>

@userこのようにして、パーシャル自体にオブジェクトを明示的に渡し、パーシャルが正しいコンテキストでレンダリングされるため、エラーなしでパーシャルがレンダリングするオブジェクトが常に利用可能であると確信できます。パーシャル自体で使用@usersすることは、グローバル変数を使用することと同等であるため、アプリケーション全体がそのグローバル変数に依存して存在します。

オブジェクトは、パーシャル as (または最終的に名前を付けることを決定したもの)の@userローカル変数でアクセスされるようになりました。object

<% object.errors.full_messages.each do |message| %>
  <li>* <%= message %></li>
<% end %>
于 2013-06-03T17:20:19.557 に答える