resource_renderer 1.0.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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +22 -0
  5. data/app/attribute_renderers/acts_as_list_renderer.rb +21 -0
  6. data/app/attribute_renderers/association_renderer.rb +23 -0
  7. data/app/attribute_renderers/attachment_renderer.rb +11 -0
  8. data/app/attribute_renderers/big_decimal_renderer.rb +2 -0
  9. data/app/attribute_renderers/boolean_renderer.rb +7 -0
  10. data/app/attribute_renderers/date_renderer.rb +8 -0
  11. data/app/attribute_renderers/duration_renderer.rb +47 -0
  12. data/app/attribute_renderers/email_renderer.rb +15 -0
  13. data/app/attribute_renderers/false_class_renderer.rb +2 -0
  14. data/app/attribute_renderers/fixnum_renderer.rb +2 -0
  15. data/app/attribute_renderers/image_renderer.rb +8 -0
  16. data/app/attribute_renderers/nil_class_renderer.rb +5 -0
  17. data/app/attribute_renderers/resource_renderer/attribute_renderer/base.rb +28 -0
  18. data/app/attribute_renderers/string_renderer.rb +15 -0
  19. data/app/attribute_renderers/text_renderer.rb +13 -0
  20. data/app/attribute_renderers/textile_doc_renderer.rb +2 -0
  21. data/app/attribute_renderers/thumbnail_renderer.rb +13 -0
  22. data/app/attribute_renderers/time_renderer.rb +8 -0
  23. data/app/attribute_renderers/true_class_renderer.rb +2 -0
  24. data/app/attribute_renderers/youtube_video_renderer.rb +20 -0
  25. data/app/collection_renderers/bootstrap_table_collection_renderer.rb +11 -0
  26. data/app/collection_renderers/bootstrap_thumbnail_collection_renderer.rb +9 -0
  27. data/app/collection_renderers/resource_renderer/collection_renderer/base.rb +45 -0
  28. data/app/collection_renderers/table_collection_renderer.rb +96 -0
  29. data/app/collection_renderers/timeline_collection_renderer.rb +5 -0
  30. data/app/helpers/resource_renderer/application_helper.rb +4 -0
  31. data/app/helpers/resource_renderer/view_helper.rb +69 -0
  32. data/app/resource_renderers/attribute_table_resource_renderer.rb +41 -0
  33. data/app/resource_renderers/bootstrap_attribute_table_resource_renderer.rb +7 -0
  34. data/app/resource_renderers/bootstrap_thumbnail_resource_renderer.rb +15 -0
  35. data/app/resource_renderers/resource_renderer/resource_renderer/base.rb +70 -0
  36. data/app/resource_renderers/table_resource_renderer.rb +60 -0
  37. data/app/resource_renderers/text_resource_renderer.rb +7 -0
  38. data/app/resource_renderers/timeline_resource_renderer.rb +36 -0
  39. data/app/resource_renderers/unordered_list_resource_renderer.rb +23 -0
  40. data/app/services/timeline/extract_events_service.rb +39 -0
  41. data/app/values/timeline/event.rb +11 -0
  42. data/lib/resource_renderer.rb +5 -0
  43. data/lib/resource_renderer/engine.rb +4 -0
  44. data/lib/resource_renderer/version.rb +3 -0
  45. metadata +242 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14657a217dfa0b3161b7426718a6b93b0cc751cb
