erb_component 0.1.5 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e48ccbfc0ce46abcce8ecedab8dd8b56e64254b242ba52e919429c4aba0e362
4
- data.tar.gz: c976659b689ad129f06160d1423af4f4ad168209af878c81cf647f4c0257b9b8
3
+ metadata.gz: 5de384cea9f470c6f868504164cac3c5f3699e7abb745834510770958463fde8
4
+ data.tar.gz: 59b2b4bcaed9977ddd6b37a7666cc6ccc6ce7119d2a1a6eea34ef0032842b59f
5
5
  SHA512:
6
- metadata.gz: df51f06dd8f67c0dbeacbee4267de9107268b29b4b7bfbedaae273774924940d5c3f5de767e8c31e9fa2f6157a0d5dae80e363ca9cabaff62dbeaabbc233b190
7
- data.tar.gz: 0b54f5577b6ee16e915dd33cd0931d950bd8726a59091c0e2dc471cc327b3af4df4eb3f88fe968a6ad61c32ca9467e4b7dabbd492f3a9c93255d74ca185d03d9
6
+ metadata.gz: 0d34289d0b204ba847d9bbdd6467d1dd7fcc10d923703ba8a8d7252718d2093ced3b002888da2f71b45c739842c1d16d55e8bc94accccd49b31a2fd788c1995b
7
+ data.tar.gz: 69c1cc17b40e3b38e4d58733e6b1e5971953166d50d47446152f3d23375f1b93ab825f4274258d57b95bd4b41407cde9aaa74a02b021f1c7eaa6c842cc63a3e2
data/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ * text=auto eol=lf
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+
10
+ .idea
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile CHANGED
File without changes
data/Gemfile.lock ADDED
@@ -0,0 +1,74 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ erb_component (0.2.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actionview (6.1.3.2)
10
+ activesupport (= 6.1.3.2)
11
+ builder (~> 3.1)
12
+ erubi (~> 1.4)
13
+ rails-dom-testing (~> 2.0)
14
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
15
+ activesupport (6.1.3.2)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ builder (3.2.4)
22
+ coderay (1.1.3)
23
+ concurrent-ruby (1.1.8)
24
+ crass (1.0.6)
25
+ diff-lcs (1.4.4)
26
+ erubi (1.10.0)
27
+ i18n (1.8.10)
28
+ concurrent-ruby (~> 1.0)
29
+ loofah (2.9.1)
30
+ crass (~> 1.0.2)
31
+ nokogiri (>= 1.5.9)
32
+ method_source (1.0.0)
33
+ minitest (5.14.4)
34
+ nokogiri (1.11.4-x86_64-linux)
35
+ racc (~> 1.4)
36
+ pry (0.14.1)
37
+ coderay (~> 1.1)
38
+ method_source (~> 1.0)
39
+ racc (1.5.2)
40
+ rails-dom-testing (2.0.3)
41
+ activesupport (>= 4.2.0)
42
+ nokogiri (>= 1.6)
43
+ rails-html-sanitizer (1.3.0)
44
+ loofah (~> 2.3)
45
+ rake (12.3.3)
46
+ rspec (3.10.0)
47
+ rspec-core (~> 3.10.0)
48
+ rspec-expectations (~> 3.10.0)
49
+ rspec-mocks (~> 3.10.0)
50
+ rspec-core (3.10.1)
51
+ rspec-support (~> 3.10.0)
52
+ rspec-expectations (3.10.1)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.10.0)
55
+ rspec-mocks (3.10.2)
56
+ diff-lcs (>= 1.2.0, < 2.0)
57
+ rspec-support (~> 3.10.0)
58
+ rspec-support (3.10.2)
59
+ tzinfo (2.0.4)
60
+ concurrent-ruby (~> 1.0)
61
+ zeitwerk (2.4.2)
62
+
63
+ PLATFORMS
64
+ x86_64-linux
65
+
66
+ DEPENDENCIES
67
+ actionview
68
+ erb_component!
69
+ pry (~> 0.14)
70
+ rake (~> 12.0)
71
+ rspec (~> 3.5)
72
+
73
+ BUNDLED WITH
74
+ 2.2.3
data/LICENSE.txt CHANGED
File without changes
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # ErbComponent
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/erb_component`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Why not have view components and write them in OOP style? It hides complexity. DRYes views.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ **FEEL FREE TO OPEN AN ISSUE OR HAVE SOME DISCUSSION**.
6
+
7
+ **USE WITH CAUTION!** This is more like an experiment.
6
8
 
7
9
  ## Installation
8
10
 
@@ -22,17 +24,132 @@ Or install it yourself as:
22
24
 
23
25
  ## Usage
24
26
 
25
- TODO: Write usage instructions here
27
+ ### Easiest example
28
+
29
+ It's important to define `template` method
30
+ ```ruby
31
+ class ImgTag < ErbComponent
32
+ attr_reader :src
33
+
34
+ # req is Rack::Request or ActionDispatch::Request (for Rails)
35
+ def initialize(req, opts)
36
+ @src = opts[:src]
37
+ super
38
+ end
39
+
40
+ def template
41
+ <<ERB
42
+ <img src="<%= src %>" />
43
+ ERB
44
+ end
45
+ end
46
+
47
+ # Somewhere in views:
48
+ url = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Ruby_logo.svg/1920px-Ruby_logo.svg.png"
49
+ ImgTag.(request, src: url) # or ImgTag.new(request, src: url).call
50
+ # => "<img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Ruby_logo.svg/1920px-Ruby_logo.svg.png\" />\n"
51
+ ```
52
+
53
+ ### You can use more elegant Rails content_tag
26
54
 
27
- ## Development
55
+ ```ruby
56
+ class ImgContentTag < ErbComponent
57
+ attr_reader :src
58
+
59
+ def initialize(req, opts)
60
+ @src = opts[:src]
61
+ super
62
+ end
63
+
64
+ def template
65
+ content_tag :img, nil, src: src
66
+ end
67
+ end
68
+ ```
69
+
70
+ ### More advanced nested example
28
71
 
29
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
72
+ Here `TabNavs.(request, tab_list: %w(overview photos contact accommodations))` will generate Bootstrap's tab navigation, like here: https://getbootstrap.com/docs/5.0/components/navs-tabs/
73
+ ```ruby
74
+ class TabNavs < ErbComponent
75
+ attr_reader :tab_list
76
+
77
+ def initialize(req, tab_list:)
78
+ @tab_list = tab_list
79
+ super
80
+ end
81
+
82
+ def template
83
+ <<ERB
84
+ <ul class="nav nav-tabs" id="myTab" role="tablist">
85
+ <%= tab_list_rendered %>
86
+ </ul>
87
+ ERB
88
+ end
89
+
90
+ def tab_list_rendered
91
+ active_found = false
92
+ opts = tab_list.map do |i|
93
+ if params[:active_tab] == i
94
+ active_found = true
95
+ {target: i, active: true}
96
+ else
97
+ {target: i, active: false}
98
+ end
99
+ end
100
+
101
+ opts[0][:active] = true unless active_found
102
+
103
+ opts.map do |i|
104
+ NavItem.(req, **i)
105
+ end.join("\n")
106
+ end
107
+ end
108
+
109
+ class NavItem < ErbComponent
110
+ attr_reader :target
111
+
112
+ def initialize(req_params, active: false, target:)
113
+ @req_params = req_params
114
+ @active = active
115
+ @target = target
116
+ super
117
+ end
118
+
119
+ def template
120
+ <<ERB
121
+ <li class="nav-item" role="presentation">
122
+ <button class="<%= button_class %>" id="<%= id %>" data-bs-toggle="tab" data-bs-target="#<%= target %>" type="button" role="tab" aria-controls="<%= target %>" aria-selected="true">
123
+ <%= tab_name %>
124
+ </button>
125
+ </li>
126
+ ERB
127
+ end
128
+
129
+ def id
130
+ "#{target}-tab"
131
+ end
132
+
133
+ def tab_name
134
+ target.humanize
135
+ end
136
+
137
+ def button_class
138
+ res = "nav-link"
139
+ res += " active" if active?
140
+ res
141
+ end
142
+
143
+ def active?
144
+ @active
145
+ end
146
+ end
147
+ ```
30
148
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
149
 
33
150
  ## Contributing
34
151
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/erb_component.
152
+ Bug reports and pull requests are welcome on GitHub at https://github.com/arthurkarganyan/erb_component.
36
153
 
37
154
 
38
155
  ## License
data/Rakefile CHANGED
File without changes
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "lib/erb_component/version"
2
4
 
3
5
  Gem::Specification.new do |spec|
@@ -22,7 +24,8 @@ Gem::Specification.new do |spec|
22
24
  spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
23
25
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
26
  end
25
- spec.bindir = "exe"
26
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.add_development_dependency "rspec", "~> 3.5"
28
+ spec.add_development_dependency "pry", "~> 0.14"
29
+ spec.add_development_dependency "actionview"
27
30
  spec.require_paths = ["lib"]
28
31
  end
data/lib/erb_component.rb CHANGED
@@ -1,3 +1,2 @@
1
1
  require "erb_component/version"
2
-
3
- autoload :ErbComponent, "erb_component/erb_component"
2
+ require "erb_component/erb_component"
@@ -1,63 +1,67 @@
1
1
  require "erb_component/version"
2
+ require "erb_component/req_tools"
2
3
  require 'erb'
3
4
 
4
5
  class ErbComponent
6
+ include ReqTools
7
+ if defined? ActionView::Helpers::TagHelper
8
+ include ActionView::Helpers::TagHelper
9
+ end
10
+
5
11
  class Error < StandardError;
6
12
  end
7
13
 
8
14
  attr_reader :req, :parent
9
15
 
10
- def initialize(req)
16
+ def initialize(req, opts = {})
11
17
  @req = req
12
- @parent = self.class.superclass == ErbComponent ? nil : self.class.superclass.new(req)
18
+ @template = opts[:template]
19
+ begin
20
+ @parent = self.class.superclass == ErbComponent ? nil : self.class.superclass.new(req)
21
+ if @parent && !(parent.template['{{VIEW}}'] || parent.template['{{view}}'])
22
+ @parent = parent.parent
23
+ end
24
+ rescue ArgumentError
25
+ end
13
26
  end
14
27
 
15
- def path
16
- @req.path
28
+ def render
29
+ str = ERB.new(template).result(binding)
30
+ res = if parent
31
+ parent.render.gsub("{{VIEW}}", str).gsub("{{view}}", str)
32
+ else
33
+ str
34
+ end
35
+ if res.respond_to? :html_safe
36
+ res.html_safe
37
+ else
38
+ res
39
+ end
17
40
  end
18
41
 
19
- def params
20
- @req.params
42
+ def self.call(req, opts = {})
43
+ new(req, **opts).render
21
44
  end
22
45
 
23
- def render
24
- str = ERB.new(template).result(binding)
25
- parent ? parent.render.gsub("{{VIEW}}", str).gsub("{{view}}", str) : str
46
+ def call
47
+ self.render
48
+ end
49
+
50
+ def self.current_file=(file)
51
+ @current_file = file
26
52
  end
27
53
 
28
- def self.render(opts = {})
29
- new(opts).render
54
+ def self.current_file
55
+ @current_file
30
56
  end
31
57
 
32
58
  def template_file_path
33
- @template_file_path ||= begin
34
- file_name = "#{self.class.name.underscore}.erb"
35
- if File.exists? "components/#{file_name}"
36
- return "components/#{file_name}"
37
- elsif File.exists? "pages/#{file_name}"
38
- return "pages/#{file_name}"
39
- else
40
- nil
41
- end
42
- end
59
+ self.class.current_file.gsub('.rb', '.erb')
43
60
  end
44
61
 
45
62
  def template
46
- if template_file_path
47
- File.read template_file_path
48
- end
63
+ return @template if @template
64
+ return File.read(template_file_path) if template_file_path
49
65
  fail "not found: #{template_file_path}"
50
66
  end
51
-
52
- def method_missing(m, *args, &block)
53
- m = m.to_s
54
- str = Kernel.const_defined?("#{self.class}::#{m}") ? "#{self.class}::#{m}" : m
55
- clazz = Kernel.const_get(str)
56
- opts = {path: path, params: params}
57
- opts.merge!(args[0]) if args.size > 0
58
- component = clazz.new(opts)
59
- component.render
60
- rescue
61
- super
62
- end
63
67
  end
@@ -0,0 +1,50 @@
1
+ module ReqTools
2
+ def path
3
+ @req.path
4
+ end
5
+
6
+ def path_hash
7
+ @path_hash ||= begin
8
+ split = path.split('/')
9
+ split.shift
10
+
11
+ res = {}
12
+ split.size.times do |i|
13
+ if split[i].to_i.to_s == split[i]
14
+ res[split[i - 1].singularize + "_id"] = split[i]
15
+ end
16
+ end
17
+ if res.respond_to? :with_indifferent_access
18
+ res.with_indifferent_access
19
+ else
20
+ res
21
+ end
22
+ end
23
+ end
24
+
25
+ def params
26
+ @params ||= begin
27
+ res = @req.params
28
+ res.merge!(JSON.parse(req.body.read)) if req.post? || req.put? || req.patch?
29
+ res.merge!(path_hash)
30
+ if res.respond_to? :with_indifferent_access
31
+ res.with_indifferent_access
32
+ else
33
+ res
34
+ end
35
+ end
36
+ end
37
+
38
+ def method_missing(m, *args, &block)
39
+ return super unless m.to_s[0].upcase == m.to_s[0]
40
+ m = m.to_s
41
+ str = Kernel.const_defined?("#{self.class}::#{m}") ? "#{self.class}::#{m}" : m
42
+ clazz = Kernel.const_get(str)
43
+ if args.size > 0
44
+ component = clazz.new(req, *args)
45
+ else
46
+ component = clazz.new(req)
47
+ end
48
+ component.render
49
+ end
50
+ end
@@ -1,3 +1,3 @@
1
1
  class ErbComponent
2
- VERSION = "0.1.5"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,15 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erb_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arthur Karganyan
8
- autorequire:
9
- bindir: exe
8
+ autorequire:
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-20 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-05-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: actionview
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'
13
55
  description: React-style front-end components but for ERB?
14
56
  email:
15
57
  - arthur.karganyan@gmail.com
@@ -17,15 +59,18 @@ executables: []
17
59
  extensions: []
18
60
  extra_rdoc_files: []
19
61
  files:
62
+ - ".gitattributes"
20
63
  - ".gitignore"
64
+ - ".rspec"
21
65
  - Gemfile
66
+ - Gemfile.lock
22
67
  - LICENSE.txt
23
68
  - README.md
24
69
  - Rakefile
25
- - bin/erb_component
26
70
  - erb_component.gemspec
27
71
  - lib/erb_component.rb
28
72
  - lib/erb_component/erb_component.rb
73
+ - lib/erb_component/req_tools.rb
29
74
  - lib/erb_component/version.rb
30
75
  homepage: https://github.com/arthurkarganyan/erb_component
31
76
  licenses:
@@ -34,7 +79,7 @@ metadata:
34
79
  allowed_push_host: https://rubygems.org
35
80
  homepage_uri: https://github.com/arthurkarganyan/erb_component
36
81
  source_code_uri: https://github.com/arthurkarganyan/erb_component
37
- post_install_message:
82
+ post_install_message:
38
83
  rdoc_options: []
39
84
  require_paths:
40
85
  - lib
@@ -49,9 +94,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
94
  - !ruby/object:Gem::Version
50
95
  version: '0'
51
96
  requirements: []
52
- rubyforge_project:
53
- rubygems_version: 2.7.6
54
- signing_key:
97
+ rubygems_version: 3.2.3
98
+ signing_key:
55
99
  specification_version: 4
56
100
  summary: React-style front-end components but for ERB?
57
101
  test_files: []
data/bin/erb_component DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "erb_component"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)