lite-component 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,22 @@
2
2
 
3
3
  module Lite
4
4
  module Component
5
- class Base < Lite::Component::Element
5
+ class Base
6
+
7
+ include ActionView::Context
8
+ include ActionView::Helpers
9
+
10
+ attr_reader :context, :options
11
+ attr_writer :iteration
12
+
13
+ def initialize(context, options = {})
14
+ @context = context
15
+ @options = default_options.deep_merge(options)
16
+ end
17
+
18
+ alias helpers context
19
+ alias c context
20
+ alias h helpers
6
21
 
7
22
  class << self
8
23
 
@@ -11,21 +26,59 @@ module Lite
11
26
  end
12
27
 
13
28
  def component_path
14
- name.chomp('Component').underscore
29
+ name.underscore.sub('_component', '')
15
30
  end
16
31
 
17
- def model_name
18
- ActiveModel::Name.new(Lite::Component::Base)
32
+ def render(context, options = {})
33
+ klass = new(context, options)
34
+ klass.render
19
35
  end
20
36
 
21
37
  end
22
38
 
39
+ def iteration
40
+ @iteration ||= Lite::Component::Iteration.new(1, 0)
41
+ end
42
+
43
+ alias i iteration
44
+
45
+ def locals
46
+ @locals ||= Lite::Component::Locals.new(options[:locals])
47
+ end
48
+
49
+ alias l locals
50
+
23
51
  def render
24
- context.render(partial: to_partial_path, object: self)
52
+ collection = options.delete(:collection)
53
+ return render_content if collection.nil? || !collection.respond_to?(:to_a)
54
+
55
+ Lite::Component::Collection.render(
56
+ collection,
57
+ component: self,
58
+ spacer_template: options.delete(:spacer_template)
59
+ )
60
+ end
61
+
62
+ def render_content
63
+ context.render(options)
25
64
  end
26
65
 
27
66
  def to_partial_path
28
- "components/#{self.class.component_path}"
67
+ "components/#{self.class.component_name}"
68
+ end
69
+
70
+ private
71
+
72
+ def default_options
73
+ {
74
+ partial: to_partial_path,
75
+ object: self,
76
+ as: :component,
77
+ locals: {
78
+ object: nil,
79
+ iteration: iteration
80
+ }
81
+ }
29
82
  end
30
83
 
31
84
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Component
5
+ class Collection
6
+
7
+ attr_reader :collection, :component, :spacer_template
8
+
9
+ def initialize(collection, component:, spacer_template: nil)
10
+ @collection = collection
11
+ @component = component
12
+ @spacer_template = spacer_template
13
+ end
14
+
15
+ class << self
16
+
17
+ def render(collection, component)
18
+ klass = new(collection, component)
19
+ klass.render
20
+ end
21
+
22
+ end
23
+
24
+ def render
25
+ component.context.safe_join(iterated_collection)
26
+ end
27
+
28
+ private
29
+
30
+ def collection_size
31
+ @collection_size ||= collection.size
32
+ end
33
+
34
+ # rubocop:disable Metrics/AbcSize
35
+ def iterated_collection
36
+ collection.each_with_object([]).with_index do |(object, array), index|
37
+ component.iteration = Lite::Component::Iteration.new(collection_size, index)
38
+ component.options.deep_merge!(locals: { object: object, iteration: component.iteration })
39
+
40
+ array << component.render_content
41
+ next unless spacer_template && !component.iteration.last?
42
+
43
+ array << component.context.render(spacer_template)
44
+ end
45
+ end
46
+ # rubocop:enable Metrics/AbcSize
47
+
48
+ end
49
+ end
50
+ end
@@ -8,17 +8,6 @@ module Lite
8
8
 
9
9
  initializer('lite-component.setup', group: :all) do |app|
10
10
  app.paths['config'] << File.join(config.root, 'app')
11
- app.paths['config'] << File.join(config.root, 'vendor')
12
- end
13
-
14
- initializer('lite-component.asset_path') do |app|
15
- app.config.assets.paths << Lite::Component.path if app.config.respond_to?(:assets)
16
- end
17
-
18
- initializer('lite-component.view_paths') do
19
- ActiveSupport.on_load(:action_controller) do
20
- append_view_path Lite::Component.path
21
- end
22
11
  end
23
12
 