4
+ data.tar.gz: 449f911f3dff114495e7e7440b71f03c121235c5
5
+ SHA512:
6
+ metadata.gz: e38924837f35761f15230232fde26fb51e8ca8a4e07436e4992b001efb0c7a67b6edac114a577ff55bfa233382925a74b768f4b9af07de4250f76f5c2ff301a1
7
+ data.tar.gz: e106380c0e971a26d5f591e24c36e5e4177765cc1434f3de8891b7e2e7aa26c189567df3d633b1dd2f0a991256b0c6c6c4abed44ea58a1d89c3f0bed3b08288c
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Roberto Vasquez Angel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = ResourceRenderer
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ResourceRenderer'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,21 @@
1
+ class ActsAsListRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(scope: nil)
4
+
5
+ scope = options.delete(:scope)
6
+
7
+ scope = "#{scope}_id".intern if scope.is_a?(Symbol) && scope.to_s !~ /_id$/
8
+
9
+ data_attributes = {
10
+ 'acts-as-list-item': true,
11
+ 'acts-as-list-item-uid': model.to_param,
12
+ 'acts-as-list-item-on-drop-target': h.url_for([:reposition, model])
13
+ }
14
+ data_attributes['acts-as-list-item-scope'] = "#{scope}-#{model.send(scope)}" if scope.present?
15
+
16
+
17
+ h.content_tag(:span, data: data_attributes, class: 'btn btn-xs btn-default acts-as-list-item') do
18
+ h.tag(:span, class: 'glyphicon glyphicon-sort')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ class AssociationRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(label_method: :to_s)
4
+ label_method = options.delete(:label_method)
5
+
6
+ associated = value_for_attribute(attribute_name)
7
+
8
+ return if associated.nil?
9
+
10
+ url = options.delete(:url)
11
+ label = associated.send(label_method)
12
+
13
+ target = url.call(model) if url.is_a?(Proc)
14
+ target = url if url.is_a?(String)
15
+ target = associated if url.is_a?(TrueClass)
16
+
17
+ if target.nil?
18
+ label
19
+ else
20
+ h.link_to(label, target)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ class AttachmentRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(format: :long)
4
+ format = options.delete(:format)
5
+
6
+ h.link_to(value_for_attribute(attribute_name).url) do
7
+ h.tag(:span, class: 'btn btn-xs btn-primary btn-responsive') +
8
+ h.content_tag(:span, h.t(".download"), class: 'btn-text')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ class BigDecimalRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ end
@@ -0,0 +1,7 @@
1
+ class BooleanRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ private
3
+
4
+ def value_for_attribute(attribute_name)
5
+ I18n.t("booleans.#{model.send(attribute_name).to_s}")
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class DateRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(format: :long)
4
+ format = options.delete(:format)
5
+
6
+ I18n.l(value_for_attribute(attribute_name), format: format)
7
+ end
8
+ end
@@ -0,0 +1,47 @@
1
+ class DurationRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ return h.capture { block.call(resource) } if block_given?
4
+
5
+ options.reverse_merge!(input_unit: :seconds)
6
+ input_unit = options.delete(:input_unit)
7
+
8
+ input_duration = value_for_attribute(attribute_name)
9
+ seconds = duration_in_seconds(input_duration, input_unit)
10
+
11
+ html_attributes = {
12
+
13
+ }
14
+
15
+ helper.capture do
16
+ h.content_tag(:span, html_attributes) { humanize(seconds) }
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def duration_in_seconds(input_duration, input_unit)
23
+ case input_unit
24
+ when :seconds
25
+ input_duration
26
+ when :minutes
27
+ input_duration * 60
28
+ when :hours
29
+ input_duration * 3600
30
+ when :days
31
+ input_duration * 86400
32
+ when :weeks
33
+ input_duration * 604800
34
+ end
35
+ end
36
+
37
+ def humanize(seconds)
38
+ [[60, :seconds], [60, :minutes], [24, :hours], [1000, :days]].inject([]){ |s, (count, name)|
39
+ if seconds > 0
40
+ seconds, n = seconds.divmod(count)
41
+ translated_name = I18n.t("datetime.distance_in_words.x_#{name}", count: n.to_i)
42
+ s.unshift translated_name
43
+ end
44
+ s
45
+ }.join(' ')
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ class EmailRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ return h.capture { block.call(resource) } if block_given?
4
+ options.reverse_merge!(class: 'email')
5
+ html_class = options.delete(:class)
6
+
7
+ html_attributes = {
8
+ class: html_class
9
+ }
10
+
11
+ helper.capture do
12
+ h.content_tag(:div, html_attributes) { h.mail_to value_for_attribute(attribute_name) }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ class FalseClassRenderer < BooleanRenderer
2
+ end
@@ -0,0 +1,2 @@
1
+ class FixnumRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ end
@@ -0,0 +1,8 @@
1
+ class ImageRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(format: :long)
4
+ format = options.delete(:format)
5
+
6
+ h.image_tag(value_for_attribute(attribute_name).url, class: 'img-responsive')
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class NilClassRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(field, label, options = {}, &block)
3
+ ''
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ module ResourceRenderer
2
+ module AttributeRenderer
3
+ class Base
4
+ attr_accessor :model, :helper
5
+ alias_method :h, :helper
6
+
7
+ def initialize(model, helper)
8
+ @model, @helper = model, helper
9
+ end
10
+
11
+ def display(attribute_name, label, options = {}, &block)
12
+ helper.capture do
13
+ if block_given?
14
+ block.call(resource)
15
+ else
16
+ "#{value_for_attribute(attribute_name)}"
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def value_for_attribute(attribute_name)
24
+ model.send(attribute_name)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ class StringRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ return h.capture { block.call(resource) } if block_given?
4
+ options.reverse_merge!(class: nil)
5
+ html_class = options.delete(:class)
6
+
7
+ html_attributes = {
8
+ class: html_class
9
+ }
10
+
11
+ helper.capture do
12
+ h.content_tag(:div, html_attributes) { value_for_attribute(attribute_name) }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class TextRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ editor_syntax = options.delete(:editor_syntax)
4
+
5
+ html_attributes = {
6
+ id: "#{model.class.name.parameterize}-#{model.to_param}",
7
+ 'data-add-editor': true
8
+ }
9
+ html_attributes[:'data-editor-syntax'] = editor_syntax if editor_syntax.present?
10
+
11
+ h.content_tag(:pre, html_attributes) { value_for_attribute(attribute_name) }
12
+ end
13
+ end
@@ -0,0 +1,2 @@
1
+ class TextileDocRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ end
@@ -0,0 +1,13 @@
1
+ class ThumbnailRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(style: :thumb, image_tag_options: { class: 'thumbnail' })
4
+ style = options.delete(:style)
5
+ image_tag_options = options.delete(:image_tag_options)
6
+
7
+ attachment = value_for_attribute(attribute_name)
8
+ return unless attachment.respond_to?(:url)
9
+ source = attachment.url(style)
10
+
11
+ helper.image_tag(source, image_tag_options)
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ class TimeRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(format: :long)
4
+ format = options.delete(:format)
5
+
6
+ I18n.l(value_for_attribute(attribute_name), format: format)
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ class TrueClassRenderer < BooleanRenderer
2
+ end
@@ -0,0 +1,20 @@
1
+ class YoutubeVideoRenderer < ResourceRenderer::AttributeRenderer::Base
2
+ def display(attribute_name, label, options = {}, &block)
3
+ options.reverse_merge!(width: 640, height: 480, aspect_ratio: '16by9')
4
+ aspect_ratio = options.delete(:aspect_ratio)
5
+ # width = options.delete(:width)
6
+ # height = options.delete(:height)
7
+
8
+ iframe_attributes = {
9
+ class: 'embed-responsive-item',
10
+ # width: width,
11
+ # height: height,
12
+ src: "https://www.youtube.com/embed/#{model.identifier}",
13
+ frameborder: '0'
14
+ }
15
+
16
+ h.content_tag(:div, class: "embed-responsive embed-responsive-#{aspect_ratio}") do
17
+ h.content_tag(:iframe, nil, iframe_attributes)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ class BootstrapTableCollectionRenderer < TableCollectionRenderer
2
+ private
3
+
4
+ def renderer_class_name
5
+ 'TableResourceRenderer'
6
+ end
7
+
8
+ def table_html_options
9
+ { class: 'table table-responsive table-condensed table-striped table-hover' }
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class BootstrapThumbnailCollectionRenderer < ResourceRenderer::CollectionRenderer::Base
2
+ def render(&block)
3
+ helper.capture do
4
+ helper.content_tag(:div, class: 'row') do
5
+ render_collection(&block)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module ResourceRenderer
2
+ module CollectionRenderer
3
+ class Base
4
+ attr_accessor :helper, :collection, :resource_class
5
+
6
+ def initialize(collection, resource_class, helper)
7
+ @collection, @resource_class, @helper = collection, resource_class, helper
8
+ end
9
+
10
+ def render(&block)
11
+ helper.capture do
12
+ render_collection(&block)
13
+ end
14
+ end
15
+
16
+ def association(*args, &block)
17
+ options = args.extract_options!
18
+ options[:as] = :association
19
+ column(*args, options, &block)
20
+ end
21
+
22
+ private
23
+
24
+ def render_collection(&block)
25
+ collection.collect do |resource|
26
+ renderer_class.new(resource, helper).render(&block)
27
+ end.join.html_safe
28
+ end
29
+
30
+ def renderer_class
31
+ @renderer_class ||= get_renderer_class
32
+ end
33
+
34
+ def get_renderer_class
35
+ renderer = Object.const_get(renderer_class_name)
36
+ raise DisplayBlockNotDefinedException, "#{renderer.to_s} not defined" unless renderer.is_a?(Class)
37
+ renderer
38
+ end
39
+
40
+ def renderer_class_name
41
+ self.class.name.gsub('Collection', 'Resource')
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,96 @@
1
+ class TableCollectionRenderer < ResourceRenderer::CollectionRenderer::Base
2
+ class Header
3
+ attr_accessor :controller, :helper, :view_context, :resource_class
4
+ alias_method :h, :helper
5
+
6
+ def initialize(resource_class, helper)
7
+ @resource_class, @helper = resource_class, helper
8
+ @controller = helper.instance_variable_get('@_controller')
9
+ @view_context = @controller.view_context
10
+ end
11
+
12
+ def render(&block)
13
+ helper.content_tag(:tr) do
14
+ block.call(self)
15
+ end
16
+ end
17
+
18
+ def association(*args, &block)
19
+ options = args.extract_options!
20
+ options[:as] = :association
21
+ column(*args, options, &block)
22
+ end
23
+
24
+ def column(attribute_name, options = {})
25
+ return column_with_sorting(attribute_name, options) if ransack_query.present? && options.has_key?(:sortable) && options[:sortable] != false
26
+
27
+ label = if @resource_class.respond_to?(:human_attribute_name)
28
+ @resource_class.human_attribute_name(attribute_name)
29
+ else
30
+ attribute_name
31
+ end
32
+ helper.content_tag(:th, label)
33
+ end
34
+
35
+ def timestamps
36
+ column(:created_at, sortable: true) +
37
+ column(:updated_at, sortable: true)
38
+ end
39
+
40
+ def acts_as_published_actions
41
+ column(:acts_as_published_actions)
42
+ end
43
+
44
+ def acts_as_list_actions(options = {})
45
+ column(:acts_as_published_actions)
46
+ end
47
+ private
48
+
49
+ def column_with_sorting(attribute_name, options = {})
50
+ sort_by = case options[:sortable]
51
+ when TrueClass
52
+ attribute_name
53
+ when Symbol, String, Array
54
+ options[:sortable]
55
+ end
56
+
57
+
58
+ label = if @resource_class.respond_to?(:human_attribute_name)
59
+ @resource_class.human_attribute_name(attribute_name)
60
+ else
61
+ attribute_name
62
+ end
63
+
64
+ sort_link = helper.sort_link(ransack_query, sort_by, label)
65
+
66
+ helper.content_tag(:th, sort_link)
67
+ end
68
+
69
+ def ransack_query
70
+ view_context.instance_variable_get('@q')
71
+ end
72
+ end
73
+
74
+ def render(&block)
75
+ helper.capture do
76
+ helper.content_tag(:table, table_html_options) do
77
+ helper.concat render_header(&block)
78
+ helper.concat render_collection(&block)
79
+ end
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def table_html_options
86
+ nil
87
+ end
88
+
89
+ def render_header(&block)
90
+ header_renderer.render(&block)
91
+ end
92
+
93
+ def header_renderer
94
+ Header.new(resource_class, helper)
95
+ end
96
+ end
@@ -0,0 +1,5 @@
1
+ class TimelineCollectionRenderer < ResourceRenderer::CollectionRenderer::Base
2
+ def collection
3
+ @collection.sort! { |a, b| a.happened_at <=> b.happened_at }
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module ResourceRenderer
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,69 @@
1
+ module ResourceRenderer
2
+ module ViewHelper
3
+ class RenderCollection
4
+ attr_accessor :helper, :collection, :renderer, :renderer_class
5
+
6
+ def initialize(collection, resource_class, helper, options = {})
7
+ options.reverse_merge!({ :as => :text })
8
+
9
+ renderer_name = options.delete(:as)
10
+
11
+ self.renderer_class = get_renderer_class(renderer_name)
12
+ self.collection = collection
13
+ self.helper = helper
14
+ self.renderer = renderer_class.new(collection, resource_class, helper)
15
+ self
16
+ end
17
+
18
+ def render_collection(&block)
19
+ renderer.render(&block)
20
+ end
21
+
22
+ private
23
+
24
+ def get_renderer_class(renderer_name)
25
+ renderer_class_name = "#{renderer_name.to_s.camelize}CollectionRenderer"
26
+ renderer = Object.const_get(renderer_class_name)
27
+ raise DisplayBlockNotDefinedException, "#{renderer.to_s} not defined" unless renderer.is_a?(Class)
28
+ renderer
29
+ end
30
+ end
31
+
32
+ class RenderResource
33
+ attr_accessor :helper, :resource, :renderer, :renderer_class
34
+
35
+ def initialize(resource, helper, options = {})
36
+ options.reverse_merge!({ :as => :text })
37
+
38
+ renderer_name = options.delete(:as)
39
+
40
+ self.renderer_class = get_renderer_class(renderer_name)
41
+ self.resource = resource
42
+ self.helper = helper
43
+ self.renderer = renderer_class.new(resource, helper)
44
+ self
45
+ end
46
+
47
+ def render(&block)
48
+ renderer.render(&block)
49
+ end
50
+
51
+ private
52
+
53
+ def get_renderer_class(renderer_name)
54
+ renderer_class_name = "#{renderer_name.to_s.camelize}ResourceRenderer"
55
+ renderer = Object.const_get(renderer_class_name)
56
+ raise DisplayBlockNotDefinedException, "#{renderer.to_s} not defined" unless renderer.is_a?(Class)
57
+ renderer
58
+ end
59
+ end
60
+
61
+ def render_resource(resource, options = {}, &block)
62
+ RenderResource.new(resource, self, options).render(&block)
63
+ end
64
+
65
+ def render_collection(collection, resource_class, options = {}, &block)
66
+ RenderCollection.new(collection, resource_class, self, options).render_collection(&block)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,41 @@
1
+ require_dependency 'resource_renderer/resource_renderer/base'
2
+
3
+ class AttributeTableResourceRenderer < ResourceRenderer::ResourceRenderer::Base
4
+ def row(attribute_name, options = {}, &block)
5
+ build_table_row(attribute_name, options, &block)
6
+ end
7
+
8
+ def render(&block)
9
+ helper.content_tag(:table, table_html_options) do
10
+ block.call(self)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def table_html_options
17
+ nil
18
+ end
19
+
20
+ def build_table_row(attribute_name, options = {}, &block)
21
+ options.reverse_merge!(table_row_html_options: default_html_options_for_table_row(attribute_name))
22
+ table_row_html_options = options.delete(:table_row_html_options)
23
+
24
+ helper.content_tag(:tr, table_row_html_options) do
25
+ helper.content_tag(:th) do
26
+ helper.content_tag(:span, extract_label(attribute_name), class: 'key')
27
+ end +
28
+ helper.content_tag(:td) do
29
+ if block_given?
30
+ block.call(resource)
31
+ else
32
+ helper.content_tag(:span, display(attribute_name, options), class: 'value')
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def default_html_options_for_table_row(attribute_name)
39
+ { role: attribute_name.to_s.dasherize }
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ class BootstrapAttributeTableResourceRenderer < AttributeTableResourceRenderer
2
+ private
3
+
4
+ def table_html_options
5
+ { class: 'table table-responsive table-condensed table-striped table-hover' }
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ class BootstrapThumbnailResourceRenderer < ResourceRenderer::ResourceRenderer::Base
2
+ def render(&block)
3
+ helper.content_tag(:div) do
4
+ block.call(self)
5
+ end
6
+ end
7
+
8
+ def thumbnail(attribute_name, options = {}, &block)
9
+ options[:as] = :thumbnail
10
+
11
+ helper.content_tag(:div, class: 'col-xs-12 col-sm-6 col-md-4 col-lg-2') do
12
+ display(attribute_name, options, &block)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,70 @@
1
+ module ResourceRenderer
2
+ module ResourceRenderer
3
+ class Base
4
+ attr_accessor :helper, :resource
5
+
6
+ def initialize(resource, helper)
7
+ @resource, @helper = resource, helper
8
+ end
9
+
10
+ def render(&block)
11
+ helper.capture do
12
+ block.call(self)
13
+ end
14
+ end
15
+
16
+ def display(attribute_name, options = {}, &block)
17
+ attribute_renderer_name = options.delete(:as) if options.has_key?(:as)
18
+ label = options.delete(:label)
19
+ label ||= extract_label(attribute_name)
20
+
21
+ attribute_renderer(attribute_name, attribute_renderer_name, &block).display(attribute_name, label, options, &block)
22
+ end
23
+
24
+ def association(*args, &block)
25
+ options = args.extract_options!
26
+ options[:as] = :association
27
+ column(*args, options, &block)
28
+ end
29
+
30
+ def resource_class
31
+ @resource_class ||= resource.class
32
+ end
33
+
34
+ private
35
+
36
+ def attribute_renderer(attribute_name, attribute_renderer_name = nil, &block)
37
+ klass = attribute_renderer_class_for(attribute_name, attribute_renderer_name, &block)
38
+ klass.new(resource, helper)
39
+ end
40
+
41
+ def extract_label(attribute_name)
42
+ if resource_class.respond_to?(:human_attribute_name)
43
+ resource_class.human_attribute_name(attribute_name)
44
+ else
45
+ attribute_name.to_s
46
+ end
47
+ end
48
+
49
+ def attribute_value(attribute_name)
50
+ attribute_renderer(attribute_name)
51
+ end
52
+
53
+ def attribute_renderer_class_for(attribute_name, attribute_renderer_name = nil, &block)
54
+ displayer_type = if block_given?
55
+ :base
56
+ elsif attribute_renderer_name.present?
57
+ attribute_renderer_name
58
+ else
59
+ resource.send(attribute_name).class.name.demodulize.underscore.to_sym
60
+ end
61
+ klass_name = "#{displayer_type}_renderer".camelize
62
+ klass = Object.const_get(klass_name)
63
+ unless klass.is_a?(Class)
64
+ raise DisplayerNotDefinedException, "#{klass.to_s} not defined"
65
+ end
66
+ return klass
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,60 @@
1
+ class TableResourceRenderer < ResourceRenderer::ResourceRenderer::Base
2
+ def column(attribute_name, options = {}, &block)
3
+ build_table_data(attribute_name, options, &block)
4
+ end
5
+
6
+ def render(&block)
7
+ helper.content_tag(:tr) do
8
+ block.call(self)
9
+ end
10
+ end
11
+
12
+ def timestamps
13
+ column(:created_at) +
14
+ column(:updated_at)
15
+ end
16
+
17
+ def acts_as_published_actions
18
+ link_path = helper.controller.url_for(action: :toggle_published, id: resource.to_param)
19
+ column(:published_actions) do |resource|
20
+ if resource.published?
21
+ helper.link_to(link_path, class: 'btn btn-xs btn-danger btn-responsive', method: :post) do
22
+ helper.content_tag(:span, nil, class: 'glyphicon glyphicon-eye-close') +
23
+ helper.content_tag(:span, helper.t('.unpublish', default: helper.t('acts_as_published.actions.unpublish')), class: 'btn-text')
24
+ end
25
+ else
26
+ helper.link_to(link_path, class: 'btn btn-xs btn-success btn-responsive', method: :post) do
27
+ helper.content_tag(:span, nil, class: 'glyphicon glyphicon-eye-open') +
28
+ helper.content_tag(:span, helper.t('.publish', default: helper.t('acts_as_published.actions.publish')), class: 'btn-text')
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def acts_as_list_actions(options = {})
35
+ scope = options[:scope]
36
+
37
+ column_options = { as: :acts_as_list }
38
+ column_options[:scope] = scope if scope.present?
39
+ column :acts_as_list_actions, column_options
40
+ end
41
+
42
+ private
43
+
44
+ def build_table_data(attribute_name, options = {}, &block)
45
+ options.reverse_merge!(table_column_html_options: default_html_options_for_table_column(attribute_name))
46
+ table_column_html_options = options.delete(:table_column_html_options)
47
+
48
+ helper.content_tag(:td, table_column_html_options) do
49
+ if block_given?
50
+ block.call(resource)
51
+ else
52
+ helper.content_tag(:span, display(attribute_name, options), class: 'value')
53
+ end
54
+ end
55
+ end
56
+
57
+ def default_html_options_for_table_column(attribute_name)
58
+ { role: attribute_name.to_s.dasherize }
59
+ end
60
+ end
@@ -0,0 +1,7 @@
1
+ class TextResourceRenderer < ResourceRenderer::ResourceRenderer::Base
2
+ def render(&block)
3
+ helper.content_tag(:pre) do
4
+ block.call(self)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ class TimelineResourceRenderer < ResourceRenderer::ResourceRenderer::Base
2
+ def event(attribute_name, options = {}, &block)
3
+ build_event(attribute_name, options, &block)
4
+ end
5
+
6
+ private
7
+
8
+ def build_event(attribute_name, options, &block)
9
+ options.reverse_merge!(title_method: :to_s, description_method: :inspect, timestamp_method: :created_at)
10
+ @timestamp_method = options.delete(:timestamp_method)
11
+ @title_method = options.delete(:title_method)
12
+ @description_method = options.delete(:description_method)
13
+
14
+ event = resource.is_a?(Timeline::Event) ? resource : extract_event
15
+
16
+
17
+ helper.content_tag(:div, class: 'timeline-block') do
18
+ helper.content_tag(:div, class: 'timeline-icon') do
19
+ end +
20
+ helper.content_tag(:div, class: 'timeline-content') do
21
+ helper.content_tag(:div, class: 'timeline-body') do
22
+ helper.content_tag(:div, event.title, class: 'timeline-title') +
23
+ helper.content_tag(:div, event.description, class: 'timeline-description')
24
+ end +
25
+ helper.content_tag(:div, I18n.l(event.happened_at), class: 'timeline-date')
26
+ end
27
+ end
28
+ end
29
+
30
+ def extract_event
31
+ Timeline::ExtractEventsService.call(resources: [resource],
32
+ title_method: @title_method,
33
+ description_method: @description_method,
34
+ timestamp_method: @timestamp_method).events.first
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ class UnorderedListResourceRenderer < ResourceRenderer::ResourceRenderer::Base
2
+ def display(attribute_name, options = {})
3
+ options.reverse_merge!(html_options: default_html_options_for(attribute_name))
4
+
5
+ html_options = options.delete(:html_options)
6
+ helper.content_tag(:li, html_options) do
7
+ helper.content_tag(:span, translated_attribute_name(attribute_name), class: 'key') +
8
+ helper.content_tag(:span, attribute_value(attribute_name), class: 'value')
9
+ end
10
+ end
11
+
12
+ def render(&block)
13
+ helper.content_tag(:ul) do
14
+ block.call(self)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def default_html_options_for(attribute_name)
21
+ { role: attribute_name.to_s.dasherize }
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ require 'timeline/event'
2
+
3
+ module Timeline
4
+ class ExtractEventsService < Itsf::Services::V2::Service::Base
5
+ class Response < Itsf::Services::V2::Response::Base
6
+ attr_accessor :events
7
+ end
8
+
9
+ attr_accessor :resources, :title_method, :description_method, :timestamp_method
10
+
11
+ def do_work
12
+ return response unless valid?
13
+ response.events = extract_events
14
+ respond
15
+ end
16
+
17
+ private
18
+
19
+ def initialize_attributes
20
+ @title_method = :title
21
+ @description_method = :description
22
+ @timestamp_method = :created_at
23
+ end
24
+
25
+ def extract_events
26
+ info 'Extracting Events'
27
+ resources.collect do |resource|
28
+ Event.new(
29
+ title: resource.send(title_method),
30
+ description: resource.send(description_method),
31
+ happened_at: resource.send(timestamp_method))
32
+ end
33
+ end
34
+
35
+ def resources
36
+ @resources || []
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ module Timeline
2
+ class Event
3
+ attr_accessor :title, :description, :happened_at
4
+
5
+ def initialize(attributes)
6
+ attributes.each do |name, value|
7
+ send("#{name}=", value)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ require 'itsf_services'
2
+ require 'resource_renderer/engine'
3
+
4
+ module ResourceRenderer
5
+ end
@@ -0,0 +1,4 @@
1
+ module ResourceRenderer
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module ResourceRenderer
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,242 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resource_renderer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Roberto Vasquez Angel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: itsf_services
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: capybara
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: shoulda-matchers
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: factory_girl_rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: guard-bundler
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: guard-rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: A simple way to render resources.
168
+ email:
169
+ - roberto@vasquez-angel.de
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - MIT-LICENSE
175
+ - README.rdoc
176
+ - Rakefile
177
+ - app/attribute_renderers/acts_as_list_renderer.rb
178
+ - app/attribute_renderers/association_renderer.rb
179
+ - app/attribute_renderers/attachment_renderer.rb
180
+ - app/attribute_renderers/big_decimal_renderer.rb
181
+ - app/attribute_renderers/boolean_renderer.rb
182
+ - app/attribute_renderers/date_renderer.rb
183
+ - app/attribute_renderers/duration_renderer.rb
184
+ - app/attribute_renderers/email_renderer.rb
185
+ - app/attribute_renderers/false_class_renderer.rb
186
+ - app/attribute_renderers/fixnum_renderer.rb
187
+ - app/attribute_renderers/image_renderer.rb
188
+ - app/attribute_renderers/nil_class_renderer.rb
189
+ - app/attribute_renderers/resource_renderer/attribute_renderer/base.rb
190
+ - app/attribute_renderers/string_renderer.rb
191
+ - app/attribute_renderers/text_renderer.rb
192
+ - app/attribute_renderers/textile_doc_renderer.rb
193
+ - app/attribute_renderers/thumbnail_renderer.rb
194
+ - app/attribute_renderers/time_renderer.rb
195
+ - app/attribute_renderers/true_class_renderer.rb
196
+ - app/attribute_renderers/youtube_video_renderer.rb
197
+ - app/collection_renderers/bootstrap_table_collection_renderer.rb
198
+ - app/collection_renderers/bootstrap_thumbnail_collection_renderer.rb
199
+ - app/collection_renderers/resource_renderer/collection_renderer/base.rb
200
+ - app/collection_renderers/table_collection_renderer.rb
201
+ - app/collection_renderers/timeline_collection_renderer.rb
202
+ - app/helpers/resource_renderer/application_helper.rb
203
+ - app/helpers/resource_renderer/view_helper.rb
204
+ - app/resource_renderers/attribute_table_resource_renderer.rb
205
+ - app/resource_renderers/bootstrap_attribute_table_resource_renderer.rb
206
+ - app/resource_renderers/bootstrap_thumbnail_resource_renderer.rb
207
+ - app/resource_renderers/resource_renderer/resource_renderer/base.rb
208
+ - app/resource_renderers/table_resource_renderer.rb
209
+ - app/resource_renderers/text_resource_renderer.rb
210
+ - app/resource_renderers/timeline_resource_renderer.rb
211
+ - app/resource_renderers/unordered_list_resource_renderer.rb
212
+ - app/services/timeline/extract_events_service.rb
213
+ - app/values/timeline/event.rb
214
+ - lib/resource_renderer.rb
215
+ - lib/resource_renderer/engine.rb
216
+ - lib/resource_renderer/version.rb
217
+ homepage: https://github.com/robotex82/resource_renderer
218
+ licenses:
219
+ - MIT
220
+ metadata: {}
221
+ post_install_message:
222
+ rdoc_options: []
223
+ require_paths:
224
+ - lib
225
+ required_ruby_version: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ required_rubygems_version: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - ">="
233
+ - !ruby/object:Gem::Version
234
+ version: '0'
235
+ requirements: []
236
+ rubyforge_project:
237
+ rubygems_version: 2.4.8
238
+ signing_key:
239
+ specification_version: 4
240
+ summary: A simple way to render resources.
241
+ test_files: []
242
+ has_rdoc: