puffer 0.0.32 → 0.1.0
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/.gitignore +7 -0
- data/Gemfile +1 -26
- data/Gemfile.lock +66 -64
- data/README.md +34 -23
- data/Rakefile +1 -11
- data/VERSION +1 -1
- data/app/assets/javascripts/puffer/application.js +6 -1
- data/app/assets/javascripts/puffer/associations.js +18 -0
- data/app/assets/javascripts/puffer/puffer.js +7 -0
- data/app/assets/javascripts/puffer/right-calendar-src.js +19 -3
- data/app/assets/javascripts/puffer/right-dnd-src.js +591 -0
- data/app/assets/javascripts/puffer/right-in-edit-src.js +373 -0
- data/app/assets/javascripts/puffer/right-keys-src.js +87 -0
- data/app/assets/javascripts/puffer/{paginator.js → right-paginator-src.js} +0 -0
- data/app/assets/javascripts/puffer/right-slider-src.js +29 -32
- data/app/assets/javascripts/puffer/right-sortable-src.js +430 -0
- data/app/assets/javascripts/puffer/right-src.js +358 -99
- data/app/assets/stylesheets/puffer/puffer.css +29 -4
- data/app/components/base/form.html.erb +8 -14
- data/app/components/base_component.rb +1 -1
- data/app/components/boolean/form.html.erb +5 -3
- data/app/components/boolean/index.html.erb +6 -2
- data/app/components/boolean_component.rb +2 -2
- data/app/components/date_time/filter.html.erb +9 -0
- data/app/components/date_time/form.html.erb +8 -4
- data/app/components/date_time_component.rb +21 -5
- data/app/components/file/form.html.erb +8 -4
- data/app/components/hidden/form.html.erb +3 -1
- data/app/components/nested_attributes_many/form.html.erb +47 -0
- data/app/components/nested_attributes_many_component.rb +7 -0
- data/app/components/nested_attributes_one/form.html.erb +48 -0
- data/app/components/nested_attributes_one_component.rb +7 -0
- data/app/components/password/form.html.erb +8 -4
- data/app/components/password_component.rb +1 -1
- data/app/components/references_many/index.html.erb +1 -1
- data/app/components/references_one/choose.html.erb +1 -1
- data/app/components/references_one/form.html.erb +10 -9
- data/app/components/references_one_component.rb +0 -1
- data/app/components/render_component.rb +13 -0
- data/app/components/select/filter.html.erb +4 -2
- data/app/components/select/form.html.erb +8 -4
- data/app/components/text/form.html.erb +8 -4
- data/app/controllers/admin/sessions_controller.rb +1 -21
- data/app/controllers/puffer/base.rb +10 -3
- data/app/controllers/puffer/dashboard_base.rb +7 -1
- data/app/controllers/puffer/{sessions_base.rb → sessions/base.rb} +10 -7
- data/app/controllers/puffer/sessions/clearance.rb +29 -0
- data/app/controllers/puffer/{sessions_devise_base.rb → sessions/devise.rb} +1 -1
- data/app/controllers/puffer/sessions/simple.rb +28 -0
- data/app/controllers/puffer/tree_base.rb +1 -1
- data/app/models/puffer_user.rb +3 -0
- data/app/views/layouts/puffer.html.erb +3 -3
- data/app/views/puffer/base/_edit.html.erb +15 -0
- data/app/views/puffer/base/_index.html.erb +26 -0
- data/app/views/puffer/base/_show.html.erb +13 -0
- data/app/views/puffer/base/_table.html.erb +1 -1
- data/app/views/puffer/base/edit.html.erb +1 -15
- data/app/views/puffer/base/edit.js.erb +1 -0
- data/app/views/puffer/base/index.html.erb +1 -20
- data/app/views/puffer/base/index.js.erb +1 -0
- data/app/views/puffer/base/new.html.erb +1 -1
- data/app/views/puffer/base/show.html.erb +1 -22
- data/app/views/puffer/base/show.js.erb +1 -0
- data/app/views/puffer/base/update.js.erb +1 -0
- data/app/views/puffer/sessions/base/new.html.erb +11 -0
- data/app/views/puffer/tree_base/_record.html.erb +1 -1
- data/lib/puffer/component.rb +14 -47
- data/lib/puffer/controller/auth.rb +13 -9
- data/lib/puffer/controller/config.rb +18 -0
- data/lib/puffer/controller/mutate.rb +8 -8
- data/lib/puffer/engine.rb +5 -0
- data/lib/puffer/field.rb +5 -11
- data/lib/puffer/filters.rb +86 -56
- data/lib/puffer/helpers/component_helper.rb +24 -0
- data/lib/puffer/helpers/puffer_helper.rb +65 -0
- data/lib/puffer/helpers/puffer_tree_helper.rb +19 -0
- data/lib/puffer/orm_adapter/active_record.rb +40 -11
- data/lib/puffer/orm_adapter/base.rb +9 -0
- data/lib/puffer/orm_adapter/mongoid.rb +32 -9
- data/lib/puffer/resource/node.rb +2 -2
- data/lib/puffer/resource/routing.rb +30 -16
- data/lib/puffer/resource.rb +20 -20
- data/lib/puffer/version.rb +3 -0
- data/lib/puffer.rb +26 -5
- data/puffer.gemspec +34 -296
- data/spec/app/components/base_component_spec.rb +1 -1
- data/spec/app/components/boolean_component_spec.rb +2 -0
- data/spec/app/components/date_time_component_spec.rb +1 -0
- data/spec/app/components/file_component_spec.rb +1 -0
- data/spec/app/components/hidden_component_spec.rb +1 -0
- data/spec/app/components/password_component_spec.rb +2 -0
- data/spec/app/components/select_component_spec.rb +1 -0
- data/spec/app/components/string_component_spec.rb +1 -0
- data/spec/app/components/text_component_spec.rb +1 -0
- data/spec/dummy/app/controllers/admin/news_controller.rb +2 -0
- data/spec/dummy/app/controllers/admin/profiles_controller.rb +1 -1
- data/spec/dummy/app/controllers/admin/users_controller.rb +2 -0
- data/spec/dummy/app/controllers/orms/active_record_orm_primals_controller.rb +8 -0
- data/spec/dummy/app/helpers/news_helper.rb +7 -0
- data/spec/dummy/app/models/active_record_orm/has_many_reference.rb +5 -0
- data/spec/dummy/app/models/active_record_orm/has_one_reference.rb +5 -0
- data/spec/dummy/app/models/active_record_orm/primal.rb +4 -0
- data/spec/dummy/config/environments/development.rb +1 -1
- data/spec/dummy/db/migrate/20111120144025_create_active_record_orm_has_one_references.rb +10 -0
- data/spec/dummy/db/migrate/20111122203304_create_active_record_orm_has_many_references.rb +10 -0
- data/spec/dummy/db/schema.rb +15 -1
- data/spec/helpers/puffer_helper_spec.rb +1 -1
- data/spec/lib/fields_spec.rb +0 -9
- data/spec/lib/filters_spec.rb +4 -8
- data/spec/lib/orm_adapter/base_shared.rb +22 -0
- data/spec/spec_helper.rb +1 -1
- metadata +89 -60
- data/app/components/string/form.html.erb +0 -5
- data/app/helpers/puffer_helper.rb +0 -51
- data/app/helpers/puffer_tree_helper.rb +0 -15
- data/app/views/puffer/sessions_base/new.html.erb +0 -11
- data/lib/puffer/extensions/form.rb +0 -16
data/lib/puffer/filters.rb
CHANGED
|
@@ -1,40 +1,103 @@
|
|
|
1
1
|
module Puffer
|
|
2
2
|
class Filters
|
|
3
|
+
class Diapason < Struct.new(:from, :till)
|
|
4
|
+
def empty?
|
|
5
|
+
from.blank? && till.blank?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def persisted?
|
|
9
|
+
false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_query(key)
|
|
13
|
+
{:from => from, :till => till}.to_query(key)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
3
17
|
include ActiveModel::Conversion
|
|
4
18
|
extend ActiveModel::Naming
|
|
5
19
|
extend ActiveModel::Translation
|
|
6
20
|
include ActiveModel::AttributeMethods
|
|
7
21
|
|
|
8
|
-
delegate :model_name, :to => 'self.class'
|
|
22
|
+
delegate :model_name, :special_attributes, :to => 'self.class'
|
|
9
23
|
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
def self.special_attributes
|
|
25
|
+
%w(puffer_search puffer_order)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
special_attributes.each do |attribute|
|
|
29
|
+
define_method attribute do
|
|
30
|
+
read_attribute attribute
|
|
31
|
+
end
|
|
32
|
+
define_method "#{attribute}=" do |value|
|
|
33
|
+
write_attribute attribute, value
|
|
14
34
|
end
|
|
15
35
|
end
|
|
16
36
|
|
|
37
|
+
attr_reader :fieldset
|
|
38
|
+
|
|
39
|
+
def initialize fieldset, attributes = {}
|
|
40
|
+
@attributes = {}
|
|
41
|
+
@fieldset = fieldset
|
|
42
|
+
generate_attribute_methods
|
|
43
|
+
|
|
44
|
+
self.attributes = attributes
|
|
45
|
+
end
|
|
46
|
+
|
|
17
47
|
def read_attribute name
|
|
18
|
-
attributes[name]
|
|
48
|
+
@attributes[name.to_s]
|
|
19
49
|
end
|
|
20
50
|
|
|
21
51
|
def write_attribute name, value
|
|
22
|
-
|
|
52
|
+
if value.is_a? Hash
|
|
53
|
+
value.each do |key, subvalue|
|
|
54
|
+
@attributes[name.to_s][key] = subvalue if subvalue.present?
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
@attributes[name.to_s] = value
|
|
58
|
+
end if value.present?
|
|
23
59
|
end
|
|
24
60
|
|
|
25
|
-
def
|
|
26
|
-
|
|
61
|
+
def any?
|
|
62
|
+
attributes.values.any?
|
|
27
63
|
end
|
|
28
64
|
|
|
29
|
-
def
|
|
30
|
-
|
|
65
|
+
def attributes
|
|
66
|
+
(fieldset.map(&:field_name) + special_attributes).reduce(ActiveSupport::HashWithIndifferentAccess.new()) do |res, attribute|
|
|
67
|
+
res.merge attribute => send(attribute)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def attributes= attributes = {}
|
|
72
|
+
attributes.each do |(key, value)|
|
|
73
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def generate_attribute_methods
|
|
78
|
+
fieldset.each do |field|
|
|
79
|
+
define_singleton_method :"#{field}" do
|
|
80
|
+
read_attribute field
|
|
81
|
+
end
|
|
82
|
+
define_singleton_method :"#{field}=" do |value|
|
|
83
|
+
write_attribute field, value
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if %(date, time, datetime, date_time, timestamp).include?(field.type.to_s)
|
|
87
|
+
@attributes[field.to_s] = Puffer::Filters::Diapason.new
|
|
88
|
+
|
|
89
|
+
define_singleton_method :"#{field}_attributes=" do |value|
|
|
90
|
+
write_attribute field, value
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
31
94
|
end
|
|
32
95
|
|
|
33
96
|
def conditions
|
|
34
|
-
|
|
97
|
+
fieldset.map(&:field_name).reduce(ActiveSupport::HashWithIndifferentAccess.new()) do |res, attribute|
|
|
35
98
|
value = send(attribute)
|
|
36
99
|
|
|
37
|
-
unless value.
|
|
100
|
+
unless value.blank?
|
|
38
101
|
value = case value
|
|
39
102
|
when 'puffer_nil' then nil
|
|
40
103
|
when 'puffer_blank' then ''
|
|
@@ -52,54 +115,21 @@ module Puffer
|
|
|
52
115
|
end
|
|
53
116
|
|
|
54
117
|
def order
|
|
55
|
-
puffer_order
|
|
118
|
+
puffer_order.to_s.split(' ').map(&:to_sym)
|
|
56
119
|
end
|
|
57
120
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def controller_filters controller
|
|
68
|
-
scope = "#{controller}Filters".split('::')[0..-2].join('::').constantize rescue Kernel
|
|
69
|
-
name = "#{controller}Filters".demodulize
|
|
70
|
-
|
|
71
|
-
if scope.const_defined?(name)
|
|
72
|
-
scope.const_get(name)
|
|
73
|
-
else
|
|
74
|
-
attributes_from_controller = controller.index_fields.reduce({}) do |res, field|
|
|
75
|
-
res[field.field_name] = nil
|
|
76
|
-
res
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
attributes_from_controller.merge!('puffer_search' => nil, 'puffer_order' => nil)
|
|
80
|
-
|
|
81
|
-
klass = Class.new(self)
|
|
82
|
-
|
|
83
|
-
attributes_from_controller.keys.each do |name|
|
|
84
|
-
klass.send :define_method, name do
|
|
85
|
-
read_attribute name
|
|
86
|
-
end
|
|
87
|
-
klass.send :define_method, "#{name}=" do |value|
|
|
88
|
-
write_attribute name, value
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
klass.send :define_method, :attributes do
|
|
93
|
-
attributes_from_controller
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
scope.const_set(name, klass)
|
|
98
|
-
end
|
|
121
|
+
def query
|
|
122
|
+
(fieldset.map(&:field_name) + special_attributes).reduce(ActiveSupport::HashWithIndifferentAccess.new()) do |res, attribute|
|
|
123
|
+
value = send(attribute)
|
|
124
|
+
attribute = "#{attribute}_attributes" if respond_to?("#{attribute}_attributes=")
|
|
125
|
+
res[attribute] = value if value.present?
|
|
126
|
+
res
|
|
99
127
|
end
|
|
100
128
|
end
|
|
101
129
|
|
|
102
|
-
|
|
130
|
+
def persisted?
|
|
131
|
+
false
|
|
132
|
+
end
|
|
103
133
|
|
|
104
134
|
end
|
|
105
135
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Puffer
|
|
2
|
+
module Helpers
|
|
3
|
+
module ComponentHelper
|
|
4
|
+
|
|
5
|
+
def component_wrap name = :span, options = {}, &block
|
|
6
|
+
content_tag name, options.merge(:id => component_id), &block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def paginate(scope, options = {}, &block)
|
|
10
|
+
paginator = Kaminari::Helpers::Paginator.new parent_controller.view_context, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :param_name => Kaminari.config.param_name, :remote => false)
|
|
11
|
+
paginator.to_s
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def component_fields_for record, &block
|
|
15
|
+
if opts[:builder]
|
|
16
|
+
capture opts[:builder], &block
|
|
17
|
+
else
|
|
18
|
+
fields_for record, &block
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
module Puffer
|
|
4
|
+
module Helpers
|
|
5
|
+
module PufferHelper
|
|
6
|
+
|
|
7
|
+
def puffer_scopes_navigation
|
|
8
|
+
Rails.application.routes.resources_tree.map(&:scope).uniq.each do |scope|
|
|
9
|
+
yield scope, send("#{scope}_root_path"), scope == puffer_namespace
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def puffer_groups_navigation namespace = puffer_namespace
|
|
14
|
+
Rails.application.routes.resources_tree.roots.select {|node| node.scope == namespace}.uniq_by(&:group).each do |resource_node|
|
|
15
|
+
if resource_node.group
|
|
16
|
+
path = send("#{resource_node.scope}_#{resource_node.url_segment}_path")
|
|
17
|
+
current = resource.resource_node ? resource.root.resource_node.group == resource_node.group : false
|
|
18
|
+
|
|
19
|
+
yield resource_node.group, path, current
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def puffer_resources_navigation namespace = puffer_namespace, group = configuration.group
|
|
25
|
+
Rails.application.routes.resources_tree.roots.select {|node| node.scope == namespace && node.group == group}.each do |resource_node|
|
|
26
|
+
title = resource_node.controller.model.model_name.human
|
|
27
|
+
path = send("#{resource_node.scope}_#{resource_node.url_segment}_path")
|
|
28
|
+
current = resource.resource_node ? resource.root.resource_node == resource_node : false
|
|
29
|
+
|
|
30
|
+
yield title, path, current
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render_head field
|
|
35
|
+
head = []
|
|
36
|
+
if field.column
|
|
37
|
+
head.push link_to_unless(puffer_filters.puffer_order == field.to_s, "▼", resource.collection_path(:page => params[:page], Puffer::Filters.model_name.param_key => puffer_filters.query.merge(:puffer_order => field)))
|
|
38
|
+
head.push link_to_unless(puffer_filters.puffer_order == [field, :desc].join(' '), "▲", resource.collection_path(:page => params[:page], Puffer::Filters.model_name.param_key => puffer_filters.query.merge(:puffer_order => [field, :desc].join(' '))))
|
|
39
|
+
end
|
|
40
|
+
head.push field.human
|
|
41
|
+
head.join(' ').html_safe
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def render_field field, record
|
|
45
|
+
if field.options[:render]
|
|
46
|
+
case field.options[:render]
|
|
47
|
+
when Symbol then
|
|
48
|
+
res = send(field.options[:render], record)
|
|
49
|
+
when Proc then
|
|
50
|
+
res = field.options[:render].bind(self).call(record)
|
|
51
|
+
else ''
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
res = record.call_chain(field.to_s)
|
|
55
|
+
end
|
|
56
|
+
unless field.native?
|
|
57
|
+
url = edit_polymorphic_path [resource.scope, record.call_chain(field.path)] rescue nil
|
|
58
|
+
res = link_to res, url if url
|
|
59
|
+
end
|
|
60
|
+
res
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Puffer
|
|
2
|
+
module Helpers
|
|
3
|
+
module PufferTreeHelper
|
|
4
|
+
|
|
5
|
+
def puffer_tree hash, options = {}, &block
|
|
6
|
+
content_tag :ul, options do
|
|
7
|
+
puffer_tree_node hash, &block
|
|
8
|
+
end if hash.present?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def puffer_tree_node hash, &block
|
|
12
|
+
hash.keys.each do |node|
|
|
13
|
+
block.call node, render_tree(hash[node], &block)
|
|
14
|
+
end if hash.present?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -8,23 +8,40 @@ module Puffer
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def reflection name
|
|
12
|
+
reflection = klass.reflect_on_association(name.to_sym)
|
|
13
|
+
Reflection.new(
|
|
14
|
+
:klass => reflection.klass,
|
|
15
|
+
:macro => reflection.macro,
|
|
16
|
+
:through? => !!reflection.through_reflection
|
|
17
|
+
) if reflection
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
def filter scope, fields, options = {}
|
|
12
|
-
fields = fields.columns
|
|
13
21
|
conditions, order = extract_conditions_and_order!(options)
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
order = order.map { |name, dir| field = fields[name]; "#{query_order(field)} #{dir}" if field && field.column }.compact.join(', ')
|
|
24
|
+
|
|
25
|
+
conditions_fields = fields.select {|f| f.column && conditions.keys.include?(f.field_name)}.to_fieldset
|
|
26
|
+
search_fields = fields.select {|f| f.column && !conditions_fields.include?(f) && search_types.include?(f.column_type)}
|
|
27
|
+
all_fields = conditions_fields + search_fields
|
|
18
28
|
|
|
19
|
-
|
|
29
|
+
scope = scope.includes(includes(all_fields)).includes(reflection_includes(fields)).where(searches(search_fields, options[:search])).order(order)
|
|
30
|
+
|
|
31
|
+
conditions.each do |name, value|
|
|
20
32
|
field = conditions_fields[name]
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
scope = if value.is_a?(Puffer::Filters::Diapason)
|
|
34
|
+
case
|
|
35
|
+
when value.from.blank? then scope.where(["#{query_column(field)} < ?", value.till])
|
|
36
|
+
when value.till.blank? then scope.where(["#{query_column(field)} > ?", value.from])
|
|
37
|
+
else scope.where(name => Range.new(value.from, value.till))
|
|
38
|
+
end
|
|
39
|
+
else
|
|
40
|
+
scope.where(name => value)
|
|
41
|
+
end if field
|
|
23
42
|
end
|
|
24
43
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
scope.includes(includes(all_fields)).where(searches(search_fields, options[:search])).where(conditions).order(order)
|
|
44
|
+
scope
|
|
28
45
|
end
|
|
29
46
|
|
|
30
47
|
private
|
|
@@ -37,8 +54,20 @@ module Puffer
|
|
|
37
54
|
fields.map {|f| f.path unless f.native?}.compact.to_includes
|
|
38
55
|
end
|
|
39
56
|
|
|
57
|
+
def reflection_includes fields
|
|
58
|
+
fields.map {|f| f.field_name if f.reflection}.compact.to_includes
|
|
59
|
+
end
|
|
60
|
+
|
|
40
61
|
def searches fields, query
|
|
41
|
-
[fields.map {|f| "#{f
|
|
62
|
+
[fields.map {|f| "#{query_column(f)} like ?"}.compact.join(' or '), *(Array.wrap("%#{query}%") * fields.count)] if query.present?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def query_column field
|
|
66
|
+
"#{field.model.table_name}.#{field.name}" if field.column
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def query_order field
|
|
70
|
+
field.options[:order] || query_column(field)
|
|
42
71
|
end
|
|
43
72
|
|
|
44
73
|
end
|
|
@@ -8,22 +8,41 @@ module Puffer
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def reflection name
|
|
12
|
+
reflection = klass.reflect_on_association(name.to_sym)
|
|
13
|
+
Reflection.new(
|
|
14
|
+
:klass => reflection.klass,
|
|
15
|
+
:macro => reflection.macro,
|
|
16
|
+
:through? => false
|
|
17
|
+
) if reflection
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
def filter scope, fields, options = {}
|
|
12
|
-
fields = fields.columns
|
|
13
21
|
conditions, order = extract_conditions_and_order!(options)
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
order = order.map { |o| f = fields[o.first]; [query_order(f), o.last] if f && f.column }.compact
|
|
24
|
+
|
|
25
|
+
conditions_fields = fields.select {|f| f.column && conditions.keys.include?(f.field_name)}.to_fieldset
|
|
26
|
+
search_fields = fields.select {|f| f.column && !conditions_fields.include?(f) && search_types.include?(f.column_type)}
|
|
17
27
|
all_fields = conditions_fields + search_fields
|
|
28
|
+
|
|
29
|
+
scope = scope.any_of(searches(search_fields, options[:search])) if options[:search].present?
|
|
30
|
+
scope = scope.order_by(order)
|
|
18
31
|
|
|
19
|
-
conditions
|
|
32
|
+
conditions.each do |name, value|
|
|
20
33
|
field = conditions_fields[name]
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
scope = if value.is_a?(Puffer::Filters::Diapason)
|
|
35
|
+
case
|
|
36
|
+
when value.from.blank? then scope.where(name.to_sym.lt => value.till)
|
|
37
|
+
when value.till.blank? then scope.where(name.to_sym.gt => value.from)
|
|
38
|
+
else scope.where(name => Range.new(value.from, value.till))
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
scope.where(name => value)
|
|
42
|
+
end if field
|
|
23
43
|
end
|
|
24
44
|
|
|
25
|
-
scope
|
|
26
|
-
scope.where(conditions).order(order)
|
|
45
|
+
scope
|
|
27
46
|
end
|
|
28
47
|
|
|
29
48
|
private
|
|
@@ -34,7 +53,11 @@ module Puffer
|
|
|
34
53
|
|
|
35
54
|
def searches fields, query
|
|
36
55
|
regexp = /#{Regexp.escape(query)}/i
|
|
37
|
-
fields.map {|field| {field.
|
|
56
|
+
fields.map {|field| {field.to_s => regexp}}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def query_order field
|
|
60
|
+
field.options[:order] || field.name
|
|
38
61
|
end
|
|
39
62
|
|
|
40
63
|
end
|
data/lib/puffer/resource/node.rb
CHANGED
|
@@ -5,38 +5,52 @@ module Puffer
|
|
|
5
5
|
include ActionController::UrlFor
|
|
6
6
|
include Rails.application.routes.url_helpers
|
|
7
7
|
|
|
8
|
-
def
|
|
9
|
-
|
|
8
|
+
def collection_method routing_type, options = {}
|
|
9
|
+
send url_method_name(routing_type, url_segment, options.delete(:action)), *url_arguments, options
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
def member_method routing_type, *args
|
|
13
|
+
options = args.extract_options!
|
|
14
|
+
send url_method_name(routing_type, singular, options.delete(:action)), *url_arguments(use_resource_id(args.first) || member_id), options
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def
|
|
18
|
-
|
|
17
|
+
def new_method routing_type, options = {}
|
|
18
|
+
send url_method_name(routing_type, singular, :new), *url_arguments, options
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
def edit_method routing_type, *args
|
|
22
|
+
options = args.extract_options!
|
|
23
|
+
member_method routing_type, *args, options.merge(:action => :edit)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
-
resource = Array.wrap(args)
|
|
29
|
-
return [scope] + ancestors.map(&:route_member) + resource, options
|
|
26
|
+
def url_method_name routing_type, current, action = nil
|
|
27
|
+
[action, scope, *ancestors.map(&:singular), current, routing_type].compact.join('_')
|
|
30
28
|
end
|
|
31
29
|
|
|
32
|
-
def
|
|
33
|
-
|
|
30
|
+
def url_arguments current = nil
|
|
31
|
+
ancestors.map(&:member_id).push(current).compact
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
%w(url path).each do |routing_type|
|
|
35
|
+
%w(collection member new edit).each do |method|
|
|
36
|
+
define_method "#{method}_#{routing_type}" do |*args|
|
|
37
|
+
send "#{method}_method", routing_type, *args
|
|
38
|
+
end
|
|
39
|
+
end
|
|
34
40
|
end
|
|
35
41
|
|
|
36
42
|
def default_url_options *args
|
|
37
43
|
Puffer::Base.default_url_options(*args)
|
|
38
44
|
end
|
|
39
45
|
|
|
46
|
+
def use_resource_id(resource)
|
|
47
|
+
if resource and resource.respond_to?(:id)
|
|
48
|
+
resource.id
|
|
49
|
+
else
|
|
50
|
+
resource
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
40
54
|
end
|
|
41
55
|
end
|
|
42
56
|
end
|
data/lib/puffer/resource.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Puffer
|
|
|
11
11
|
include Routing
|
|
12
12
|
|
|
13
13
|
attr_reader :resource_node, :scope, :params, :controller_instance
|
|
14
|
-
delegate :controller, :name, :plural?, :to => :resource_node, :allow_nil => true
|
|
14
|
+
delegate :controller, :name, :plural?, :singular, :plural, :url_segment, :to => :resource_node, :allow_nil => true
|
|
15
15
|
delegate :model, :to => :controller, :allow_nil => true
|
|
16
16
|
delegate :env, :request, :to => :controller_instance, :allow_nil => true
|
|
17
17
|
|
|
@@ -51,14 +51,10 @@ module Puffer
|
|
|
51
51
|
resource_node.ancestors[0..-2].each do |ancestor|
|
|
52
52
|
key = ancestor.to_s.singularize.foreign_key
|
|
53
53
|
parent_params[key] = params[key] if params[key]
|
|
54
|
-
key = key.gsub(/_id$/, '_member')
|
|
55
|
-
parent_params[key] = params[key] if params[key]
|
|
56
54
|
end
|
|
57
55
|
|
|
58
56
|
key = resource_node.parent.to_s.singularize.foreign_key
|
|
59
57
|
parent_params[:id] = params[key] if params[key]
|
|
60
|
-
key = key.gsub(/_id$/, '_member')
|
|
61
|
-
parent_params[:member] = params[key] if params[key]
|
|
62
58
|
|
|
63
59
|
self.class.new parent_params, controller_instance
|
|
64
60
|
end
|
|
@@ -72,14 +68,10 @@ module Puffer
|
|
|
72
68
|
resource_node.ancestors.each do |ancestor|
|
|
73
69
|
key = ancestor.to_s.singularize.foreign_key
|
|
74
70
|
child_params[key] = params[key] if params[key]
|
|
75
|
-
key = key.gsub(/_id$/, '_member')
|
|
76
|
-
child_params[key] = params[key] if params[key]
|
|
77
71
|
end
|
|
78
72
|
|
|
79
73
|
key = resource_node.to_s.singularize.foreign_key
|
|
80
74
|
child_params[key] = params[:id] if params[:id]
|
|
81
|
-
key = key.gsub(/_id$/, '_member')
|
|
82
|
-
child_params[key] = params[:member] if params[:member]
|
|
83
75
|
|
|
84
76
|
self.class.new child_params, controller_instance
|
|
85
77
|
end
|
|
@@ -92,31 +84,40 @@ module Puffer
|
|
|
92
84
|
end
|
|
93
85
|
end
|
|
94
86
|
|
|
87
|
+
def member_id
|
|
88
|
+
params[:id]
|
|
89
|
+
end
|
|
90
|
+
|
|
95
91
|
def collection_scope
|
|
96
92
|
parent ? parent.member.send(name) : model
|
|
97
93
|
end
|
|
98
94
|
|
|
95
|
+
def adapter
|
|
96
|
+
model.to_adapter
|
|
97
|
+
end
|
|
98
|
+
|
|
99
99
|
def collection
|
|
100
|
-
|
|
100
|
+
scope = collection_scope
|
|
101
|
+
scope = scope.send controller.configuration.scope if controller.configuration.scope
|
|
102
|
+
adapter.filter scope, controller.filter_fields,
|
|
101
103
|
:conditions => controller_instance.puffer_filters.conditions,
|
|
102
104
|
:search => controller_instance.puffer_filters.search,
|
|
103
105
|
:order => controller_instance.puffer_filters.order
|
|
104
106
|
end
|
|
105
107
|
|
|
106
108
|
def member
|
|
107
|
-
return params[:member] if params[:member]
|
|
108
109
|
if parent
|
|
109
110
|
if plural?
|
|
110
|
-
parent.member.send(name).find
|
|
111
|
+
parent.member.send(name).find member_id if member_id
|
|
111
112
|
else
|
|
112
113
|
parent.member.send(name)
|
|
113
114
|
end
|
|
114
115
|
else
|
|
115
|
-
|
|
116
|
+
adapter.get member_id if member_id
|
|
116
117
|
end
|
|
117
118
|
end
|
|
118
119
|
|
|
119
|
-
def new_member
|
|
120
|
+
def new_member attributes = attributes
|
|
120
121
|
if parent
|
|
121
122
|
if plural?
|
|
122
123
|
parent.member.send(name).new attributes
|
|
@@ -129,15 +130,14 @@ module Puffer
|
|
|
129
130
|
end
|
|
130
131
|
|
|
131
132
|
def attributes
|
|
132
|
-
params[
|
|
133
|
+
params[attributes_key] || {}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def attributes_key
|
|
137
|
+
model.model_name.param_key
|
|
133
138
|
end
|
|
134
139
|
|
|
135
140
|
def method_missing method, *args, &block
|
|
136
|
-
method = method.to_s
|
|
137
|
-
if method.match(/path$/) && respond_to?(method.gsub(/path$/, 'url'))
|
|
138
|
-
options = args.extract_options!
|
|
139
|
-
return send method.gsub(/path$/, 'url'), *(args << options.merge(:routing_type => :path))
|
|
140
|
-
end
|
|
141
141
|
model.send method, *args, &block if model.respond_to? method
|
|
142
142
|
end
|
|
143
143
|
|