24
13
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Component
5
+ class Iteration
6
+
7
+ attr_reader :index, :size
8
+
9
+ def initialize(size, index)
10
+ @size = size
11
+ @index = index
12
+ end
13
+
14
+ def first?
15
+ index.zero?
16
+ end
17
+
18
+ def last?
19
+ index == (size - 1)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Component
5
+ class Locals
6
+
7
+ attr_reader :locals
8
+
9
+ def initialize(locals)
10
+ @locals = (locals || {}).symbolize_keys
11
+ end
12
+
13
+ private
14
+
15
+ def method_missing(method_name, *arguments, &block)
16
+ if locals.key?(method_name)
17
+ locals[method_name]
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ def respond_to_missing?(method_name, include_private = false)
24
+ locals.key?(method_name) || super
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Component
5
5
 
6
- VERSION ||= '1.0.1'
6
+ VERSION ||= '1.0.2'
7
7
 
8
8
  end
9
9
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- %w[version errors application engine element base].each do |filename|
3
+ %w[version engine iteration collection locals base].each do |filename|
4
4
  require "lite/component/#{filename}"
5
5
  end
6
6
 
7
- require 'generators/component_generator'
7
+ require 'generators/rails/component_generator'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-component
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-13 00:00:00.000000000 Z
11
+ date: 2019-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -159,20 +159,19 @@ files:
159
159
  - app/helpers/lite/component/component_helper.rb
160
160
  - bin/console
161
161
  - bin/setup
162
- - lib/generators/component_generator.rb
163
- - lib/generators/templates/install.js
164
- - lib/generators/templates/install.rb.erb
165
- - lib/generators/templates/install.scss
162
+ - lib/generators/rails/USAGE
163
+ - lib/generators/rails/component_generator.rb
164
+ - lib/generators/rails/templates/install.js
165
+ - lib/generators/rails/templates/install.rb.erb
166
+ - lib/generators/rails/templates/install.scss
166
167
  - lib/lite/component.rb
167
- - lib/lite/component/application.rb
168
168
  - lib/lite/component/base.rb
169
- - lib/lite/component/element.rb
169
+ - lib/lite/component/collection.rb
170
170
  - lib/lite/component/engine.rb
171
- - lib/lite/component/errors.rb
171
+ - lib/lite/component/iteration.rb
172
+ - lib/lite/component/locals.rb
172
173
  - lib/lite/component/version.rb
173
174
  - lite-component.gemspec
174
- - vendor/assets/javascripts/lite-component.js.erb
175
- - vendor/assets/stylesheets/lite-component.css.erb
176
175
  homepage: http://drexed.github.io/lite-component
177
176
  licenses:
178
177
  - MIT
@@ -192,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
191
  - !ruby/object:Gem::Version
193
192
  version: '0'
194
193
  requirements: []
195
- rubygems_version: 3.0.6
194
+ rubygems_version: 3.1.1
196
195
  signing_key:
197
196
  specification_version: 4
