spyro 0.0.2

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.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/OLDjavascripts/application.js +25 -0
  6. data/app/assets/OLDjavascripts/components.es6 +10 -0
  7. data/app/assets/OLDjavascripts/components/base/base.es6 +197 -0
  8. data/app/assets/OLDjavascripts/components/base/collection.es6 +199 -0
  9. data/app/assets/OLDjavascripts/components/base/element.es6 +134 -0
  10. data/app/assets/OLDjavascripts/components/base/field.es6 +26 -0
  11. data/app/assets/OLDjavascripts/components/base/inputs/text.es6 +21 -0
  12. data/app/assets/OLDjavascripts/components/base/pagination.es6 +23 -0
  13. data/app/assets/OLDjavascripts/vendor/lodash.js +121 -0
  14. data/app/assets/OLDjavascripts/vendor/moment-twitter.js +86 -0
  15. data/app/assets/OLDjavascripts/vendor/moment.js +80 -0
  16. data/app/assets/OLDjavascripts/vendor/pluralize.js +433 -0
  17. data/app/views/base/_associations.html.haml +11 -0
  18. data/app/views/base/_custom.html.haml +0 -0
  19. data/app/views/base/_details.html.haml +3 -0
  20. data/app/views/base/_edit_header.html.haml +3 -0
  21. data/app/views/base/_fields.html.haml +11 -0
  22. data/app/views/base/_form.html.haml +6 -0
  23. data/app/views/base/_index_header.html.haml +4 -0
  24. data/app/views/base/_new_header.html.haml +3 -0
  25. data/app/views/base/_other_form_fields.html.haml +0 -0
  26. data/app/views/base/_show_header.html.haml +9 -0
  27. data/app/views/base/_upload_fields.html.haml +5 -0
  28. data/app/views/base/copy.html.haml +10 -0
  29. data/app/views/base/edit.html.haml +4 -0
  30. data/app/views/base/index.csv.haml +8 -0
  31. data/app/views/base/index.html.haml +7 -0
  32. data/app/views/base/index.js.haml +2 -0
  33. data/app/views/base/index.xls.ruby +12 -0
  34. data/app/views/base/mailer.html.haml +46 -0
  35. data/app/views/base/new.html.haml +4 -0
  36. data/app/views/base/notify.html.haml +11 -0
  37. data/app/views/base/show.html.haml +8 -0
  38. data/app/views/base/stats.html.haml +36 -0
  39. data/app/views/base/trombi.html.haml +1 -0
  40. data/app/views/base/upload.html.haml +24 -0
  41. data/config/initializers/assets.rb +1 -0
  42. data/config/routes.rb +2 -0
  43. data/lib/spyro.rb +24 -0
  44. data/lib/spyro/active_record_add_on.rb +38 -0
  45. data/lib/spyro/application_controller_add_on.rb +24 -0
  46. data/lib/spyro/collections/outputs/admin_table.rb +28 -0
  47. data/lib/spyro/collections/outputs/bar_graph_table.rb +46 -0
  48. data/lib/spyro/collections/outputs/base.rb +23 -0
  49. data/lib/spyro/collections/outputs/csv.rb +34 -0
  50. data/lib/spyro/collections/outputs/fields.rb +118 -0
  51. data/lib/spyro/collections/outputs/flatui_table.rb +40 -0
  52. data/lib/spyro/collections/outputs/inplace_table.rb +29 -0
  53. data/lib/spyro/collections/outputs/map.rb +22 -0
  54. data/lib/spyro/collections/outputs/table.rb +126 -0
  55. data/lib/spyro/collections/outputs/xlsx.rb +39 -0
  56. data/lib/spyro/collections/parsers/active_ldap_relation.rb +22 -0
  57. data/lib/spyro/collections/parsers/active_record_relation.rb +138 -0
  58. data/lib/spyro/collections/parsers/array.rb +38 -0
  59. data/lib/spyro/collections/parsers/base.rb +60 -0
  60. data/lib/spyro/collections/parsers/kaminari_array.rb +38 -0
  61. data/lib/spyro/collections/parsers/model.rb +31 -0
  62. data/lib/spyro/controllers/strong_parameted.rb +33 -0
  63. data/lib/spyro/engine.rb +6 -0
  64. data/lib/spyro/filters_controller_add_on.rb +161 -0
  65. data/lib/spyro/helpers/action_view_extension.rb +726 -0
  66. data/lib/spyro/namespace_template_inheritance.rb +30 -0
  67. data/lib/spyro/usefull_attributes.rb +14 -0
  68. data/lib/spyro/version.rb +3 -0
  69. data/lib/tasks/spyro_tasks.rake +4 -0
  70. data/test/dummy/README.rdoc +28 -0
  71. data/test/dummy/Rakefile +6 -0
  72. data/test/dummy/app/assets/javascripts/application.js +13 -0
  73. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  74. data/test/dummy/app/controllers/application_controller.rb +5 -0
  75. data/test/dummy/app/helpers/application_helper.rb +2 -0
  76. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  77. data/test/dummy/bin/bundle +3 -0
  78. data/test/dummy/bin/rails +4 -0
  79. data/test/dummy/bin/rake +4 -0
  80. data/test/dummy/bin/setup +29 -0
  81. data/test/dummy/config.ru +4 -0
  82. data/test/dummy/config/application.rb +26 -0
  83. data/test/dummy/config/boot.rb +5 -0
  84. data/test/dummy/config/database.yml +25 -0
  85. data/test/dummy/config/environment.rb +5 -0
  86. data/test/dummy/config/environments/development.rb +41 -0
  87. data/test/dummy/config/environments/production.rb +79 -0
  88. data/test/dummy/config/environments/test.rb +42 -0
  89. data/test/dummy/config/initializers/assets.rb +11 -0
  90. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  91. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  92. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  93. data/test/dummy/config/initializers/inflections.rb +16 -0
  94. data/test/dummy/config/initializers/mime_types.rb +4 -0
  95. data/test/dummy/config/initializers/session_store.rb +3 -0
  96. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  97. data/test/dummy/config/locales/en.yml +23 -0
  98. data/test/dummy/config/routes.rb +4 -0
  99. data/test/dummy/config/secrets.yml +22 -0
  100. data/test/dummy/public/404.html +67 -0
  101. data/test/dummy/public/422.html +67 -0
  102. data/test/dummy/public/500.html +66 -0
  103. data/test/dummy/public/favicon.ico +0 -0
  104. data/test/integration/navigation_test.rb +8 -0
  105. data/test/spyro_test.rb +7 -0
  106. data/test/test_helper.rb +21 -0
  107. metadata +256 -0
