问题
I have a model with serialized data and I want to edit this data using the best_in_place gem. This isn't possible by default when using the best_in_place gem. How can this be done?
回答1:
It can be done by extending method_missing and respond_to_missing? to forward the requests to the serialized data. Lets say you have your serialized Hash in data. In the class that's containing the serialized data you can for example use this code:
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
Now you can access the object.data[:name] using the getter object.data_name and set value using the setter object.data_name="test". But to get this working using best_in_place you need to dynamicly add it to the attr_accessible list. To do this you need to change the behavior of the mass_assignment_authorizer and make the object respond to accessable_methods with an array of method names that should be allowed to be edited like this:
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
So in the View you can now call
best_in_place @object, :data_name
To edit the serialized data of @object.data[:name]
// You can also do this for an array using the element index instead of the attribute name:
<% @object.data.count.times do |index| %>
<%= best_in_place @object, "data_#{index}".to_sym %>
<% end %>
You dont need to change the rest of the code.
来源:https://stackoverflow.com/questions/21286987/how-can-i-change-serialized-data-using-the-best-in-place-gem