web-dev-qa-db-ja.com

Rails:データベースに要素がないときにメッセージを表示するエレガントな方法

私はこれに似た多くのコードを書いていることに気づきました:

<% unless @messages.blank? %>
  <% @messages.each do |message|  %>
    <%# code or partial to display the message %>
  <% end %>
<% else %>
  You have no messages.
<% end %>

Rubyおよび/またはRailsこれにより、最初の条件をスキップできるようになりますか?それで、イテレータ/ループが入らないときに実行されます一度でも?例えば:

<% @messages.each do |message| %>
  <%# code or partial to display the message %>
<% and_if_it_was_blank %>
  You have no messages.
<% end %>
65
Jakub Troszok

:collectionパラメータを使用してレンダリングする場合。 render :partial => 'message', :collection => @messagesの場合、コレクションが空の場合、renderの呼び出しはnilを返します。これを||に組み込むことができます式、例えば.

<%= render(:partial => 'message', :collection => @messages) || 'You have no messages' %>

これまでに遭遇したことがない場合は、render :collectionは各要素に同じパーシャルを使用してコレクションをレンダリングし、@messagesの各要素をローカル変数messageとして使用できるようにします完全な応答を構築します。 :spacer_template => "message_divider"を使用して、各要素の間にレンダリングされる仕切りを指定することもできます

60
mikej

次のようなものを書くこともできます:

<% if @messages.each do |message| %>
  <%# code or partial to display the message %>
<% end.empty? %>
  You have no messages.
<% end %>
159
Fernando Allen

私のお気に入りの答えがここにないことに驚いています。近い答えがありますが、私は裸のテキストが好きではなく、content_forを使用するのは無茶苦茶です。サイズを試してみてください:

  <%= render(@user.recipes) || content_tag("p") do %>
    This user hasn't added any recipes yet!
  <% end %>
16
David Bock

1つの方法は次のようなことです。

<%= render(:partial => @messages) || render('no_messages') %>

編集:

私が正しく覚えているなら、これはこのコミットによって可能になった:

http://github.com/Rails/rails/commit/a8ece12fe2ac7838407954453e0d31af6186a5db

16
jonnii

カスタムヘルパーを作成できます。以下は一例です。

# application_helper.html.erb
def unless_empty(collection, message = "You have no messages", &block)
  if collection.empty?
    concat(message)
  else
    concat(capture(&block))
  end
end

# view.html.erb
<% unless_empty @messages do %>
  <%# code or partial to dispaly the message %>
<% end %>
6
Simone Carletti

注として、式の効率を求めている場合は、空の配列を反復処理することもできます。

<% @messages.each do |message|  %>
  <%# code or partial to dispaly the message %>
<% end %>
<% if (@messages.blank?) %>
  You have no messages.
<% end %>

これはnilの@messagesを処理しませんが、ほとんどの状況で機能するはずです。ルーチンビューであるべきものに不規則な拡張機能を導入すると、おそらく他の点では単純なことを複雑にするでしょう。

より適切なアプローチは、「空の」セクションをレンダリングするパーシャルとヘルパーを定義して、これらがかなり複雑である場合です。

<% render_each(:message) do |message|  %>
  <%# code or partial to dispaly the message %>
<% end %>

# common/empty/_messages.erb
You have no messages.

これを次のように定義する場合:

def render_each(item, &block)
  plural = "#{item.to_s.pluralize}"
  items = instance_variable_get("@#{plural}")
  if (items.blank?)
    render(:partial => "common/empty/#{plural}")
  else
    items.each(&block)
  end
end
3
tadman

古いトピックですが、これらのどれも好きではなかったので、Rails 3.2で遊んでみました。この代替案を見つけました。

<% content_for :no_messages do %>
  <p>
    <strong>No Messages Found</strong>
  </p>
<% end %>

<%= render @messages || content_for(:no_messages) %>

または、私がしたように、部分パスを使用してより詳細なレンダリングが必要な場合:

<%= render(:partial => 'messages', 
     :collection => @user.messages) || content_for(:no_messages) %>

このようにして、「メッセージなし」の部分を任意のHTML /ビューロジックでスタイル設定し、読みやすくすることができます。

1
Kansha

2つのケースを異なるテンプレートに分割できます。1つはメッセージが存在する場合、もう1つはメッセージが存在しない場合です。コントローラーアクション(_MessagesController#index_おそらく)で、最後のステートメントとして追加します。

_render :action => 'index_empty' if @messages.blank?
_

メッセージがない場合は、_app/views/messages/index_empty.html.erb_と表示されます。メッセージがある場合は、通常通り処理されて_app/views/messages/index.html.erb_が表示されます。

これが複数のアクションで必要な場合は、次のような(テストされていない)ヘルパーメソッドにうまくリファクタリングできます。

_def render_action_or_empty (collection, options = {})
    template = params[:template] || "#{params[:controller]}/#{params[:action]}"
    template << '_empty' if collection.blank?
    render options.reverse_merge { :template => template }
end
_

これにより、コントローラーアクションの最後にrender_action_or_empty(@var)を配置するだけで、コレクションが空の場合に 'action'テンプレートまたは 'action_empty'テンプレートのいずれかが表示されます。アクションテンプレートの代わりにパーシャルを使用してこれを簡単に機能させることもできます。

0
Zargony

trおよびtdプロパティとcolspanプロパティが欲しいので、以下の解決策は私にとってうまくいきます:

<%= render(@audit_logs) || content_tag(:tr, content_tag(:td, 'No records',colspan: "11"))%>
0
Jigar Bhatt

このコードは、次のように短縮できます。

<%= @messages.empty? ? 'You have no messages.' : @messages.collect { |msg| formatted_msg(msg) }.join(msg_delimiter) %>

コメント:

formatted_msg()-メッセージにフォーマットを追加するヘル​​パーメソッド

msg_delimiter-「\ n」や「<br />」などの区切り文字を含む変数

ところで私は空を使用することをお勧めしますか?空白の代わりにメソッド?配列をチェックするため、a)その名前はより簡潔です:)およびb)空白ですか? Rails外では機能しないActiveSupport拡張メソッドです。

0
Lukas Stejskal