2012-03-08 10 views
10

私には以下のものがあります。シリアライズされたハッシュフィールドとシンプルフォーム

class Page < ActiveRecord::Base 
    belongs_to :category 
    serialize :fields 
end 

fieldsの値はカテゴリによって異なります。しかし例として。

{"address" => "8 finance street, hong kong", 
"founded" => "1973"} 

この例では、カテゴリは、カスタムフィールドとして"address""founded"を定義しています。

私が言いたいのは、

= simple_form_for(@page) do |f| 
    = f.association :category 
    - f.object.category.fields.each do |field| 
    = f.input field.name 

しかし、私は@page.foundedは、代わりに私が@page.fields["founded"]されているはずです有効な

ではないという事実に対処するための魔法の何かをする必要があります。

提案がありますか?


更新:

私は

- if f.object.category 
    - f.object.category.fields.each do |field| 
    = f.input field.name do 
     = text_field_tag "post[fields][#{field.name}]", f.object.fields[file.name] 

寄りに少し持っている今(オブジェクトの名前を指定する必要はありません)このドライヤーを行う必要があります。

私はこのためのまともなシンプルなフォーム拡張を書くことができるかどうかを見ていきます。

答えて

25

ハングフィールドタイプのモンゴイドモデルでsimple_fields_forを使用しようとすると、同様の問題が発生しました。私が扱ったあなたの例のMongoidのバージョンは、このように見えた:

class Page 
    include Mongoid::Document 
    field :fields, type: Hash 
end 

私はすでに、私は時間の先を探していますハッシュキーを知っているし、ちょうど仕事にsimple_fields_forを必要に応じて私の状況は、しかし多少異なる場合がありますハッシュフィールドを持つ

= simple_form_for(@page) do |f| 
    = f.simple_fields_for :fields do |ff| 
    = ff.input :address 
    = ff.input :founded 

しかし、それは正しくフォームに移入されませんでした:私が使っていた素朴な方法(基本fields_for使い方)は、このように見えました。構造体にハッシュを包むのnicholaidesのソリューションは、私の仕事:

- require 'ostruct' 
= simple_form_for(@page) do |f| 
    = f.simple_fields_for :fields, OpenStruct.new(@page.fields) do |ff| 
    = ff.input :address 
    = ff.input :founded 

が私の見解にOpenStructのものをミックスすることを避けるために、私は自動的にOpenStructにハッシュの種類をラップし、それを置くためにsimple_formのためのモンキーパッチを作成しました

require 'ostruct' 

module SimpleForm::ActionViewExtensions::Builder 
    def simple_fields_for_with_hash_support(*args, &block) 
    if args[0] && !args[1] 
     field = object.send(args[0]) 
     args << OpenStruct.new(field) if field.respond_to?(:has_key?) 
    end 
    simple_fields_for_without_hash_support(*args, &block) 
    end 
    alias simple_fields_for_without_hash_support simple_fields_for 
    alias simple_fields_for simple_fields_for_with_hash_support 
end 

これで、特別な表示コードなしでオリジナルの使いやすいソリューションを使用できるようになりました。

+0

+1です。私はOpenStructビットを追加するまで、値を正しく取得していなかった理由を解明するために、私の脳を何時間も破壊しました。 – gk0r

+1

これは素晴らしいです。強力なパラメーターユーザーのための追加の注記:明示的に追加する各フィールドを定義する必要があります。たとえば、 'params.require(:page).permit(:fields => [:address、:found])' –

+0

Thxはソリューションのために、それは完璧に動作します。エラーを '@ page.fields'に返します。 –

3

OpenStructを使用してください。それは次のように機能します。ここでは

require 'ostruct' 

struct = OStruct.new("address" => "8 finance street, hong kong", "founded" => "1973") 
struct.address # => 8 
struct.founded # => "1973" 
+0

"コールアベイラビリティ"(これは 'CallableHash'を使って覚えています)には問題ありません。しかし、私の具体的な質問はSimpleFormについてです。私はきちんとした解決策が欲しい。 "f.simple_fields_for:フィールド、OpenStruct.new(@ page.fields)do | ff |"の場合は –

1

は、あなたが簡単にあなたの問題に対応できるソリューションです:

https://gist.github.com/2157877

はフォームスーパークリーンを維持し、アクティブなモデル(何の正常な動作を保ちますあなたのコントローラに追加する)。

乾杯!

1

I'veは、以前の私は、この問題に3日間を逃していないだろう、この記事を見つけた場合にのみ。

だけ追加するようfields_forにハッシュのMongoの配列(のようにhas_many)をしようと誰もがさらにあなたが"#{key}_attributes="(この場合はfields_attributesでルートOpenStructオブジェクトを指定する必要があります場合、私は、answearにコメントすることができませんでした=)メソッドであるので、fields_forはそれがhas_many関係であると識別します。

関連する問題