neuron 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/views/defaults/_form.html.haml +3 -0
- data/app/views/defaults/edit.html.haml +4 -0
- data/app/views/defaults/index.atom.builder +50 -0
- data/app/views/defaults/index.html.haml +4 -0
- data/app/views/defaults/new.html.haml +4 -0
- data/app/views/defaults/update.js.erb +1 -0
- data/app/views/shared/_flash_messages.html.haml +6 -0
- data/config/locales/neuron.en.yml +4 -0
- data/config/locales/neuron.ru.yml +4 -0
- data/lib/neuron/authorization.rb +23 -0
- data/lib/neuron/integrations/cancan_inherited_resources.rb +83 -0
- data/lib/neuron/rails.rb +10 -0
- data/lib/neuron/resolver.rb +1 -1
- data/lib/neuron/resources.rb +144 -0
- data/lib/neuron/version.rb +1 -1
- data/lib/neuron.rb +25 -7
- metadata +15 -2
@@ -0,0 +1,50 @@
|
|
1
|
+
atom_feed(
|
2
|
+
root_url: collection_url(page: params[:page], format: :html),
|
3
|
+
language: I18n.locale,
|
4
|
+
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'
|
5
|
+
) do |feed|
|
6
|
+
feed.title(head_title)
|
7
|
+
feed.updated(collection.first.try(:created_at))
|
8
|
+
feed.icon "http://#{request.host}/favicon.ico"
|
9
|
+
|
10
|
+
if collection.respond_to?(:total_pages) # WillPaginate::Collection
|
11
|
+
feed.link(rel: :first, type: 'application/atom+xml', href: collection_url(format: :atom))
|
12
|
+
feed.link(rel: :last, type: 'application/atom+xml', href: collection_url(format: :atom, page: collection.total_pages))
|
13
|
+
if collection.previous_page
|
14
|
+
feed.link(rel: :previous, type: 'application/atom+xml', href: collection_url(format: :atom, page: collection.previous_page))
|
15
|
+
end
|
16
|
+
if collection.next_page
|
17
|
+
feed.link(rel: :next, type: 'application/atom+xml', href: collection_url(format: :atom, page: collection.next_page))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if @user
|
22
|
+
atom_author(feed, @user)
|
23
|
+
end
|
24
|
+
|
25
|
+
collection.each do |resource|
|
26
|
+
feed.entry(resource, url: atom_entry_url(resource)) do |entry|
|
27
|
+
entry.title(resource)
|
28
|
+
|
29
|
+
if resource.respond_to?(:content)
|
30
|
+
entry.content simple_format(resource.content), type: :html
|
31
|
+
end
|
32
|
+
|
33
|
+
if resource.respond_to?(:user)
|
34
|
+
atom_author(entry, resource.user)
|
35
|
+
end
|
36
|
+
|
37
|
+
if resource.respond_to?(:keywords)
|
38
|
+
atom_categories(entry, resource.keywords)
|
39
|
+
end
|
40
|
+
|
41
|
+
if resource.respond_to?(:comments)
|
42
|
+
atom_replies(entry, resource)
|
43
|
+
end
|
44
|
+
|
45
|
+
if resource.respond_to?(:commentable) && resource.commentable.respond_to?(:comments)
|
46
|
+
atom_in_reply_to(feed, resource.commentable)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
console.log(<%= "#<#{resource_class}:#{resource.id}> #{resource.changed? ? 'has not' : 'has'} been updated".to_json %>);
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'neuron'
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
module Neuron
|
5
|
+
module Authorization
|
6
|
+
module Controller
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
rescue_from CanCan::AccessDenied do |exception|
|
11
|
+
access_denied(exception)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def access_denied(exception = nil)
|
16
|
+
redirect_to '/422.html'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module View
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'inherited_resources'
|
2
|
+
require 'cancan'
|
3
|
+
|
4
|
+
module InheritedResources
|
5
|
+
module Actions
|
6
|
+
# GET /resources/1/edit
|
7
|
+
def edit(options={}, &block)
|
8
|
+
authorize! authorization_action, resource
|
9
|
+
respond_with(*(with_chain(resource) << options), &block)
|
10
|
+
end
|
11
|
+
alias :edit! :edit
|
12
|
+
end
|
13
|
+
|
14
|
+
module BaseHelpers
|
15
|
+
protected
|
16
|
+
|
17
|
+
def resource
|
18
|
+
get_resource_ivar ||
|
19
|
+
set_resource_ivar(end_of_association_chain.accessible_by(current_ability, authorization_action).send(method_for_find, params[:id])).tap do |resource|
|
20
|
+
authorize!(authorization_action, resource)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_resource
|
25
|
+
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build)).tap do |resource|
|
26
|
+
current_ability.attributes_for(authorization_action, resource_class).each do |attribute, value|
|
27
|
+
resource.send("#{attribute}=", value) if attribute.is_a?(Symbol)
|
28
|
+
end
|
29
|
+
resource.attributes = resource_params
|
30
|
+
authorize!(action_name, resource)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def collection
|
35
|
+
get_collection_ivar || begin
|
36
|
+
authorize!(authorization_action, resource_class)
|
37
|
+
set_collection_ivar(end_of_association_chain.accessible_by(current_ability, authorization_action).paginate(page: params[:page]))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_resource(object)
|
42
|
+
authorize!(authorization_action, object)
|
43
|
+
object.save
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_resource(object, attributes)
|
47
|
+
authorize!(authorization_action, object)
|
48
|
+
object.update_attributes(attributes)
|
49
|
+
end
|
50
|
+
|
51
|
+
def destroy_resource(object)
|
52
|
+
authorize!(authorization_action, object)
|
53
|
+
object.destroy
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def authorization_action
|
59
|
+
@authorization_action ||= action_name.to_sym
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module BelongsToHelpers
|
64
|
+
private
|
65
|
+
|
66
|
+
# Evaluate the parent given. This is used to nest parents in the
|
67
|
+
# association chain.
|
68
|
+
def evaluate_parent(parent_symbol, parent_config, chain = nil) #:nodoc:
|
69
|
+
instantiated_object = instance_variable_get("@#{parent_config[:instance_name]}")
|
70
|
+
return instantiated_object if instantiated_object
|
71
|
+
|
72
|
+
parent = if chain
|
73
|
+
chain.send(parent_config[:collection_name])
|
74
|
+
else
|
75
|
+
parent_config[:parent_class]
|
76
|
+
end.accessible_by(current_ability, :read)
|
77
|
+
|
78
|
+
parent = parent.send(parent_config[:finder], params[parent_config[:param]])
|
79
|
+
|
80
|
+
instance_variable_set("@#{parent_config[:instance_name]}", parent)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/neuron/rails.rb
ADDED
data/lib/neuron/resolver.rb
CHANGED
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'neuron'
|
2
|
+
|
3
|
+
module Neuron
|
4
|
+
module Resources
|
5
|
+
module Controller
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def resources(options = {})
|
10
|
+
inherit_resources
|
11
|
+
append_neuron_view_path_resolver
|
12
|
+
if options[:orders] == true
|
13
|
+
order_scopes
|
14
|
+
elsif options[:orders]
|
15
|
+
order_scopes(options[:orders])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
# Adds default ordering scopes for #index action
|
19
|
+
# @param [Hash] options options hash
|
20
|
+
# @option options [Array, Symbol, String] :ascending default ascending scopes
|
21
|
+
# @option options [Array, Symbol, String] :descending default descending scopes
|
22
|
+
def order_scopes(options = {})
|
23
|
+
with_options only: :index, type: :array do |index|
|
24
|
+
index.has_scope(:ascending) { |controller, scope, values| values.any? ? scope.asc(*values) : scope }
|
25
|
+
index.has_scope(:descending) { |controller, scope, values| values.any? ? scope.desc(*values) : scope }
|
26
|
+
end
|
27
|
+
prepend_before_filter :set_default_order
|
28
|
+
define_method(:set_default_order) do
|
29
|
+
unless params[:ascending] || params[:descending]
|
30
|
+
params[:ascending] = options[:ascending] if options[:ascending]
|
31
|
+
params[:descending] = options[:descending] if options[:descending]
|
32
|
+
end
|
33
|
+
params[:ascending] = Array(params[:ascending])
|
34
|
+
params[:descending] = Array(params[:descending])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module View
|
41
|
+
# Creates a link that alternates between acending and descending
|
42
|
+
# @param [Hash] options options hash
|
43
|
+
# @param [Hash] html_options html options hash
|
44
|
+
# @option options [Symbol, String] :by the name of the columnt to sort by
|
45
|
+
# @option options [String] :as the text used in link, defaults to human_method_name of :by
|
46
|
+
# @option options [String] :params hash with additional params which will be added to generated url
|
47
|
+
def order(options = {}, html_options = {})
|
48
|
+
options[:by] = options[:by].to_sym
|
49
|
+
options[:as] ||= human(resource_class, options[:by])
|
50
|
+
asc_orders = Array(params[:ascending]).map(&:to_sym)
|
51
|
+
desc_orders = Array(params[:descending]).map(&:to_sym)
|
52
|
+
ascending = asc_orders.include?(options[:by])
|
53
|
+
selected = ascending || desc_orders.include?(options[:by])
|
54
|
+
new_scope = ascending ? :descending : :ascending
|
55
|
+
url_options = params.dup.merge(ascending: asc_orders, descending: desc_orders)
|
56
|
+
|
57
|
+
if selected
|
58
|
+
css_classes = html_options[:class] ? html_options[:class].split(/\s+/) : []
|
59
|
+
if ascending # selected
|
60
|
+
options[:as] = "▲ #{options[:as]}"
|
61
|
+
css_classes << 'ascending'
|
62
|
+
url_options[:ascending] = url_options[:ascending] - [options[:by]]
|
63
|
+
else # descending selected
|
64
|
+
options[:as] = "▼ #{options[:as]}"
|
65
|
+
css_classes << 'descending'
|
66
|
+
url_options[:descending] = url_options[:descending] - [options[:by]]
|
67
|
+
end
|
68
|
+
html_options[:class] = css_classes.join(' ')
|
69
|
+
end
|
70
|
+
url_options[new_scope] += [options[:by]]
|
71
|
+
url_options[:ascending] = url_options[:ascending].uniq
|
72
|
+
url_options[:descending] = url_options[:descending].uniq
|
73
|
+
link_to(options[:as].html_safe, collection_path(url_options.deep_merge(options[:params] || {})), html_options)
|
74
|
+
end
|
75
|
+
|
76
|
+
def collection_title(collection = nil, tag = :h1)
|
77
|
+
collection ||= self.collection
|
78
|
+
options = {count: collection.count}
|
79
|
+
''.html_safe.tap do |result|
|
80
|
+
result << title(t("#{controller_i18n_scope}.#{view_name}.title",
|
81
|
+
options.merge(default: t("navigation.#{controller_i18n_scope}.#{action_name}", options))),
|
82
|
+
tag: tag)
|
83
|
+
if can?(:create, resource_class) && controller.respond_to?(:create)
|
84
|
+
result << link_to(t("#{controller_i18n_scope}.new", scope: :actions, default: [:new, 'New']), new_resource_path)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def collection_list(collection = nil, collection_name = nil)
|
90
|
+
collection ||= self.collection
|
91
|
+
collection_name ||= self.resource_collection_name
|
92
|
+
if collection.respond_to?(:total_pages)
|
93
|
+
start = 1 + (collection.current_page - 1) * collection.per_page
|
94
|
+
pagination = will_paginate(collection)
|
95
|
+
else
|
96
|
+
start = 1
|
97
|
+
pagination = ''
|
98
|
+
end
|
99
|
+
content_tag(:ol,
|
100
|
+
render(collection),
|
101
|
+
class: "b-list b-list_#{collection_name.to_s.gsub(/_/, '-')}",
|
102
|
+
start: start) << pagination
|
103
|
+
end
|
104
|
+
|
105
|
+
def collection_block(collection = nil, tag = :h1, &block)
|
106
|
+
collection ||= self.collection
|
107
|
+
content_tag(:article, class: 'b-collection') do
|
108
|
+
''.html_safe.tap do |result|
|
109
|
+
result << content_tag(:header, collection_title(collection, tag), class: 'b-collection__header')
|
110
|
+
if block_given?
|
111
|
+
result << capture(&block)
|
112
|
+
else
|
113
|
+
result << if collection.any?
|
114
|
+
collection_list(collection)
|
115
|
+
else
|
116
|
+
content_tag(:p, t(:no_entries, :scope => [:resources, :collection, :no_entries], :default => [controller_i18n_scope.to_sym, :all]))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def resource_title(resource = nil)
|
124
|
+
resource ||= self.resource
|
125
|
+
action = action_name.to_sym
|
126
|
+
''.html_safe.tap do |result|
|
127
|
+
result << title(t("navigation.#{controller_i18n_scope}.#{action}",
|
128
|
+
resource: link_to(resource, canonical_path(resource)),
|
129
|
+
default: resource.to_s).html_safe)
|
130
|
+
if (action == :show) && can?(:update, resource)
|
131
|
+
result << content_tag(:sup,
|
132
|
+
link_to(t(:edit,
|
133
|
+
object: resource,
|
134
|
+
scope: :actions,
|
135
|
+
default: [:"#{controller_i18n_scope}.edit", :edit, 'Edit']), edit_resource_path))
|
136
|
+
end
|
137
|
+
#if (action == :edit) && can?(:update, resource)
|
138
|
+
#result << content_tag(:sup, link_to(t(:edit, :scope => "actions.#{controller_i18n_scope}"), edit_resource_path))
|
139
|
+
#end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/lib/neuron/version.rb
CHANGED
data/lib/neuron.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
require 'neuron/version'
|
2
2
|
|
3
3
|
module Neuron
|
4
|
-
autoload :Application,
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
4
|
+
autoload :Application, 'neuron/application'
|
5
|
+
autoload :Authorization, 'neuron/authorization'
|
6
|
+
autoload :Controller, 'neuron/controller'
|
7
|
+
autoload :Navigation, 'neuron/navigation'
|
8
|
+
autoload :Resolver, 'neuron/resolver'
|
9
|
+
autoload :Resources, 'neuron/resources'
|
10
|
+
autoload :Railtie, 'neuron/rails'
|
11
|
+
autoload :View, 'neuron/view'
|
9
12
|
|
10
|
-
def self.
|
13
|
+
def self.setup!
|
11
14
|
if defined?(ActionView)
|
12
15
|
ActionView::Base.send :include, Neuron::View
|
13
16
|
ActionView::Base.send :include, Neuron::Navigation::View
|
@@ -15,7 +18,22 @@ module Neuron
|
|
15
18
|
if defined?(ActionController)
|
16
19
|
ActionController::Base.send :include, Neuron::Controller
|
17
20
|
end
|
21
|
+
if defined?(InheritedResources)
|
22
|
+
ActionController::Base.send :include, Neuron::Resources::Controller
|
23
|
+
ActionView::Base.send :include, Neuron::Resources::View
|
24
|
+
if defined?(CanCan)
|
25
|
+
require 'neuron/integrations/cancan_inherited_resources'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
if defined?(CanCan)
|
29
|
+
ActionController::Base.send :include, Neuron::Authorization::Controller
|
30
|
+
ActionView::Base.send :include, Neuron::Authorization::View
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.path
|
35
|
+
File.expand_path('../..', __FILE__)
|
18
36
|
end
|
19
37
|
end
|
20
38
|
|
21
|
-
|
39
|
+
require 'neuron/rails' if defined?(Rails)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neuron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-05-
|
12
|
+
date: 2011-05-30 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: Code reused in many applications
|
15
15
|
email:
|
@@ -21,11 +21,24 @@ files:
|
|
21
21
|
- .gitignore
|
22
22
|
- Gemfile
|
23
23
|
- Rakefile
|
24
|
+
- app/views/defaults/_form.html.haml
|
25
|
+
- app/views/defaults/edit.html.haml
|
26
|
+
- app/views/defaults/index.atom.builder
|
27
|
+
- app/views/defaults/index.html.haml
|
28
|
+
- app/views/defaults/new.html.haml
|
29
|
+
- app/views/defaults/update.js.erb
|
30
|
+
- app/views/shared/_flash_messages.html.haml
|
31
|
+
- config/locales/neuron.en.yml
|
32
|
+
- config/locales/neuron.ru.yml
|
24
33
|
- lib/neuron.rb
|
25
34
|
- lib/neuron/application.rb
|
35
|
+
- lib/neuron/authorization.rb
|
26
36
|
- lib/neuron/controller.rb
|
37
|
+
- lib/neuron/integrations/cancan_inherited_resources.rb
|
27
38
|
- lib/neuron/navigation.rb
|
39
|
+
- lib/neuron/rails.rb
|
28
40
|
- lib/neuron/resolver.rb
|
41
|
+
- lib/neuron/resources.rb
|
29
42
|
- lib/neuron/version.rb
|
30
43
|
- lib/neuron/view.rb
|
31
44
|
- neuron.gemspec
|