puffer 0.0.32 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +1 -26
  3. data/Gemfile.lock +66 -64
  4. data/README.md +34 -23
  5. data/Rakefile +1 -11
  6. data/VERSION +1 -1
  7. data/app/assets/javascripts/puffer/application.js +6 -1
  8. data/app/assets/javascripts/puffer/associations.js +18 -0
  9. data/app/assets/javascripts/puffer/puffer.js +7 -0
  10. data/app/assets/javascripts/puffer/right-calendar-src.js +19 -3
  11. data/app/assets/javascripts/puffer/right-dnd-src.js +591 -0
  12. data/app/assets/javascripts/puffer/right-in-edit-src.js +373 -0
  13. data/app/assets/javascripts/puffer/right-keys-src.js +87 -0
  14. data/app/assets/javascripts/puffer/{paginator.js → right-paginator-src.js} +0 -0
  15. data/app/assets/javascripts/puffer/right-slider-src.js +29 -32
  16. data/app/assets/javascripts/puffer/right-sortable-src.js +430 -0
  17. data/app/assets/javascripts/puffer/right-src.js +358 -99
  18. data/app/assets/stylesheets/puffer/puffer.css +29 -4
  19. data/app/components/base/form.html.erb +8 -14
  20. data/app/components/base_component.rb +1 -1
  21. data/app/components/boolean/form.html.erb +5 -3
  22. data/app/components/boolean/index.html.erb +6 -2
  23. data/app/components/boolean_component.rb +2 -2
  24. data/app/components/date_time/filter.html.erb +9 -0
  25. data/app/components/date_time/form.html.erb +8 -4
  26. data/app/components/date_time_component.rb +21 -5
  27. data/app/components/file/form.html.erb +8 -4
  28. data/app/components/hidden/form.html.erb +3 -1
  29. data/app/components/nested_attributes_many/form.html.erb +47 -0
  30. data/app/components/nested_attributes_many_component.rb +7 -0
  31. data/app/components/nested_attributes_one/form.html.erb +48 -0
  32. data/app/components/nested_attributes_one_component.rb +7 -0
  33. data/app/components/password/form.html.erb +8 -4
  34. data/app/components/password_component.rb +1 -1
  35. data/app/components/references_many/index.html.erb +1 -1
  36. data/app/components/references_one/choose.html.erb +1 -1
  37. data/app/components/references_one/form.html.erb +10 -9
  38. data/app/components/references_one_component.rb +0 -1
  39. data/app/components/render_component.rb +13 -0
  40. data/app/components/select/filter.html.erb +4 -2
  41. data/app/components/select/form.html.erb +8 -4
  42. data/app/components/text/form.html.erb +8 -4
  43. data/app/controllers/admin/sessions_controller.rb +1 -21
  44. data/app/controllers/puffer/base.rb +10 -3
  45. data/app/controllers/puffer/dashboard_base.rb +7 -1
  46. data/app/controllers/puffer/{sessions_base.rb → sessions/base.rb} +10 -7
  47. data/app/controllers/puffer/sessions/clearance.rb +29 -0
  48. data/app/controllers/puffer/{sessions_devise_base.rb → sessions/devise.rb} +1 -1
  49. data/app/controllers/puffer/sessions/simple.rb +28 -0
  50. data/app/controllers/puffer/tree_base.rb +1 -1
  51. data/app/models/puffer_user.rb +3 -0
  52. data/app/views/layouts/puffer.html.erb +3 -3
  53. data/app/views/puffer/base/_edit.html.erb +15 -0
  54. data/app/views/puffer/base/_index.html.erb +26 -0
  55. data/app/views/puffer/base/_show.html.erb +13 -0
  56. data/app/views/puffer/base/_table.html.erb +1 -1
  57. data/app/views/puffer/base/edit.html.erb +1 -15
  58. data/app/views/puffer/base/edit.js.erb +1 -0
  59. data/app/views/puffer/base/index.html.erb +1 -20
  60. data/app/views/puffer/base/index.js.erb +1 -0
  61. data/app/views/puffer/base/new.html.erb +1 -1
  62. data/app/views/puffer/base/show.html.erb +1 -22
  63. data/app/views/puffer/base/show.js.erb +1 -0
  64. data/app/views/puffer/base/update.js.erb +1 -0
  65. data/app/views/puffer/sessions/base/new.html.erb +11 -0
  66. data/app/views/puffer/tree_base/_record.html.erb +1 -1
  67. data/lib/puffer/component.rb +14 -47
  68. data/lib/puffer/controller/auth.rb +13 -9
  69. data/lib/puffer/controller/config.rb +18 -0
  70. data/lib/puffer/controller/mutate.rb +8 -8
  71. data/lib/puffer/engine.rb +5 -0
  72. data/lib/puffer/field.rb +5 -11
  73. data/lib/puffer/filters.rb +86 -56
  74. data/lib/puffer/helpers/component_helper.rb +24 -0
  75. data/lib/puffer/helpers/puffer_helper.rb +65 -0
  76. data/lib/puffer/helpers/puffer_tree_helper.rb +19 -0
  77. data/lib/puffer/orm_adapter/active_record.rb +40 -11
  78. data/lib/puffer/orm_adapter/base.rb +9 -0
  79. data/lib/puffer/orm_adapter/mongoid.rb +32 -9
  80. data/lib/puffer/resource/node.rb +2 -2
  81. data/lib/puffer/resource/routing.rb +30 -16
  82. data/lib/puffer/resource.rb +20 -20
  83. data/lib/puffer/version.rb +3 -0
  84. data/lib/puffer.rb +26 -5
  85. data/puffer.gemspec +34 -296
  86. data/spec/app/components/base_component_spec.rb +1 -1
  87. data/spec/app/components/boolean_component_spec.rb +2 -0
  88. data/spec/app/components/date_time_component_spec.rb +1 -0
  89. data/spec/app/components/file_component_spec.rb +1 -0
  90. data/spec/app/components/hidden_component_spec.rb +1 -0
  91. data/spec/app/components/password_component_spec.rb +2 -0
  92. data/spec/app/components/select_component_spec.rb +1 -0
  93. data/spec/app/components/string_component_spec.rb +1 -0
  94. data/spec/app/components/text_component_spec.rb +1 -0
  95. data/spec/dummy/app/controllers/admin/news_controller.rb +2 -0
  96. data/spec/dummy/app/controllers/admin/profiles_controller.rb +1 -1
  97. data/spec/dummy/app/controllers/admin/users_controller.rb +2 -0
  98. data/spec/dummy/app/controllers/orms/active_record_orm_primals_controller.rb +8 -0
  99. data/spec/dummy/app/helpers/news_helper.rb +7 -0
  100. data/spec/dummy/app/models/active_record_orm/has_many_reference.rb +5 -0
  101. data/spec/dummy/app/models/active_record_orm/has_one_reference.rb +5 -0
  102. data/spec/dummy/app/models/active_record_orm/primal.rb +4 -0
  103. data/spec/dummy/config/environments/development.rb +1 -1
  104. data/spec/dummy/db/migrate/20111120144025_create_active_record_orm_has_one_references.rb +10 -0
  105. data/spec/dummy/db/migrate/20111122203304_create_active_record_orm_has_many_references.rb +10 -0
  106. data/spec/dummy/db/schema.rb +15 -1
  107. data/spec/helpers/puffer_helper_spec.rb +1 -1
  108. data/spec/lib/fields_spec.rb +0 -9
  109. data/spec/lib/filters_spec.rb +4 -8
  110. data/spec/lib/orm_adapter/base_shared.rb +22 -0
  111. data/spec/spec_helper.rb +1 -1
  112. metadata +89 -60
  113. data/app/components/string/form.html.erb +0 -5
  114. data/app/helpers/puffer_helper.rb +0 -51
  115. data/app/helpers/puffer_tree_helper.rb +0 -15
  116. data/app/views/puffer/sessions_base/new.html.erb +0 -11
  117. data/lib/puffer/extensions/form.rb +0 -16
