1

テーラーメジャーフォームとして機能するアプリを書いています。

顧客モデルには、ミリメートル単位の整数としてデータベースに格納される多くの属性があります。このアプリはヨーロッパと米国の両方で使用されるため、仮想属性を使用して、データのインチとセンチメートルのバージョンをユーザーに表示します。

たとえば、顧客の身長については、モデルにこれがあります。

  def height_in_cm
    height / 10
  end

  def height_in_cm=(height)
    self.height = height.to_f  * 10
  end

  def height_in_in
    height * 0.039370
  end

  def height_in_in=(height)
    self.height = height.to_f / 0.039370
  end

そしてこれは私の_formビューで:

  <% if @customer.measure_unit.eql? "imperial" %>
    <%= f.input :height_in_in %></br>
  <% else %>      
    <% if @customer.measure_unit.eql? "metric" %>
      <%= f.input :height_in_cm %></br>
    <% end %>     
  <% end %>

私が言ったように、私は多くの属性を持っているので、私の顧客モデルファイルは非常に長くなり、非常にエラーが発生しやすくなっています。

それを短くするための乾いた方法はありますか?

4

2 に答える 2

1

そのロジックを次のようにカプセル化します。

def display_height
  case measure_unit
  when 'imperial' then height_in_in
  when 'metric'   then height_in_cm
  else height_in_in
  end
end

次に、ビューは次のようになります。

<%= @customer.display_height %>

多くのモデルでこれらの同じ変換方法を使用している場合は、次のようにモジュールに抽出します。

module HeightConversions

  def height_in_cm
    height / 10
  end

  def height_in_in
    height * 0.039370
  end

  def display_height
    case measure_unit
    when 'imperial' then height_in_in
    when 'metric'   then height_in_cm
    else height_in_in
    end
  end

end

必要に応じて、モデルに次のように含めます。

class Customer
  include HeightConversions
end

編集:

わかりました、おそらく次のようなものがもっと必要です:

  %w(neck waist arm).each do |name|
    self.class_eval do

      define_method :"#{name}_in_cm" do
        self.send(name) / 10
      end

      define_method :"#{name}_in_cm=" do |n|
        self.send("#{name}=", (n.to_f * 10))
      end

      define_method :"#{name}_in_in" do
        self.send(name) * 0.03
      end

      define_method :"#{name}_in_in=" do |n|
        self.send("#{name}=", (n.to_f / 0.039370))
      end

    end
  end

これは通常、メタプログラミングと呼ばれます。Rails でそれを行うさまざまな方法についての簡潔な記事を次に示します

于 2012-12-12T15:31:46.593 に答える
0

gem または javascript のいずれかに変換を行わせます。ruby-unitsなどの gemはやり過ぎかもしれませんが、必要な変換に対して永続的な解決策を提供します。

JavaScript に変換を行わせるために、application.js に追加できるものを次に示します。「ベースライン」の概念を使用して、レールでメソッドを DRY することもできます。

function convert_units(input, input_unit, output_unit) {
// Used to convert all units to similar intermediary unit. I used meters.
var inches_per_meter = 39.3701;
var sixteenths_per_meter = 629.9216;
var cm_per_meter = 100;
var mm_per_meter = 1000;

var intermediary = 0; //in meters

switch(input_unit)
{
  case: "mm": intermediary = input * mm_per_meter;
    break;
  case: "cm": intermediary = input * cm_per_meter;
    break;
  case: "meter": intermediary = input;
    break;
  case: "inches": intermediary = input * inches_per_meter;
    break;
  case: "sixteenths": intermediary = input * sixteenths_per_meter;
    break;
  default: return "Input unit not correctly accomodated";
}

switch(output_unit)
{
  case: "mm": return intermediary / mm_per_meter;
    break;
  case: "meter": return intermediary;
    break;
  case: "inches": return intermediary / inches_per_meter;
    break;
  case: "sixteenths": return intermediary / sixteenths_per_meter;
    break;
  case: "cm": return intermediary / cm_per_meter;
    break;
  default: return "Output unit not correctly accomodated";
}
}

次に、あなたの見解で

convert_units(@customer.height, 'inches', 'cm');
于 2012-12-12T16:24:22.150 に答える