Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/handle ancestor relation #74

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,34 @@ editable @model, :enabled, source: source, classes: classes, class: "label"
%h1= editable [picture.gallery, picture], :name, nested: :translations, nid: picture.translation.id
```

* **nest_def (takes precedence to the two options above)** - Hash or array of hash that describes the nestd attributes

```ruby
class Group << ActiveRecord::Base
has_many :users
end

class User << ActiveRecord::Base
# name: string
belongs_to :group
has_many :posts
end

class Post << ActiveRecord::Base
# title: string
belongs_to :user
end


%h1= editable @group, :name, nest_def: {users: @user.id}
#=> the params will be {group: {users_attributes: {id: <@user.id>, name: <name>}}}

%h1= editable @group, :title, nest_def: [{users: @user.id}, {posts: @post.id}]
#=> the params will be {group: {users_attributes: {id: <@user.id>, posts_attributes: {id: <@post.id>, title: <title>} }}
# Note that the order of array matters.

```

### Authorization

Add a helper method to your controllers to indicate if `x-editable` should be enabled.
Expand Down
59 changes: 49 additions & 10 deletions lib/x-editable-rails/view_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary spacing detected.
Operator ? should be surrounded by a single space.

}
source = options[:source] ? format_source(options.delete(:source), value) : default_source_for(value)
classes = format_source(options.delete(:classes), value)


Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra blank line detected.

title = options.delete(:title) do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary spacing detected.
Operator = should be surrounded by a single space.

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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is too long. [170/80]

else
klass = nested ? object.class.const_get(nested.to_s.classify) : object.class

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is too long. [92/80]

end
klass.human_attribute_name(method)
end

Expand All @@ -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 ),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is too long. [93/80]
Space inside parentheses detected.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.

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?}
Expand Down Expand Up @@ -145,6 +157,33 @@ def default_source_for(value)
end
end

def dig_nested_obj(obj, nested)
case(nested)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after keyword case is missing.

when Array

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent when as deep as case.

obj = nested.inject(obj){|memo, n|

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using {...} for multi-line blocks.

attr = n.keys.first
id = n.values.first
case(memo.class.reflect_on_association(attr))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after keyword case is missing.

when ActiveRecord::Reflection::HasOneReflection

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent when as deep as case.

memo = memo.send(attr)
when ActiveRecord::Reflection::HasManyReflection

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent when as deep as case.

memo = memo.send(attr).find_by(id: id)
end
memo
}
when Hash

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent when as deep as case.

attr = nested.keys.first
id = nested.values.first
obj = case(obj.class.reflect_on_association(attr))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after keyword case is missing.

when ActiveRecord::Reflection::HasOneReflection

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent when as deep as case.

obj.send(attr)
when ActiveRecord::Reflection::HasManyReflection

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent when as deep as case.

obj.send(attr).find_by(id: id)
end
end
return obj

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant return detected.

end

# helper method that take some shorthand source definitions and reformats them
def format_source(source, value)
formatted_source = case value
Expand Down
25 changes: 24 additions & 1 deletion vendor/assets/javascripts/editable/rails/editable_form.js.coffee
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
unless EditableForm
build_nested_param = (attr_to_update, updated_value, nest_def)->

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function arrows (-> and =>) must be spaced properly

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) =>
Expand All @@ -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
Expand Down
14 changes: 12 additions & 2 deletions vendor/assets/javascripts/editable/rails/error_handling.js.coffee
Original file line number Diff line number Diff line change
@@ -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])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function arrows (-> and =>) must be spaced properly

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 "; "
error_msgs.join "; "