6

Tôi đang cố gắng lưu một hàm băm tùy chọn trong một trường DB. Biểu mẫu có thể lưu dữ liệu vào DB nhưng không thể truy xuất lại dữ liệu đó khi tôi chỉnh sửa nó (ví dụ: tất cả các trường khác được điền sẵn ngoại trừ trường wp_options).Sử dụng Trình trợ giúp biểu mẫu đường ray với Lớp tùy chỉnh được nối tiếp

class Profile < ActiveRecord::Base 
serialize :wp_options 
end 

Đây là lớp học của tôi tùy chỉnh:

class WP_Options 
attr_accessor :wp_name, :wp_desc, :wp_limit 
end 

Ở dạng của tôi:

<%= form_for(@profile, :remote => true) do |f| %> 
... 
    <%= f.fields_for :wp_options do |wp_options| %> 
     <%= wp_options.text_field :wp_name %> 
    <% end %> 
... 

Trong điều khiển của tôi:

@profile = Profile.new(:wp_options => WP_Options.new) 

Trong cột DB của tôi 'wp_options':

--- !map:ActiveSupport::HashWithIndifferentAccess 
wp_name: Test 

Mọi lời khuyên sẽ thực sự được đánh giá cao.

Trả lời

10

Thực ra rất dễ dàng. Bạn cần sử dụng lớp học với các phương thức reader. Bạn có thể tạo nó bằng nhiều cách khác nhau, nhưng cách dễ nhất là sử dụng lớp OpenStruct (thông báo, rằng nó sẽ không thể thấy các trường nằm trong các phương thức của OpenStruct ... lớp này không thể định nghĩa lại các phương thức).

Ở dạng của bạn, bạn nên thêm:

<%= f.fields_for :wp_options, @profile.wp_options do |wp_options| %> 

Thay vì @profile (nếu bạn có biến động), bạn có thể sử dụng f.object.wp_options.

Và đối với mô hình Profile bạn nên thêm phương thức wp_options.

def wp_options 
    OpenStruct.new(self.attributes['wp_options']) 
end 

Trong trường hợp đó, nó sẽ chỉ hoạt động nếu wp_options được tuần tự hóa của bạn là lớp Hash.

Hy vọng điều đó sẽ hữu ích.

PS. Tôi đã sử dụng kỹ thuật tương tự, nhưng vì tôi có các khóa băm type, OpenStruct không thể tạo ra nó, vì vậy tôi đã sử dụng lớp Struct đơn giản. Tôi đã data cột:

def data 
    keys = current_data.keys 
    data = attributes[:data] 
    Struct.new(*keys).new(*keys.map { |k| data[k] }) 
end 

Một chút ít tầm thường, nhưng dù sao các phương pháp tương tự (trước đó tôi đã tạo ra lớp học đặc biệt, nhưng bây giờ tôi biết rằng Struct là cách tốt hơn để tạo ra của những thứ loại More. ý tưởng mà bạn có thể tìm thấy ở đây: How do I use hash keys as methods on a class?)

+0

Tôi cần tương đương wp_options để giữ nguyên dạng băm để tôi có thể lặp lại các mục nhập của nó. Vì vậy, tôi đã không thực hiện bất kỳ thay đổi nào đối với mô hình và đặt 'OpenStruct.new' ở dạng như sau: <% = f.fields_for: wp_options, OpenStruct.new (@ profile.wp_options) do | wp_options | %> Có thể nó có chế độ xem nhìn vào việc triển khai mô hình, nhưng tất cả những gì nó biết là wp_options là một hàm băm thay vì một đối tượng có phương thức attr. – Turadg

1

Đối với những người sử dụng giải pháp Dmitry, trên đường ray 3.0.5 (không chắc chắn về trước/phiên bản tiếp theo vì vậy hãy thử trước đó), thêm

require 'ostruct' 

đến file environment.rb của bạn để có OpenStruct inc luded.

Nếu bạn sắp xếp hàng tuần với JSON, trong mô hình của bạn thêm (oh và tôi khá mới đối với RoR, vì vậy hãy xem xét kỹ lưỡng và đề xuất giải pháp "hoạt động" tốt hơn) () tên biến của tôi thay đổi để phù hợp với ví dụ trên):

before_save :json_serialize 
after_save :json_deserialize 
after_find :json_deserialize 

def json_serialize 
    self.wp_options = ActiveSupport::JSON.encode(self.attributes['wp_options']) 
end 

def json_deserialize 
    unless (self.attributes['wp_options'].nil?) 
    self.wp_options = ActiveSupport::JSON.decode(self.attributes['wp_options'].to_s) 
    end 
end 

trên một lưu ý cuối cùng: tôi thành thật không chắc chắn lý do tại sao nó phải được lưu trữ vào self.wp_options và không self.attributes [ 'wp_options '], nếu ai đó có thể giải thích nó sẽ rất tuyệt.

0

Tôi gặp phải vấn đề tương tự. Giải pháp của tôi là như sau:

  1. Xác định một phương pháp trong helper của bạn:

    def wp_options_text_field(profile, wp_options, name) 
        wp_options.text_field name, :value => profile.wp_options[name] 
    end 
    
  2. Theo quan điểm của bạn:

    <%= form_for(@profile, :remote => true) do |f| %> 
    ... 
    <%= f.fields_for :wp_options do |wp_options| %> 
        <%= wp_options_text_field :wp_name %> 
    <% end %> 
    ... 
    

Vấn đề duy nhất ở đây là bạn' sẽ cần phải định nghĩa các phương thức cho mỗi phương thức trợ giúp bạn sẽ sử dụng. Trong trường hợp của tôi, tôi chỉ có 2 phương pháp được sử dụng và nó không đau đớn.

Các vấn đề liên quan