@@ -0,0 +1,34 @@
1
+ require_relative "base"
2
+ require "csv"
3
+
4
+
5
+ module Spyro
6
+ module ActionViewExtension
7
+
8
+ module CollectionForHelper
9
+ module Output
10
+ class CSV < Output::Base
11
+
12
+ def render_header csv
13
+ return unless @unicollection.meta[:data]
14
+ csv << @unicollection.meta[:data]
15
+ end
16
+
17
+ def render_body csv
18
+ @unicollection.rows.each do |row|
19
+ csv << row[:data].map(&:value)
20
+ end
21
+ end
22
+
23
+ def render
24
+ return "" if @unicollection.rows.empty?
25
+ ::CSV.generate({}) do |csv|
26
+ render_header csv
27
+ render_body csv
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,118 @@
1
+
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ module Fields
9
+ # Key => [class => object class ; symbol => db_type, string for pattern matching]
10
+ @@fields = { [ActiveSupport::TimeWithZone, ""] => {:method => :datetime},
11
+ [Object, /_prct$/] => {:method => :prct},
12
+ [Float, ""] => {:method => :float},
13
+ [:boolean, ""] => {:method => :boolean},
14
+ [:text, /_html$/] => {:method => :html},
15
+ [:text, /code$/] => {:method => :html},
16
+ [:text, ""] => {:method => :text},
17
+ [String, /_url$/] => {:method => :url},
18
+ #[String, /_email$/] => {:method => :email},
19
+ [String, ""] => {:method => :string}, }
20
+
21
+ @@fields[[CarrierWave::Uploader::Base, /_image$/]] = {:method => :cw_image} if defined? CarrierWave and defined? CarrierWave::Uploader and defined? CarrierWave::Uploader::Base
22
+ @@fields[[CarrierWave::Uploader::Base, ""]] = {:method => :cw_file} if defined? CarrierWave and defined? CarrierWave::Uploader and defined? CarrierWave::Uploader::Base
23
+ @@fields[[ClassyEnum::Base, ""]] = {:method => :classy_enum} if defined? ClassyEnum
24
+
25
+ @@fields[[Object, ""]] = {:method => :default}
26
+
27
+ delegate :l, :link_to, :mail_to, :cw_image_tag, :truncate, :strip_tags, :progress, to: :@h
28
+
29
+ def format_default value, options
30
+ value.to_s
31
+ end
32
+
33
+ def format_classy_enum value, options
34
+ value.blank? ? "" : value.text
35
+ end
36
+
37
+ def format_datetime value, options
38
+ l(value, :format => options[:format] || :datetime)
39
+ end
40
+
41
+ def format_cw_image value, options
42
+ cw_image_tag value, options[:version]
43
+ end
44
+
45
+ def format_cw_file value, options
46
+ link_to value.file.filename, value.url unless value.file.nil?
47
+ end
48
+
49
+ def format_email value, options
50
+ mail_to value
51
+ end
52
+
53
+ def format_boolean value, options
54
+ value ? "Yes" : "No"
55
+ end
56
+
57
+ def format_period values, options
58
+ begin_at, end_at, current = *values
59
+ current ||= Time.zone.now
60
+
61
+ total, actual = (end_at.to_i - begin_at.to_i), (current.to_i - begin_at.to_i)
62
+ current_percentage = [0, 100, (actual * 100) / total].sort.second
63
+ <<EOP
64
+ <div class="col-md-12">
65
+ <span class="date-before col-md-6 pull-left">#{l(begin_at, :format => options[:format] || :datetime)}</span>
66
+ <span class="date-after col-md-6 pull-right">#{l(end_at, :format => options[:format] || :datetime)}</span>
67
+ <div class="col-md-10 col-md-offset-1">
68
+ #{progress current_percentage}
69
+ </div>
70
+ </div>
71
+ EOP
72
+
73
+ end
74
+
75
+ def format_progress values, options
76
+ actual, total = *values
77
+ current_percentage = [0, 100, (actual * 100) / total].sort.second rescue 0
78
+ <<EOP
79
+ <div class="col-md-12">
80
+ <div class="col-md-12 percentage-label">
81
+ #{actual} / #{total}
82
+ </div>
83
+ <div class="col-md-10 col-md-offset-1">
84
+ #{progress current_percentage}
85
+ </div>
86
+ </div>
87
+ EOP
88
+
89
+ end
90
+
91
+ def format_prct value, options
92
+ value ? ("%.2f%%" % value) : "N/A"
93
+ end
94
+
95
+ def format_float value, options
96
+ value ? ("%.2f" % value) : "N/A"
97
+ end
98
+
99
+ def format_url value, options
100
+ link_to value, (value.start_with?('http') ? value : ('http://' + value))
101
+ end
102
+
103
+ def format_html value, options
104
+ "<span class='has-popover' data-html='true' data-content='#{@h.send(:h, value.to_s)}'>#{@h.truncate(@h.strip_tags(HTMLEntities.new.decode(value.to_s)), :length => 40, :separator => ' ')}</span>".html_safe
105
+ end
106
+
107
+ def format_text value, options
108
+ "<span class='has-popover' data-content='#{@h.send(:h, value.to_s)}'>#{@h.truncate(value.to_s, :length => 40, :separator => ' ')}</span>".html_safe
109
+ end
110
+
111
+ def format_string value, options
112
+ value.to_s
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "table"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+ module CollectionForHelper
6
+ module Output
7
+ class FlatuiTable < Table
8
+ delegate :link_to, :button, :button_success, :button_danger, :button_info, to: :@h
9
+
10
+ def initialize unicollection, helper, parser_class
11
+ super
12
+ end
13
+
14
+ def render_cell_buttons row
15
+ row[:meta][:actions] = {} if row[:meta][:actions].nil?
16
+
17
+ html = if row[:meta][:actions].is_a? Hash
18
+ row[:meta][:actions].map do |name, link|
19
+ case name
20
+ when :show
21
+ button_success "", link, :icon => :search, :class => 'btn btn-lg'
22
+ when :edit
23
+ button_info "", link, :icon => :edit, :class => "btn btn-lg"
24
+ when :destroy
25
+ button_danger "", link, default_destroy_link_attributes.merge(:icon => :trash, :class => "btn btn-lg")
26
+ else
27
+ button "", link, :icon => :name, :class => "btn btn-lg"
28
+ end
29
+ end.join ''
30
+ else
31
+ row[:meta][:actions]
32
+ end
33
+
34
+ "<td>#{html}</td>"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "table"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class InplaceTable < Table
9
+ def initialize unicollection, helper, parser_class
10
+ raise "InplaceTable: Bad parser class (#{parser_class} instead of CollectionForHelper::Parser::Model)" if parser_class != CollectionForHelper::Parser::Model
11
+ super
12
+ end
13
+
14
+ def data_type elem
15
+ "input"
16
+ end
17
+
18
+ def custom_value_formatted value, elem
19
+ if elem.name.to_sym.in? [:header, :id, :created_at, :updated_at]
20
+ value
21
+ else
22
+ "<span class='best_in_place' data-type='#{data_type elem}' data-url='#{@unicollection.meta[:show]}' data-object='#{@unicollection.meta[:model_class].to_s.underscore}' data-attribute='#{elem.name}' data-type='input'>#{value}</span>"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require_relative "base"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class Map < Output::Base
9
+ delegate :image_tag, to: :@h
10
+
11
+ def render
12
+ locations = @unicollection.rows.map do |r|
13
+ r[:data].map(&:value).join(', ')
14
+ end
15
+
16
+ image_tag "http://maps.googleapis.com/maps/api/staticmap?size=600x300&maptype=roadmap&sensor=false&#{locations.map {|location| "markers=#{location}"}.join('&')}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,126 @@
1
+ require_relative "base"
2
+ require_relative "fields"
3
+
4
+ module Spyro
5
+ module ActionViewExtension
6
+
7
+ module CollectionForHelper
8
+ module Output
9
+ class Table < Output::Base
10
+ delegate :link_to, :mini_button, :mini_button_success, :mini_button_danger, :mini_button_info, to: :@h
11
+
12
+ include Fields
13
+
14
+ def header
15
+ @header ||= (@unicollection.meta[:header] || []) + (@unicollection.meta[:actions] ? ['Actions'] : [])
16
+ end
17
+
18
+ def render_header
19
+ return "" unless @unicollection.meta[:header]
20
+ content_tag :thead, @unicollection.meta[:html_header] do
21
+ html = header.map do |header_sym|
22
+ header = t(header_sym)
23
+ header = @unicollection.meta[:block_header].call header_sym, header if @unicollection.meta[:block_header]
24
+ "<th>#{header}</th>"
25
+ end.join('')
26
+ "<tr>#{html}</tr>".html_safe
27
+ end
28
+ end
29
+
30
+ def default_destroy_link_attributes
31
+ {:data => {:confirm => "Are you sure?", :method => "delete", :'confirm-title' => "Confirmation"}}
32
+ end
33
+
34
+ def render_cell_buttons row
35
+ row[:meta][:actions] = {} if row[:meta][:actions].nil?
36
+
37
+ html = if row[:meta][:actions].is_a? Hash
38
+ (row[:meta][:actions] || []).map do |name, link|
39
+ case name
40
+ when :show
41
+ mini_button_success name, link
42
+ when :edit
43
+ mini_button_info name, link
44
+ when :destroy
45
+ mini_button_danger name, link, default_destroy_link_attributes
46
+ else
47
+ mini_button name, link
48
+ end
49
+ end.join ''
50
+ else
51
+ row[:meta][:actions]
52
+ end
53
+
54
+ "<td><span class='btn-group'>#{html}</span></td>"
55
+ end
56
+
57
+ def format_value value, elem
58
+ return self.send("format_#{elem.as}".to_sym, value, {}) if elem.as
59
+
60
+
61
+ @@fields.each do |keys, values|
62
+ klass, pattern = *keys
63
+ if (Symbol === klass and klass == elem.db_type) or (Class === klass and value.is_a? klass)
64
+ return self.send("format_#{values[:method]}".to_sym, value, {}) if elem.name.to_s.match pattern
65
+ end
66
+ end
67
+ value
68
+ end
69
+
70
+ def custom_value_formatted value, elem
71
+ value
72
+ end
73
+
74
+ def render_body
75
+ content = @unicollection.rows.map do |row|
76
+ html = row[:data].map do |elem|
77
+ value_formatted = elem.value
78
+ value_formatted = t(value_formatted) if elem.translate
79
+ value_formatted = format_value value_formatted, elem
80
+ value_formatted = link_to value_formatted, elem.link if elem.link
81
+ value_formatted = custom_value_formatted value_formatted, elem
82
+ elem.html ? content_tag(:td, value_formatted, elem.html) : "<td>#{value_formatted}</td>"
83
+ end.join('')
84
+ html += render_cell_buttons row if @unicollection.meta[:actions]
85
+ (row[:meta][:opts] and row[:meta][:opts][:html]) ? content_tag(:tr, html.html_safe, row[:meta][:opts][:html]) : "<tr>#{html}</tr>"
86
+ end.join('').html_safe
87
+
88
+ if @unicollection.meta[:header]
89
+ content_tag :tbody, @unicollection.meta[:html_body] do
90
+ content
91
+ end
92
+ else
93
+ content
94
+ end
95
+ end
96
+
97
+ def render_footer
98
+ return "" unless @unicollection.meta[:footer] and @unicollection.meta[:header]
99
+
100
+ total = header.count
101
+
102
+ content_tag :tfoot, @unicollection.meta[:html_footer] do
103
+ content = @unicollection.meta[:footer].map do |elem|
104
+ colspan = [(header.count / @unicollection.meta[:footer].count.to_f).ceil, total].min
105
+ total -= colspan
106
+ "<td colspan='#{colspan}'>#{elem}</td>"
107
+ end.join('')
108
+ "<tr>#{content}</tr>".html_safe
109
+ end
110
+ end
111
+
112
+ def render
113
+ return "" if @unicollection.rows.empty?
114
+ table_html_opts = {:class => ['table', self.class.to_s.demodulize.underscore]}.deep_merge(@unicollection.meta[:html] || {}) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
115
+ content_tag :table, table_html_opts do
116
+ html = render_header.html_safe
117
+ html << render_body
118
+ html << render_footer
119
+ html
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "base"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class XLSX < Output::Base
9
+ def render_header sheet
10
+ return unless @unicollection.meta[:data]
11
+ sheet.add_row @unicollection.meta[:data]
12
+ end
13
+
14
+ def render_body sheet
15
+ @unicollection.rows.each do |row|
16
+ sheet.add_row row[:data].map(&:value)
17
+ end
18
+ end
19
+
20
+ def render
21
+ return "" if @unicollection.rows.empty?
22
+
23
+ filename = @unicollection.meta[:filename] || @unicollection.meta[:model_class] || "file"
24
+ xlsx_package = Axlsx::Package.new({})
25
+ wb = xlsx_package.workbook
26
+
27
+
28
+ wb.add_worksheet(name: filename) do |sheet|
29
+ render_header sheet
30
+ render_body sheet
31
+ end
32
+
33
+ xlsx_package.to_stream.string
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ # require_relative "base"
2
+ # require_relative "active_record_relation"
3
+ # require_relative "../../../app/models/active_ldap"
4
+
5
+ # module Spyro
6
+ # module ActionViewExtension
7
+
8
+ # module CollectionForHelper
9
+ # module Parser
10
+ # class ActiveLdapRelation < ActiveRecordRelation
11
+ # @@types[::ActiveLDAP::Relation] = self
12
+
13
+ # def initialize *args
14
+ # super
15
+
16
+ # header [:id, :login, :email], :actions => true
17
+ # end
18
+ # end
19
+ # end
20
+ # end
21
+ # end
22
+ # end
@@ -0,0 +1,138 @@
1
+ require_relative "base"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Parser
8
+ class ActiveRecordRelation < Parser::Base
9
+ @@types[::ActiveRecord::Relation] = self
10
+
11
+ def initialize collection, helper, options
12
+ super
13
+ end
14
+
15
+ def header args, opts = {}, &block
16
+ self.data args, opts, &block
17
+ end
18
+
19
+ def data args, opts = {}, &block
20
+ if args.is_a? ::Array
21
+ @unicollection.add_meta :data, args
22
+ else
23
+ @unicollection.add_meta :data, args.values.reduce(:+).uniq
24
+ args.each do |key, value|
25
+ @unicollection.add_meta "data-#{key}".to_sym, value
26
+ end
27
+ end
28
+
29
+ self.actions if opts[:actions]
30
+ @unicollection.add_meta :html_header, opts[:html]
31
+ @unicollection.add_meta :block_header, block if block_given?
32
+ end
33
+
34
+ def parse
35
+ unless @unicollection.has_meta? :data
36
+ @unicollection.add_meta :data, @collection.first.try(:attribute_names).try(:compact) || []
37
+ @unicollection.add_meta :actions, true
38
+ end
39
+
40
+ if @unicollection.rows.empty?
41
+ @collection.each do |model|
42
+ @unicollection.meta[:model_class] ||= model.class.to_s
43
+
44
+ @unicollection.row do |r|
45
+ @unicollection.meta[:data].each do |name|
46
+ hash = hash_for_name model, name
47
+ hash[:link] = link model if name == :name
48
+ r.add_elem UniData::Element.new(hash)
49
+ end
50
+ r.add_elem_meta :actions, populate_actions(model, r, @options, [:show, :edit, :destroy])
51
+ r.add_elem_meta :id, model.id
52
+ end
53
+ end
54
+ end
55
+
56
+ @unicollection.add_meta :header, @unicollection.meta[:data]
57
+ @unicollection.try_add_meta :footer, ["Total: #{@unicollection.rows.count}"]
58
+ end
59
+
60
+ def footer content, opts = {}
61
+ @unicollection.add_meta :footer, [*content]
62
+ @unicollection.add_meta :html_footer, opts[:html]
63
+ end
64
+
65
+ def populate_actions model, row, options, buttons
66
+ actions = {}
67
+
68
+ buttons.each do |button|
69
+ actions[:show] = polymorphic_path([*options[:parents], model]) rescue nil if button == :show
70
+ actions[:edit] = (actions[:show] ? "#{actions[:show]}/edit" : edit_polymorphic_path([*options[:parents], model])) rescue nil if button == :edit
71
+ actions[:destroy] = actions[:show] || polymorphic_path([*options[:parents], model]) rescue nil if button == :destroy
72
+ actions[button.keys.first] = button.values.first if button.is_a? Hash
73
+ end
74
+
75
+ actions.delete_if { |_, v| v.nil? }
76
+ end
77
+
78
+ def actions val = true
79
+ @unicollection.add_meta :actions, val
80
+ end
81
+
82
+ def body opts = {}, &block
83
+ def row opts
84
+ @r.add_elem_meta :opts, opts
85
+ end
86
+
87
+ @collection.each do |elem|
88
+ @unicollection.meta[:model_class] ||= elem.class.to_s
89
+ @unicollection.row do |r|
90
+ @elem = elem
91
+ @r = r
92
+ r.add_elem_meta :id, elem.id if elem.respond_to?(:id)
93
+ block.call elem
94
+ end
95
+ end
96
+
97
+ @unicollection.add_meta :html_body, opts[:html]
98
+ end
99
+
100
+ def cell value = nil, options = {}, &block
101
+ if value.is_a? Hash
102
+ options = value
103
+ value = nil
104
+ end
105
+
106
+ value = @h.capture(&block) || "" if block_given?
107
+
108
+ options[:link] = true if @unicollection.meta[:data] and @unicollection.meta[:data][@unicollection.rows.last[:data].count] == :name
109
+ options[:link] = link @elem if options[:link] == true
110
+
111
+ hash = if value
112
+ {value: value, type: String, name: "custom", db_type: String}
113
+ else
114
+ hash_for_name @elem, @unicollection.meta[:data][@unicollection.rows.last[:data].count]
115
+ end
116
+
117
+ @r.add_elem UniData::Element.new(hash.merge(options))
118
+ end
119
+
120
+ def buttons buttons = nil, opts = {}, &block
121
+ if block_given?
122
+ @r.add_elem_meta :actions, @h.capture(&block)
123
+ else
124
+ buttons = :all if buttons.nil?
125
+ buttons = [*buttons]
126
+ buttons.map! {|b| b == :all ? [:show, :edit, :destroy] : b}
127
+ buttons.flatten!
128
+ @r.add_elem_meta :actions, populate_actions(@elem, @r, @options, [*buttons])
129
+ end
130
+ end
131
+
132
+ alias_method :button, :buttons
133
+
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end