198
197
  summary: Generate component from collections of data points
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
-
5
- class ComponentGenerator < Rails::Generators::NamedBase
6
-
7
- class_option :skip_erb, type: :boolean, default: false
8
- class_option :skip_css, type: :boolean, default: false
9
- class_option :skip_js, type: :boolean, default: false
10
-
11
- source_root File.expand_path('../templates', __FILE__)
12
-
13
- def create_component_file
14
- template('install.rb.erb', "app/components/#{name}_component.rb")
15
- end
16
-
17
- def create_erb_file
18
- return if options['skip_erb']
19
-
20
- name_parts = name.split('/')
21
- file_parts = name_parts[0..-2]
22
- file_parts << "_#{name_parts.last}.html.erb"
23
-
24
- create_file("app/views/components/#{file_parts.join('/')}")
25
- end
26
-
27
- def copy_javascript_file
28
- return if options['skip_js']
29
-
30
- copy_file('install.js', "app/assets/javascripts/components/#{name}.js")
31
- end
32
-
33
- def copy_stylesheet_file
34
- return if options['skip_css']
35
-
36
- copy_file('install.scss', "app/assets/stylesheets/components/#{name}.scss")
37
- end
38
-
39
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lite
4
- module Component
5
-
6
- def self.names
7
- components_ext = '_component.rb'
8
- components_dir = "#{path}/"
9
- components_glob = path.join("**/*#{components_ext}")
10
-
11
- Dir.glob(components_glob).map { |name| name.sub(components_dir, '').chomp(components_ext) }
12
- end
13
-
14
- def self.path
15
- Rails.root.join('app/components')
16
- end
17
-
18
- end
19
- end
@@ -1,124 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'action_view'
4
-
5
- module Lite
6
- module Component
7
- class Element
8
-
9
- include ActiveModel::Validations
10
- include ActionView::Context
11
- include ActionView::Helpers
12
-
13
- attr_reader :context
14
-
15
- def initialize(context, attributes = nil, &block)
16
- initialize_attributes(attributes || {})
17
- initialize_elements
18
-
19
- @context = context
20
- @yield = block_given? ? @context.capture(self, &block) : nil
21
-
22
- validate!
23
- rescue ActiveModel::ValidationError => e
24
- raise Lite::Component::ValidationError, e.message
25
- end
26
-
27
- class << self
28
-
29
- def attribute(name, default: nil)
30
- attributes[name] = { default: default }
31
- define_method_or_raise(name) { get_instance_variable(name) }
32
- end
33
-
34
- def attributes
35
- @attributes ||= {}
36
- end
37
-
38
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
39
- # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
40
- def element(name, multiple: false, &config)
41
- plural_name = name.to_s.pluralize.to_sym if multiple
42
-
43
- elements[name] = {
44
- multiple: plural_name || false,
45
- class: Class.new(Element, &config)
46
- }
47
-
48
- define_method_or_raise(name) do |attributes = nil, &block|
49
- return get_instance_variable(multiple ? plural_name : name) unless attributes || block
50
-
51
- element = self.class.elements[name][:class].new(context, attributes, &block)
52
-
53
- if multiple
54
- get_instance_variable(plural_name) << element
55
- else
56
- set_instance_variable(name, element)
57
- end
58
- end
59
-
60
- return if !multiple || name == plural_name
61
-
62
- define_method_or_raise(plural_name) { get_instance_variable(plural_name) }
63
- end
64
- # rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
65
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
66
-
67
- def elements
68
- @elements ||= {}
69
- end
70
-
71
- def model_name
72
- ActiveModel::Name.new(Lite::Component::Element)
73
- end
74
-
75
- private
76
-
77
- def define_method_or_raise(method_name, &block)
78
- return define_method(method_name, &block) unless method_defined?(method_name.to_sym)
79
-
80
- raise Lite::Component::BuildError, "Method #{method_name.inspect} already exists"
81
- end
82
-
83
- end
84
-
85
- def to_s
86
- @yield
87
- end
88
-
89
- alias render to_s
90
-
91
- protected
92
-
93
- def initialize_attributes(attributes)
94
- self.class.attributes.each do |name, options|
95
- set_instance_variable(
96
- name,
97
- attributes[name] || (options[:default] && options[:default].dup)
98
- )
99
- end
100
- end
101
-
102
- def initialize_elements
103
- self.class.elements.each do |name, options|
104
- if (plural_name = options[:multiple])
105
- set_instance_variable(plural_name, [])
106
- else
107
- set_instance_variable(name, nil)
108
- end
109
- end
110
- end
111
-
112
- private
113
-
114
- def get_instance_variable(name)
115
- instance_variable_get(:"@#{name}")
116
- end
117
-
118
- def set_instance_variable(name, value)
119
- instance_variable_set(:"@#{name}", value)
120
- end
121
-
122
- end
123
- end
124
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lite
4
- module Component
5
-
6
- class BuildError < StandardError; end
7
- class ValidationError < StandardError; end
8
-
9
- end
10
- end
@@ -1,7 +0,0 @@
1
- <% Lite::Component.names.each do |name| %>
2
- <% begin %>
3
- <% require_asset("components/#{name}") %>
4
- <% rescue Sprockets::FileNotFound %>
5
- <%# Do nothing %>
6
- <% end %>
7
- <% end %>
@@ -1,7 +0,0 @@
1
- <% Lite::Component.names.each do |name| %>
2
- <% begin %>
3
- <% require_asset("components/#{name}") %>
4
- <% rescue Sprockets::FileNotFound %>
5
- <%# Do nothing %>
6
- <% end %>
7
- <% end %>