diff --git a/lib/x-editable-rails/view_helpers.rb b/lib/x-editable-rails/view_helpers.rb index 54cd7be..5475b11 100644 --- a/lib/x-editable-rails/view_helpers.rb +++ b/lib/x-editable-rails/view_helpers.rb @@ -26,18 +26,29 @@ def editable(object, method, options = {}) url = options.delete(:url){ polymorphic_path(object) } object = object.last if object.kind_of?(Array) - value = options.delete(:value){ object.send(method) } - source = options[:source] ? format_source(options.delete(:source), value) : default_source_for(value) - classes = format_source(options.delete(:classes), value) error = options.delete(:e) html_options = options.delete(:html){ Hash.new } if xeditable?(object) - model = object.class.model_name.param_key - nid = options.delete(:nid) - nested = options.delete(:nested) - title = options.delete(:title) do - klass = nested ? object.class.const_get(nested.to_s.classify) : object.class + model = object.class.model_name.param_key + nid = options.delete(:nid) + nested = options.delete(:nested) + nest_def = options.delete(:nest_def) + + deepest_obj = nest_def ? dig_nested_obj(object, nest_def) : object + value = options.delete(:value){ + nest_def ? deepest_obj.send(method) : object.send(method) + } + source = options[:source] ? format_source(options.delete(:source), value) : default_source_for(value) + classes = format_source(options.delete(:classes), value) + + + title = options.delete(:title) do + if nest_def + klass = nest_def.is_a?(Array) ? object.class.const_get(nest_def.last.keys.first.to_s.classify) : object.class.const_get(nest_def.keys.first.to_s.classify) + else + klass = nested ? object.class.const_get(nested.to_s.classify) : object.class + end klass.human_attribute_name(method) end @@ -54,13 +65,14 @@ def editable(object, method, options = {}) type: type, model: model, name: method, - value: ( type == 'wysihtml5' ? Base64.encode64(output_value) : output_value ), + value: ( type == 'wysihtml5' ? Base64.encode64(output_value) : output_value ), placeholder: placeholder, classes: classes, source: source, url: url, nested: nested, - nid: nid + nid: nid, + nest_def: nest_def }.merge(options.symbolize_keys) data.reject!{|_, value| value.nil?} @@ -145,6 +157,33 @@ def default_source_for(value) end end + def dig_nested_obj(obj, nested) + case(nested) + when Array + obj = nested.inject(obj){|memo, n| + attr = n.keys.first + id = n.values.first + case(memo.class.reflect_on_association(attr)) + when ActiveRecord::Reflection::HasOneReflection + memo = memo.send(attr) + when ActiveRecord::Reflection::HasManyReflection + memo = memo.send(attr).find_by(id: id) + end + memo + } + when Hash + attr = nested.keys.first + id = nested.values.first + obj = case(obj.class.reflect_on_association(attr)) + when ActiveRecord::Reflection::HasOneReflection + obj.send(attr) + when ActiveRecord::Reflection::HasManyReflection + obj.send(attr).find_by(id: id) + end + end + return obj + end + # helper method that take some shorthand source definitions and reformats them def format_source(source, value) formatted_source = case value diff --git a/vendor/assets/javascripts/editable/rails/editable_form.js.coffee b/vendor/assets/javascripts/editable/rails/editable_form.js.coffee index 745e4b1..a8314af 100644 --- a/vendor/assets/javascripts/editable/rails/editable_form.js.coffee +++ b/vendor/assets/javascripts/editable/rails/editable_form.js.coffee @@ -1,10 +1,31 @@ unless EditableForm + build_nested_param = (attr_to_update, updated_value, nest_def)-> + ret = {} + last = ret + if(Array.isArray(nest_def)) + for obj in nest_def + attr = Object.keys(obj)[0] + key = attr + "_attributes" + id = obj[attr] + last[key] = {id: id} + last = last[key] + else if (typeof nest_def == "object" && nest_def != null) + attr = Object.keys(nest_def)[0] + key = attr + "_attributes" + id = nest_def[attr] + last[key] = {id: id} + last = last[key] + + last[attr_to_update] = updated_value + ret + EditableForm = $.fn.editableform.Constructor EditableForm.prototype.saveWithUrlHook = (value) -> originalUrl = @options.url model = @options.model nestedName = @options.nested nestedId = @options.nid + nestDef = @options.nestDef nestedLocale = @options.locale @options.url = (params) => @@ -20,7 +41,9 @@ unless EditableForm obj = {} - if nestedName + if nestDef + obj = build_nested_param(myName, myValue, nestDef) + else if nestedName nested = {} nested[myName] = myValue nested['id'] = nestedId diff --git a/vendor/assets/javascripts/editable/rails/error_handling.js.coffee b/vendor/assets/javascripts/editable/rails/error_handling.js.coffee index df81815..f8edb03 100644 --- a/vendor/assets/javascripts/editable/rails/error_handling.js.coffee +++ b/vendor/assets/javascripts/editable/rails/error_handling.js.coffee @@ -1,4 +1,14 @@ $.fn.editable.defaults.error = (response, newValue) -> - field_name = $(this).data("name") + nested = $(this).data('nested') + if(Array.isArray(nested)) + keys = nested.map((obj)-> Object.keys(obj)[0]) + keys.push($(this).data("name")) + field_name = keys.join(".") + else if (typeof nested == "object" && nested != null) + key = Object.keys(nested)[0] + field_name = key + "." + $(this).data("name") + else + field_name = $(this).data("name") + error_msgs = response.responseJSON.errors[field_name] - error_msgs.join "; " \ No newline at end of file + error_msgs.join "; "