@@ -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 initialize attributes = {}
11
- attributes ||= {}
12
- attributes.each do |(key, value)|
13
- send("#{key}=", value) if respond_to?("#{key}=")
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
- attributes[name] = value.presence if attributes.key?(name)
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 persisted?
26
- false
61
+ def any?
62
+ attributes.values.any?
27
63
  end
28
64
 
29
- def any?
30
- attributes.keys.any? { |attribute| !send(attribute).nil? }
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
- attributes.except('puffer_search', 'puffer_order').keys.reduce({}) do |res, attribute|
97
+ fieldset.map(&:field_name).reduce(ActiveSupport::HashWithIndifferentAccess.new()) do |res, attribute|
35
98
  value = send(attribute)
36
99
 
37
- unless value.nil?
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
- module ClassMethods
59
- def model_name
60
- @model_name ||= begin
61
- name = super
62
- name.instance_variable_set :@param_key, 'filters'
63
- name
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
- extend ClassMethods
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
- conditions_fields = fields.select {|f| conditions.keys.include?(f.field_name)}.to_fieldset
16
- search_fields = fields.select {|f| !conditions_fields.include?(f) && search_types.include?(f.column_type)}
17
- all_fields = conditions_fields + search_fields
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
- conditions = conditions.reduce({}) do |res, (name, value)|
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
- res[field.query_column] = value if field
22
- res
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
- order = order.map {|field, direction| "#{field} #{direction}"}.join(', ')
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.query_column} like ?"}.compact.join(' or '), *(Array.wrap("%#{query}%") * fields.count)] if query.present?
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
@@ -11,6 +11,15 @@ module Puffer
11
11
  end
