Railsで整数クラスにメソッドを追加するのに最適な場所はどこですか? to_meters
およびto_miles
メソッドを追加したいと思います。
7 に答える
Numeric (または整数など) クラスをいじって単位変換を取得することに心を向けている場合は、少なくとも論理的に、実際の値を使用して実行してください。
最初に、単位の種類 (メートル、フィート、キュビットなど) と作成時の値を格納する Unit クラスを作成します。次に、ユニットが持つことができる有効な値に対応する一連のメソッドを Numeric に追加します。これらのメソッドは、メソッド名として記録された型を持つ Unit オブジェクトを返します。Unit クラスは、対応する単位値を持つ別の単位タイプに変換する一連の to_* メソッドをサポートします。そうすれば、次のコマンドを実行できます。
>> x = 47.feet.to_meters
=> 14.3256
>> x.inspect
=> #<Unit 0xb795efb8 @value=14.3256, @type=:meter>
それを処理する最善の方法は、おそらく Unit クラスの変換型と式のマトリックスであり、次に method_missing を使用して、特定の型を別の型に変換できるかどうかを確認します。数値クラスでは、method_missing を使用して、指定されたメソッドをユニット型としてサポートしているかどうかを Unit に問い合わせます。サポートしている場合は、数値を値として使用して、要求された型のユニット オブジェクトを返します。次に、変換行列を拡張する unit に register_type および register_conversion クラス メソッドを追加することで、実行時に単位と変換を追加することをサポートできます。Numeric は「自動的に」機能を取得します。
どこに置くかについては、lib/units.rb ファイルを作成します。このファイルには、Numeric への monkey_patch も含まれます。次に、lib/units.rb ファイルを必要とする config/environment.rb bu で初期化します。
通常(そして論理的に)、整数はマイルやメートルに変換できません。整数で初期化され、size_in_milesやsize_in_metersなどのメソッドを含む「Feet」や「inches」などの新しいクラスを作成したい場合があるようです。便宜上、これらのメソッドは10進数またはfloat型を返すことができますが、milesクラスまたはmetersクラスを作成することもできます。
別のメソッドとして、次のようなシグネチャを持つ静的メソッドを新しいクラスに作成することをお勧めします。
Float feetToMiles(integer I)
あなたが呼ぶだろう
miles = Feet.feetToMiles(5280);
取得しますmiles = 1.0
このタスクを実行するために必要なときにスコープに含める独自のモジュール/ライブラリを作成します。
「requre'unitCoversions'」など
そして、たぶん、あなたが十分に一生懸命に見れば、誰かがすでにこれをしているでしょう:)
ただし、ネイティブコアクラスを変更しようとしないでください。これはMiseryでのみ終了します。
(また、拡張したいクラスは'numeric'であり、整数と浮動小数点数の両方に適用されます:))
なぜ私がこれをすべきでないのか完全には明らかではありません...Railsはこれを文字列クラスに対して行い、大成功を収めています。
それができるからといって、それがなされるべきだという意味ではありません。知られている「モンキーパッチ」は、あらゆる種類の奇妙な副作用をもたらす可能性があり、間違って行われると壮大な失敗になる可能性があります。
良い選択肢がないときにそれを行います。
本当に何かやりたいことがあれば、コアクラスにモンキーパッチを当てるだけでフレームワーク全体を構築できるからです。
たとえば、データベースをその頭で反転させます。
5.getArtist();
10.getEvent();
100.getTrack();
などなど。それを行うための悪い方法の数に制限はありません。
"Bob".createUser();
カップの惨めさ。
実用的なことをしたい場合は、Convertクラスまたは関数を用意してください。
convert( 3 , { :from=>:miles, :to=>:meters });
少なくとも、グローバル名前空間とコア関数をそのように汚染しているわけではなく、より一貫性のある意味があります。
なぜだけではないのですか?
class Feet
def self.in_miles(feet)
feet/5280
end
end
利用方法:
Feet.in_miles 2313
または多分それを別の方法で見てください:
class Miles
def self.from_feet(feet)
feet/5280
end
end
Miles.from_feet 2313
モンキーパッチは注意して使用する必要があることに同意しますが、場合によっては意味があります。active_support ライブラリの一部である 5.days.ago を入力できるヘルパーが本当に気に入っています
したがって、この場合、他の答えのいくつかがより良いかもしれませんが、Ruby クラスを拡張している場合は、すべての拡張機能を lib/extensions/class_name.rb に保持します。
このようにして、プロジェクトに取り組んでいるときに、標準クラスでは通常とは異なる可能性があるものをすばやく簡単に見つけて確認できます。
質問が古いことに気付きますが、最も明確な方法は、 と の 2 つの属性@length
を持つ Distance クラスを作成することだと思います@unit
。
おそらく距離のクラス変数として、変換ハッシュが必要です。
class Distance
@@conversion_rates = {
meters: {
feet: 3.28084,
meters: 1.0
}
}
def to(new_unit)
new_length = @length * @@conversion_rates[@unit][new_unit]
Distance.new( new_length, new_unit )
end
end
そして、それはちょっと次のようになります:
Distance.new(3, :meters).to(:feet)
私が正直に思うよりも
3.meters.to_feet
これを行う場合は、すべきではありませんが、コードを次の場所に配置します。
config/initializers/add_methods_that_are_naughty_to_numeric.rb
Railsはこれらを自動的に実行します。