13

高さはインチ単位でデータベースに保存されます。

ただし、フィートとインチには、次の形式で独自の入力が必要です。

Height: [_______] feet [_______] inches

そこで、仮想属性を使用して、それを機能させました。これが私のモデルの簡略版です:

class Client < ActiveRecord::Base
  attr_accessible :name, :height_feet, :height_inches

  before_save :combine_height

    def height_feet
      height.floor/12 if height
    end

    def height_feet=(feet)
      @feet = feet
    end

    def height_inches
      if height && height%12 != 0
        height%12
      end
    end

    def height_inches=(inches) #on save?
      @inches = inches
    end

  def combine_height
    self.height = @feet.to_d*12 + @inches.to_d #if @feet.present?
  end

end

そして、_formsimple_formを使用した部分:

<%= simple_form_for(@client) do |f| %>
  <ul>
    <%= f.error_notification %>
    <%= f.input :name %>
    <%= f.input :weight %>
    <li>
      <%= f.input :height_feet, :label => 'Height', :wrapper => false %>
      <span>feet</span>
      <%= f.input :height_inches, :label => false, :wrapper => false %>
      <span>inches</span>
    </li>
    <%= f.error :base %>
  </ul>
    <%= f.button :submit %>
<% end %>

これは機能します。しかし、それは理想的ではありません。

これを乾かしてカスタム入力コンポーネントを作成し、フォームに高さを追加できるようにします。<%= f.input :height, as: :feet_and_inch %>したがって、。などの同じパターンに従う他の入力を追加し<%= f.input :wingspan, as: :feet_and_inch %>ます。

カスタムコンポーネントを試しましたが、2つの入力を表示できません。また、「変換」ロジックをフィートとインチからインチに(そして同様にインチからインチに戻す)のに最適な場所がわかりません。フィートとインチ)。

4

2 に答える 2

6

私の知る限り、レンダリング以外はカスタム入力に移動することはできません。SimpleFormは、フォームが送信されると呼び出されないため、値に実際に干渉することはありません。過去にも必要だったので、これについては間違っていたいと思います。とにかく、これはモデルに変換ロジックを保持するバージョンです。

カスタムSimpleForm入力:

# app/inputs/feet_and_inch_input.rb
class FeetAndInchInput < SimpleForm::Inputs::Base
  def input
    output           = ""
    label            = @options.fetch(:label) { @attribute_name.to_s.capitalize }

    feet_attribute   = "#{attribute_name}_feet".to_sym
    inches_attribute = "#{attribute_name}_inches".to_sym

    output << @builder.input(feet_attribute, wrapper: false, label: label)
    output << template.content_tag(:span, " feet ")
    output << @builder.input(inches_attribute, wrapper: false, label: false)
    output << template.content_tag(:span, " inches ")

    output.html_safe
  end

  def label
    ""
  end
end

フォーム。カスタム入力内にタグを配置しなかったことに注意してください<li>。この方法の方が柔軟性が高いと思いますが、自由に変更してください。

# app/views/clients/_form.html.erb
<li>
  <%= f.input :height, as: :feet_and_inch %>
</li>

これはすべて、すべての属性について、height属性も持っているという事実に依存しています。height_feetheight_inches

モデルについては、これが進むべき道であるかどうかは正直にわかりません。誰かがより良い解決策を考え出すかもしれませんが、ここでは次のようになります。

class Client < ActiveRecord::Base
  attr_accessible :name

  ["height", "weight"].each do |attribute|
    attr_accessible "#{attribute}_feet".to_sym
    attr_accessible "#{attribute}_inches".to_sym

    before_save do
      feet  = instance_variable_get("@#{attribute}_feet_ins_var").to_d
      inches = instance_variable_get("@#{attribute}_inches_ins_var").to_d

      self.send("#{attribute}=", feet*12 + inches)
    end

    define_method "#{attribute}_feet" do
      value = self.send(attribute)
      value.floor / 12 if value
    end

    define_method "#{attribute}_feet=" do |feet|
      instance_variable_set("@#{attribute}_feet_ins_var", feet)
    end

    define_method "#{attribute}_inches=" do |inches|
      instance_variable_set("@#{attribute}_inches_ins_var", inches)
    end

    define_method "#{attribute}_inches" do
      value = self.send(attribute)
      value % 12 if value && value % 12 != 0
    end
  end
end

基本的に同じことを行いますが、メソッドを動的に定義します。上部に、これらのメソッドを生成する属性のリストがあります。

これらすべてが完全にテストされているわけではなく、猫を殺す可能性がありますが、うまくいけばいくつかのアイデアを与えることができることに注意してください。

于 2012-12-28T18:05:36.093 に答える
2

私の謙虚な意見は、ユーザーが1つのフィールドにデータを入力するだけで、ユーザーエクスペリエンスが向上するということです。これが私の懸念です:

限られた範囲(おそらく人間の身長)の高さを使用していると仮定すると、ユーザー入力(インチまたはフィート)を検出する検証を記述できます。次に、入力が意図したもの(インチまたはフィートが検出された)であるかどうかを尋ねる検証リンク(またはより適切なボタン)を作成できます。

これはすべて(インチ->フィートの寸法変換を含む)javascriptで実行でき、Ajax呼び出しによって現在の寸法をフェッチして、ページのコード全体を再読み込みすることを回避できます。

編集:私は複雑な入力に関連する興味深い視点を見つけました。フィートとインチでフォームに入力する際のユーザーインタラクションに関するもう1つの便利なリソース。

あなたの質問は本当に興味深いものであり、私はあなたが選んだ解決策を見てみたいです。

于 2012-12-21T12:03:04.317 に答える