12
12
 
13
13
  end
14
+
15
+ class Reflection < ActiveSupport::OrderedOptions
16
+
17
+ def initialize hash
18
+ super
19
+ hash.each { |(key, value)| self[key] = value }
20
+ end
21
+
22
+ end
14
23
  end
15
24
  end
16
25
 
@@ -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
- conditions_fields = fields.select {|f| conditions.keys.include?(f.field_name)}.to_fieldset
16
- search_fields = fields.select {|f| !conditions_fields.include?(f) && search_types.include?(f.column_type)}
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 = conditions.reduce({}) do |res, (name, value)|
32
+ conditions.each do |name, value|
20
33
  field = conditions_fields[name]
21
- res[field.name] = value if field
22
- res
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 = scope.any_of(searches(search_fields, options[:search])) if options[:search].present?
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.name => regexp}}
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
@@ -59,8 +59,8 @@ module Puffer
59
59
  ancestors
60
60
  end
61
61
 
62
- def url_string
63
- [scope, name, (:index if singular == plural)].compact.map(&:to_s).join('_')
62
+ def url_segment
63
+ [name, (:index if singular == plural)].compact.map(&:to_s).join('_')
64
64
  end
65
65
 
66
66
  def to_struct
@@ -5,38 +5,52 @@ module Puffer
5
5
  include ActionController::UrlFor
6
6
  include Rails.application.routes.url_helpers
7
7
 
8
- def collection_url *args
9
- polymorphic_url *route_args(route_member(model), *args)
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 member_url *args
13
- suggest = args.shift if args.first.respond_to? :to_key
14
- polymorphic_url *route_args(route_member(suggest), *args)
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 new_url *args
18
- new_polymorphic_url *route_args(name.to_s.singularize, *args)
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 edit_url *args
22
- suggest = args.shift if args.first.respond_to? :to_key
23
- edit_polymorphic_url *route_args(route_member(suggest), *args)
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 route_args *args
27
- options = args.extract_options!
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 route_member suggest = nil
33
- plural? ? (suggest || member) : name.to_s.singularize
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
@@ -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
- model.to_adapter.filter collection_scope, controller.index_fields,
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 params[:id] if params[:id]
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
- model.find params[:id] if params[:id]
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[name.to_s.singularize]
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
 
@@ -0,0 +1,3 @@
1
+ module Puffer
2
+ VERSION = "0.1.0"
3
+ end