2012-03-08 10 views
10

Tôi có những điều sau đây.Trường băm được nối tiếp và Biểu mẫu đơn giản

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

Giá trị của fields sẽ tùy thuộc vào danh mục. Nhưng làm ví dụ;

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

Trong ví dụ này các loại đã xác định "address""founded" như các lĩnh vực tùy chỉnh.

Điều tôi muốn nói;

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

Nhưng tôi cần phải làm một cái gì đó kỳ diệu để đối phó với thực tế là @page.founded không hợp lệ

Thay vào đó tôi nên nhìn vào @page.fields["founded"].

Mọi đề xuất?


Cập nhật:

Tôi đã có một chút gần

- 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] 

Bây giờ cần phải thực hiện máy sấy này (không muốn nêu rõ tên của đối tượng).

Tôi sẽ xem liệu tôi có thể viết phần mở rộng biểu mẫu đơn giản cho việc này hay không.

Trả lời

25

Tôi đã gặp sự cố tương tự khi cố gắng sử dụng simple_fields_for trên loại trường Hash của mô hình Mongoid. Phiên bản Mongoid ví dụ của bạn tôi đã đối phó với trông như thế này:

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

tình hình của tôi có thể là hơi khác nhau tuy nhiên, như tôi đã biết các phím băm Tôi đang tìm kiếm trước thời hạn, và chỉ cần simple_fields_for làm việc với trường băm. Phương pháp ngây thơ (cơ bản fields_for sử dụng) Tôi đã sử dụng trông như thế này:

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

Nhưng điều đó đã không Populating dạng đúng.giải pháp nicholaides của gói băm trong một cấu trúc làm việc cho tôi:

- 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 

Để tránh phải trộn những thứ OpenStruct vào quan điểm của tôi, tôi đã tạo ra một bản vá khỉ cho simple_form để tự động quấn loại băm trong một OpenStruct và đặt nó vào trình khởi tạo:

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 

Và bây giờ tôi có thể sử dụng giải pháp ngây thơ ban đầu của mình mà không có mã xem đặc biệt.

+0

+1 cho trường "f.simple_fields_for:, OpenStruct.new (@ page.fields) do | ff |". Tôi đã phá hỏng bộ não của mình trong một giờ để tìm ra lý do tại sao nó không lấy lại giá trị đúng cho đến khi tôi thêm bit OpenStruct. – gk0r

+1

Điều này thật tuyệt vời. Một lưu ý bổ sung cho người dùng thông số mạnh mẽ: bạn phải xác định từng trường bạn thêm một cách rõ ràng. Ví dụ, 'params.require (: page) .permit (: fields => [: address,: founded])' –

+0

Thx cho giải pháp, nó hoạt động hoàn hảo, với một ngoại lệ: Tôi không biết, cách thêm xác nhận lỗi cho '@ page.fields'. –

3

Sử dụng OpenStruct. Nó hoạt động như thế này:

require 'ostruct' 

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

thì tốt cho "khả năng gọi" (Tôi nhớ sử dụng 'CallableHash' trong ngày '). Nhưng câu hỏi cụ thể của tôi là về SimpleForm. Tôi muốn một giải pháp gọn gàng. –

1

Đây là một giải pháp bạn có thể dễ dàng thích ứng với vấn đề của bạn:

https://gist.github.com/2157877

Giữ hình thức siêu sạch và giữ cho hành vi bình thường của một mô hình hoạt động (không có gì để thêm vào bộ điều khiển của bạn).

Chúc mừng!

1

Nếu chỉ tôi đã tìm thấy bài đăng này trước đó, tôi sẽ không bỏ lỡ ba ngày về vấn đề này.

tôi đã không thể bình luận về answear vì vậy chỉ cần thêm, nếu có ai cố gắng để fields_for một mảng Mongo của băm (has_many tương tự) thêm bạn sẽ cần phải cung cấp cho các đối tượng OpenStruct gốc với một "#{key}_attributes=" (trong trường hợp này fields_attributes =) phương pháp như vậy fields_for sẽ xác định nó là một mối quan hệ has_many.

Hy vọng nó sẽ giúp ai đó;)