如何使用best_in_place gem更改序列化数据?

时间:2014-01-22 15:25:30

标签: ruby-on-rails ruby-on-rails-3 serialization best-in-place

我有一个包含序列化数据的模型,我想使用best_in_place gem编辑这些数据。使用best_in_place gem时,默认情况下这是不可能的。怎么办呢?

1 个答案:

答案 0 :(得分:4)

可以通过扩展method_missingrespond_to_missing?将请求转发到序列化数据来完成。假设您在Hash中已将序列化data。在包含序列化数据的类中,您可以使用此代码:

def method_missing(method_name, *arguments, &block) # forewards the arguments to the correct methods
  if method_name.to_s =~ /data_(.+)\=/
    key = method_name.to_s.match(/data_(.+)=/)[1]
    self.send('data_setter=', key, arguments.first)
  elsif method_name.to_s =~ /data_(.+)/
    key = method_name.to_s.match(/data_(.+)/)[1]
    self.send('data_getter', column_number)
  else
    super
  end
end

def respond_to_missing?(method_name, include_private = false) # prevents giving UndefinedMethod error
  method_name.to_s.start_with?('data_') || super
end

def data_getter(key)
  self.data[key.to_i] if self.data.kind_of?(Array)
  self.data[key.to_sym] if self.data.kind_of?(Hash)
end

def data_setter(key, value)
  self.data[key.to_i] = value if self.data.kind_of?(Array)
  self.data[key.to_sym] = value if self.data.kind_of?(Hash)
  value # the method returns value because best_in_place sets the returned value as text
end

现在,您可以使用getter object.data_name访问object.data [:name],并使用setter object.data_name =“test”设置值。但要使用best_in_place使其正常工作,您需要动态地将其添加到attr_accessible列表中。为此,您需要更改mass_assignment_authorizer的行为,并使对象响应accessable_methods,并使用应允许编辑的方法名称数组:

def accessable_methods # returns a list of all the methods that are responded dynamicly
  self.data.keys.map{|x| "data_#{x.to_s}".to_sym }
end

private
  def mass_assignment_authorizer(user) # adds the list to the accessible list.
    super + self.accessable_methods
  end

因此,在视图中,您现在可以调用

  best_in_place @object, :data_name

编辑@ object.data [:name]

的序列化数据

//您也可以使用元素索引而不是属性名称对数组执行此操作:

<% @object.data.count.times do |index| %>
  <%= best_in_place @object, "data_#{index}".to_sym %>
<% end %>

您无需更改其余代码。