32

Rails 3.0 Todo アプリの場合、 Statusフィールドを持つ Tasks モデルがあります。Status フィールド データ (フィールド タイプ) を保存し、ビュー (HTML テーブル) に人間が読めるバージョンを表示する最良の方法は何ですか? ステータスは次のとおりです。

0 = 通常
1 = アクティブ
2 = 完了

今私はこれを持っています:

Rails スキーマは次のとおりです。

create_table "タスク", :force => true do |t|
t.integer "ステータス", :limit => 1, :default => 0, :null => false

Railsモデルはこちら:

class Task < ActiveRecord::Base
  validates_inclusion_of :status, :in => 0..2,
    :message => "{{value}} must be 0, 1, or 2"

Railsビューはこちら:

<h1>Listing tasks</h1>

<table>
  <tr>
    <th>Status</th>
    <th>Name</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @tasks.each do |task| %>
  <tr>
    <td><%= task.status %></td>
    <td><%= task.name %></td>
    <td><%= link_to 'Show', task %></td>
    <td><%= link_to 'Edit', edit_task_path(task) %></td>
    <td><%= link_to 'Delete', task, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>

要件

  1. 値を簡単にローカライズできるように、タスクのステータスをデータベースに保存します。つまり、「通常」、「アクティブ」、「完了」を文字列フィールドとして保存するかどうかわかりません。

  2. ソリューションは Rails 3.0 で動作する必要があります。

質問:

  1. フィールドを整数として保存する必要がありますか (上記を参照)。もしそうなら、RailsビューのHTMLテーブルに人間が読める正しいステータスを表示するにはどうすればよいですか。たとえば、HTMLテーブルに「1」ではなく「Active」を表示します。

  2. 列挙型を使用する必要がありますか? もしそうなら、これは後で簡単にローカライズできますか?

  3. 「Normal」、「Active」、「Completed」などのストレート文字列を使用する必要がありますか

  4. これを機能させるためのビュー ヘルパー、コントローラー、またはビュー コードの簡単なコード サンプルを提供できますか?

4

6 に答える 6

43

1.DBでのクエリをどれだけ最適化したいかによって異なります。

2.そうではありません。AR では「そのまま」サポートされていません。# Rails 4 の時点で、デフォルトで enum がサポートされています

3.私見では、パフォーマンスを大幅に低下させることなく文字列を使用できます(インデックスにフィールドを追加することを忘れないでください)。国際化と保守が簡単なので、私はこれを行います。ただし、追加のパフォーマンスが必要な場合は、整数を使用できます。

ここここで議論されている 2 つの SO スレッドを見ることができます。

4.それらを整数として保持したい場合は、これを達成する方法は次のとおりです。

class Task << AR::Base
  NORMAL    = 1
  ACTIVE    = 2
  COMPLETED = 3


  STATUSES = {
    NORMAL    => 'normal',
    ACTIVE    => 'active',
    COMPLETED => 'completed'
  }

  validates_inclusion_of :status, :in => STATUSES.keys,
      :message => "{{value}} must be in #{STATUSES.values.join ','}"

  # just a helper method for the view
  def status_name
    STATUSES[status]
  end
end

そしてビューで:

<td><%= task.status_name %></td>

文字列を使用する場合は、より単純化されています。

STATUSES = ['normal', 'active', 'completed']
validates_inclusion_of :status, :in => STATUSES,
          :message => "{{value}} must be in #{STATUSES.join ','}"
于 2010-04-16T07:17:46.757 に答える
6

最も簡単な方法は、別のテーブルを追加するのではなく、実際の文字列をフィールドに格納することです。あなたの視点に応じて、これはデータベースが十分に正規化されないため悪い考えであるか、アプリがより効率的に正規化されるため良い考えです.

それを行わず、値を別のテーブルに保持することを選択した場合。モデルで関係を設定する必要があります。

class Task < ActiveRecord::Base
    has_one :status
end

class Status < ActiveRecord::Base
    belongs_to :tasks
end 

次に、ビューで次の方法で値を参照できます。

<%= task.status %>
于 2010-04-16T07:21:06.210 に答える
3

このようなユースケースにはEnum-Columnを使用しました。プラグインを使用すると、移行スクリプトで列挙列タイプを定義し、属性の MYSQL 列挙列タイプを作成できます。

create_table :tasks do |t|
  ...
  t.enum :status, :limit => [:normal, :active, :completed], :default => :normal
  ...
end

これで、コードで次のことができます。

task.status = "active"
task.status = :completed
p "Task status: #{task.status}" # prints Task status: completed


Task.find_by_status(:active)
Task.find_by_status("active")
Task.find_by_status(2)

シリアライゼーションでもうまく機能します:

task.to_xml # will result in status= active instead of status-2

その他の優れた点は、通常の DB クライアント (例: mysql コマンド コンソールまたは phpMyAdmin) を使用して表示すると、ステータス値が文字列として表示されることです。

プラグインは、列挙型に最適なストレージとユーザー フレンドリーなアクセスを提供します。

警告:

プラグインはかなり古く、メンテナンスされていません。MySQL DB で広く使用しています。PostgreSQL で動作させるには、コードにパッチを適用する必要がありました。MySQL を使用している場合は、このプラグインが適しています。

于 2010-04-16T07:36:39.423 に答える
2

次の理由により、「通常」、「アクティブ」、..「完了」を文字列としてテーブルに格納することを好みます。

  • それはセルフドキュメンテーションです (たとえば、誰かがデータを見ても、Rails のソースコードを読んでいない可能性があります)。
  • パフォーマンスへの影響はほとんどありません (ゼロではないにしても)。
  • モデルのRails仮想属性または他の言語のレイヤーを使用して、i18nを行うのは(まだ)簡単です

最近では、Rails の定数をデータベースからできるだけ切り離すようにしています。私たちの周りには常に PHP/MSSQL/??DBA 関係者がいます (私たちほど Rails を愛していない人もいるかもしれません ;-)

したがって、答えは整数でも列挙型でもありません(ただし、varchar ;-)

于 2010-04-16T07:37:34.363 に答える