rux-rails 1.4.0 → 2.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 +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/Gemfile +4 -4
  4. data/README.md +59 -5
  5. data/lib/rux-rails/engine.rb +46 -0
  6. data/lib/rux-rails/output_buffer.rb +13 -0
  7. data/lib/rux-rails/rux_loader.rb +7 -0
  8. data/lib/rux-rails/tag_builder.rb +2 -2
  9. data/lib/rux-rails/tasks/transpile.rake +11 -10
  10. data/lib/rux-rails/version.rb +1 -1
  11. data/lib/rux-rails.rb +7 -12
  12. data/rux-rails.gemspec +4 -2
  13. data/spec/components/rails/button_spec.rb +18 -0
  14. data/spec/components/rails/button_to_spec.rb +24 -0
  15. data/spec/components/rails/content_tag_spec.rb +13 -0
  16. data/spec/components/rails/form_with_spec.rb +20 -0
  17. data/spec/components/rails/hidden_field_spec.rb +11 -0
  18. data/spec/components/rails/label_spec.rb +21 -0
  19. data/spec/components/rails/link_to_spec.rb +16 -0
  20. data/spec/components/rails/password_field_spec.rb +11 -0
  21. data/spec/components/rails/text_field_spec.rb +11 -0
  22. data/spec/components/rux/component_spec.rb +9 -0
  23. data/spec/controllers/home_controller_spec.rb +37 -1
  24. data/spec/dummy/app/components/html_safety_component.rb +13 -0
  25. data/spec/dummy/app/components/html_safety_component.rux +9 -0
  26. data/spec/dummy/app/components/image.rux +16 -0
  27. data/spec/dummy/config/application.rb +4 -0
  28. data/spec/dummy/log/test.log +792 -131
  29. data/spec/dummy/tmp/local_secret.txt +1 -0
  30. data/spec/html_safety_spec.rb +10 -0
  31. data/spec/spec_helper.rb +28 -10
  32. metadata +56 -23
  33. data/lib/rux-rails/components/audio.rb +0 -18
  34. data/lib/rux-rails/components/image.rb +0 -18
  35. data/lib/rux-rails/components/video.rb +0 -18
  36. data/lib/rux-rails/components.rb +0 -5
  37. data/lib/rux-rails/core_ext/kernel.rb +0 -67
  38. data/lib/rux-rails/core_ext/kernel_zeitwerk.rb +0 -63
  39. data/lib/rux-rails/ext/activesupport/dependencies.rb +0 -47
  40. data/lib/rux-rails/ext/bootsnap/autoload.rb +0 -27
  41. data/lib/rux-rails/ext/zeitwerk/loader.rb +0 -35
  42. data/lib/rux-rails/railtie.rb +0 -64
  43. data/lib/rux-rails/safe_buffer.rb +0 -13
  44. data/spec/dummy/app/components/button.rb +0 -15
  45. data/spec/dummy/app/components/home_component.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80c3381d7ae7854540067cd7267c5636961a7b30a538fad7c5fd063c5cb12a64
4
- data.tar.gz: c4234d93e5b93109b612a5249f06b065cc53157999246cc04f12aea1bdc98cad
3
+ metadata.gz: 1dd540a2fa0ae930bc671d469c20928dc71faba5ad1ef3d52a13212f1e6373ef
4
+ data.tar.gz: 6f8d5e0c2897d8c03c4bdea2b6fec7c170a1103c9ca2ef5a58edf07396c98328
5
5
  SHA512:
6
- metadata.gz: 8b61ed880646e3a058c4bd525f6f7fe9e308fe066f40d76c53ea312a5c604874eb321405f9d41f3a026221df3a83b3049356c1146f897ca7c9c4cf96b5274443
7
- data.tar.gz: 6aa7c072623ab565de33479b0428c096412377f9cf020c0c91751cf9b80e2f21fad1c2f8500a95b2b67dd5450a985ef8a5d0162ac72978d6cd1de04d706b64dc
6
+ metadata.gz: 694511000ee0f54d57a382d18986d50130811e2c74d3f5f8b4963f7e9472b4629174a893d659fe42b9e03fa6f683f3b1e9e0ffad9714411c34d2de9a13d61949
7
+ data.tar.gz: 859fcf4b865afe9cd22f77d990263ac495acb275dccd21d487c0d01bf047b5ae0ab616ba57e61426c2d67d8eb8eebeadf90fea78048e7672e92376ba38849934
data/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 2.0.0
2
+ * Remove the `Image`, `Audio`, and `Video` components (was anyone actually using these?)
3
+ * Remove support for Rails 6.1 and 6.0.
4
+ * Upgrade to onload v1.1 and rux to v1.3.
5
+ - Add `config.rux.ignore_path` to Rails config for controlling which ignore file should be populated with generated paths.
6
+ * Add a series of Rails helper components:
7
+ - `Rails::ButtonTo`
8
+ - `Rails::LinkTo`
9
+ - `Rails::ContentTag`
10
+ - `Rails::FormWith`
11
+ - `Rails::Label`
12
+ - `Rails::Button`
13
+ - `Rails::HiddenField`
14
+ - `Rails::PasswordField`
15
+ - `Rails::TextField`
16
+ * Add the `Rux::Component` component for rendering component instances.
17
+ - Eg: `<Rux::Component instance={@child} />`.
18
+
19
+ ## 1.5.0
20
+ * Extract monkeypatches into the [onload gem](https://github.com/camertron/onload).
21
+ * Upgrade to rux v1.2.
22
+ * Drop official support for Rails < 6 and Ruby < 3.
23
+
1
24
  ## 1.4.0
2
25
  * Make rux-rails safe to load in production.
3
26
  - All the monkeypatches to `Kernel`, etc are now only loaded if `config.rux.transpile` is `true`.
data/Gemfile CHANGED
@@ -2,21 +2,21 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rux', github: 'camertron/rux' # path: '/Users/cdutro/workspace/rux'
6
-
7
5
  group :development, :test do
8
- gem 'pry-byebug'
9
6
  gem 'rake'
7
+ gem 'debug'
10
8
  end
11
9
 
12
10
  group :development do
13
11
  gem 'appraisal'
14
12
  gem 'benchmark-ips'
15
- gem 'rails', '~> 7.0'
16
13
  gem 'slim', '~> 5.0'
14
+ gem 'appraisal-run', '~> 1.0'
17
15
  end
18
16
 
19
17
  group :test do
20
18
  gem 'rspec-rails'
21
19
  gem 'capybara', '~> 3.0'
22
20
  end
21
+
22
+ gem "csv"
data/README.md CHANGED
@@ -81,11 +81,9 @@ In my humble opinion, the rux version:
81
81
 
82
82
  Integrating rux into your Rails app is pretty straightforward.
83
83
 
84
- 1. Add rux-rails to the development group in your Gemfile, eg:
84
+ 1. Add rux-rails to your Gemfile, eg:
85
85
  ```ruby
86
- group :development do
87
- gem 'rux-rails', '~> 1.0'
88
- end
86
+ gem 'rux-rails', '~> 1.0'
89
87
  ```
90
88
  1. Run `bundle install`
91
89
  1. ... that's it.
@@ -104,7 +102,7 @@ config.rux.transpile = false
104
102
 
105
103
  ### Production Environment
106
104
 
107
- By including rux-rails in the `:development` group in your Gemfile, rux-rails and its monkeypatches to `Kernel` aren't loaded in production (which is a good thing). You could choose to include rux-rails in the default group, but automatic transpilation of .rux files is disabled in the production environment for the same reasons the asset pipeline is disabled. Your view components (and static assets) don't change once deployed, so it's more efficient to precompile (or pre-transpile) them before deploying. Rux-rails comes with a handy rake task that can pre-transpile all your .rux templates:
105
+ By default, `config.rux.transpile` is set to `false` in the production environment, which means rux-rails' monkeypatches to `Kernel`, etc aren't loaded in production (which is a good thing). You could choose to turn it on, but automatic transpilation of .rux files is disabled automatically in the production environment for the same reasons the asset pipeline is disabled. Your view components (and static assets) don't change once deployed, so it's more efficient to precompile (or pre-transpile) them before deploying. Rux-rails comes with a handy rake task that can pre-transpile all your .rux templates:
108
106
 
109
107
  ```bash
110
108
  bundle exec rake rux:transpile
@@ -284,6 +282,62 @@ There are also monkeypatches in place for Zeitwerk and `ActiveSupport::Dependenc
284
282
 
285
283
  Hit me up if you know of a less invasive way of enabling auto-transpilation.
286
284
 
285
+ ## Built-in Components
286
+
287
+ The rux-rails gem contains several helper components to make it easier to work with Rails forms and tag helpers. Only a subset of Rails helpers are implemented. If you need others, please open an issue or, better yet, submit a pull request.
288
+
289
+ ### Tag Helpers
290
+
291
+ The following tag helpers are available as components:
292
+
293
+ 1. `button_to`: Use the `Rails::ButtonTo` component, eg: `<Rails::ButtonTo url: "http://example.com" label: "Click me" />`.
294
+ 1. `link_to`: Use the `Rails::LinkTo` component, eg: `<Rails::LinkTo url="http://example.com" label="Navigate" />`.
295
+ 1. `content_tag`: Use the `Rails::ContentTag` component, eg: `<Rails::ContentTag tag={:div}>content</Rails::ContentTag>`
296
+
297
+ ### Form Helpers
298
+
299
+ 1. `form_with`: `Rails::FormWith`
300
+ 1. `button_tag` or `f.submit`: `Rails::Button`
301
+ 1. `label_tag` or `f.label`: `Rails::Label`
302
+ 1. `text_field_tag` or `f.text_field`: `Rails::TextField`
303
+ 1. `password_field_tag` or `f.password_field`: `Rails::PasswordField`
304
+ 1. `hidden_field_tag` or `f.hidden_field`: `Rails::HiddenField`
305
+
306
+ ### Form Example
307
+
308
+ Here's how to use the above components to build eg. a simple sign up form:
309
+
310
+ ```ruby
311
+ <Rails::FormWith model={User.new}>
312
+ <Rails::Label name="name">Name</Rails::Label>
313
+ <Rails::TextField name="name" />
314
+ <Rails::Label name="email_address">Email address</Rails::Label>
315
+ <Rails::TextField name="email_address" />
316
+ <Rails::Label name="password">Password</Rails::Label>
317
+ <Rails::PasswordField name="password" />
318
+ <Rails::Label name="password_confirm">Confirm password</Rails::Label>
319
+ <Rails::PasswordField name="password_confirmation" />
320
+ </Rails::FormWith>
321
+ ```
322
+
323
+ ### The `Component` component
324
+
325
+ Occasionally it can be useful to create an instance of a component outside the `call` method. While such a component can be rendered via the `render` method, doing so doesn't feel very "ruxy." That's where the `Rux::Component` component comes into play. It accepts a single `instance:` argument and renders it. For example:
326
+
327
+ ```ruby
328
+ class ParentComponent < ApplicationComponent
329
+ def initialize
330
+ @child = ChildComponent.new
331
+ end
332
+
333
+ def call
334
+ <div>
335
+ <Rux::Component instance={@child} />
336
+ </div>
337
+ end
338
+ end
339
+ ```
340
+
287
341
  ## Editor Support
288
342
 
289
343
  Sublime Text: [https://github.com/camertron/rux-SublimeText](https://github.com/camertron/rux-SublimeText)
@@ -0,0 +1,46 @@
1
+ require 'onload'
2
+
3
+ module RuxRails
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace RuxRails
6
+
7
+ config.rux = ActiveSupport::OrderedOptions.new
8
+
9
+ initializer 'rux-rails.initialize', before: 'onload.initialize' do |app|
10
+ if config.rux.transpile.nil? && (Rails.env.development? || Rails.env.test?)
11
+ config.rux.transpile = true
12
+ Onload.enabled = true
13
+ else
14
+ Onload.enabled = config.rux.transpile
15
+ end
16
+
17
+ if config.rux.transpile
18
+ Onload.register('.rux', RuxRails::RuxLoader)
19
+ end
20
+
21
+ ActionView::Template.register_template_handler(
22
+ :ruxt, RuxRails::TemplateHandler
23
+ )
24
+
25
+ Rux.library_paths.each do |library_path|
26
+ app.config.eager_load_paths << library_path
27
+ app.config.autoload_paths << library_path
28
+ end
29
+ end
30
+
31
+ config.after_initialize do
32
+ ignore_path = config.rux.ignore_path || Onload.config.ignore_path
33
+
34
+ if ignore_path.nil? && Rails.root.join(".gitignore").exist?
35
+ ignore_path = Rails.root.join(".gitignore").to_s
36
+ end
37
+
38
+ Onload.config.ignore_path = ignore_path
39
+ config.rux.ignore_path = ignore_path
40
+ end
41
+
42
+ rake_tasks do
43
+ load File.expand_path(File.join(*%w(. tasks transpile.rake)), __dir__)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ require 'action_view'
2
+
3
+ module RuxRails
4
+ class OutputBuffer < ActionView::OutputBuffer
5
+ def safe_append(obj)
6
+ Array(obj).each { |o| self.safe_append=(o) }
7
+ end
8
+
9
+ def append(obj)
10
+ Array(obj).each { |o| self.append=(o) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module RuxRails
2
+ class RuxLoader
3
+ def self.call(source)
4
+ Rux.to_ruby(source)
5
+ end
6
+ end
7
+ end
@@ -2,8 +2,8 @@ require 'rux'
2
2
 
3
3
  module RuxRails
4
4
  class TagBuilder < ::Rux::DefaultTagBuilder
5
- def call(*args)
6
- super.html_safe
5
+ def call(*args, &block)
6
+ build(*args, &block).html_safe
7
7
  end
8
8
  end
9
9
  end
@@ -3,18 +3,19 @@ require 'set'
3
3
 
4
4
  namespace :rux do
5
5
  task transpile: :environment do
6
- config = Rails.application.config
7
- paths = Set.new(config.autoload_paths + config.eager_load_paths)
6
+ ignore_file = if Rails.application.config.rux.ignore_path
7
+ Onload::IgnoreFile.load(Rails.application.config.rux.ignore_path)
8
+ end
9
+
10
+ Dir.glob(Rails.root.join('**/*.rux')) do |file|
11
+ rux_file = Rux::File.new(file)
12
+ rux_file.write
8
13
 
9
- paths.each do |path|
10
- # Skip library paths. Libraries should ship with all their rux files
11
- # pre-transpiled.
12
- next if Rux.library_paths.include?(path)
14
+ puts "Wrote #{rux_file.default_outfile}"
13
15
 
14
- Dir.glob(File.join(path, '**/*.rux')).each do |file|
15
- Rux::File.new(file).write
16
- puts "Wrote #{file}"
17
- end
16
+ ignore_file&.add(rux_file.default_outfile)
18
17
  end
18
+
19
+ ignore_file&.persist!
19
20
  end
20
21
  end
@@ -1,3 +1,3 @@
1
1
  module RuxRails
2
- VERSION = '1.4.0'
2
+ VERSION = '2.0.0'
3
3
  end
data/lib/rux-rails.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  module RuxRails
2
2
  autoload :Components, 'rux-rails/components'
3
- autoload :SafeBuffer, 'rux-rails/safe_buffer'
3
+ autoload :OutputBuffer, 'rux-rails/output_buffer'
4
+ autoload :RuxLoader, 'rux-rails/rux_loader'
4
5
  autoload :TagBuilder, 'rux-rails/tag_builder'
5
6
  autoload :TemplateHandler, 'rux-rails/template_handler'
6
7
  autoload :Visitor, 'rux-rails/visitor'
@@ -16,23 +17,17 @@ module RuxRails
16
17
  def tag_builder
17
18
  @tag_builder ||= TagBuilder.new
18
19
  end
19
-
20
- def transpile_on_load?
21
- transpile_on_load.call
22
- end
23
20
  end
24
21
 
25
- self.transpile_on_load = -> () { true }
22
+ self.transpile_on_load = true
26
23
  end
27
24
 
28
25
 
29
26
  require 'rux'
30
- require 'rux-rails/railtie'
31
27
 
32
- # require both of these to support multiple versions of view_component
33
- require 'view_component'
34
- require 'view_component/engine'
28
+ if defined?(Rails)
29
+ require 'rux-rails/engine'
30
+ end
35
31
 
36
- ViewComponent::Base.send(:include, RuxRails::Components)
37
32
  Rux.tag_builder = RuxRails.tag_builder
38
- Rux.buffer = RuxRails::SafeBuffer
33
+ Rux.buffer = RuxRails::OutputBuffer
data/rux-rails.gemspec CHANGED
@@ -10,9 +10,11 @@ Gem::Specification.new do |s|
10
10
  s.description = s.summary = 'Rux view components on Rails.'
11
11
  s.platform = Gem::Platform::RUBY
12
12
 
13
- s.add_dependency 'rux', '~> 1.0'
13
+ s.add_dependency 'rux', '~> 1.3'
14
14
  s.add_dependency 'railties', '>= 5.0'
15
- s.add_dependency 'view_component', '>= 2', '< 4'
15
+ s.add_dependency 'view_component', '>= 2', '< 5'
16
+ s.add_dependency 'onload', '~> 1.1'
17
+ s.add_dependency 'use_context', '~> 1.2'
16
18
 
17
19
  s.require_path = 'lib'
18
20
 
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::Button, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(described_class.new)
6
+ expect(rendered_content).to eq("<button name=\"button\" type=\"submit\">Button</button>")
7
+ end
8
+
9
+ it 'renders with the given label' do
10
+ render_inline(described_class.new(label: "Click me"))
11
+ expect(rendered_content).to eq("<button name=\"button\" type=\"submit\">Click me</button>")
12
+ end
13
+
14
+ it 'renders with the given attributes' do
15
+ render_inline(described_class.new(disabled: true))
16
+ expect(rendered_content).to eq("<button name=\"button\" type=\"submit\" disabled=\"disabled\">Button</button>")
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::ButtonTo, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(described_class.new(url: "http://example.com"))
6
+ expect(rendered_content).to include(
7
+ /<form .* action=\"http:\/\/example.com".*<button type=\"submit\"><\/button>/
8
+ )
9
+ end
10
+
11
+ it 'renders with a label' do
12
+ render_inline(described_class.new(label: "Click me", url: "http://example.com"))
13
+ expect(rendered_content).to include(
14
+ /<form .* action=\"http:\/\/example.com".*<button type=\"submit\">Click me<\/button>/
15
+ )
16
+ end
17
+
18
+ it 'renders with the content as the label' do
19
+ render_inline(described_class.new(url: "http://example.com")) { "Click me" }
20
+ expect(rendered_content).to include(
21
+ /<form .* action=\"http:\/\/example.com".*<button type=\"submit\">Click me<\/button>/
22
+ )
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::ContentTag, type: :component do
4
+ it 'renders an empty tag by default' do
5
+ render_inline(described_class.new(tag: :div))
6
+ expect(rendered_content).to eq("<div></div>")
7
+ end
8
+
9
+ it 'renders content within the tags' do
10
+ render_inline(described_class.new(tag: :div)) { 'Hello, world' }
11
+ expect(rendered_content).to eq("<div>Hello, world</div>")
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::FormWith, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(described_class.new(url: "/foo"))
6
+ expect(rendered_content).to include("<form action=\"/foo\" accept-charset=\"UTF-8\" method=\"post\"><input type=\"hidden\" name=\"authenticity_token\"")
7
+ end
8
+
9
+ it 'adds the builder to the rux context' do
10
+ builder = nil
11
+
12
+ render_inline(described_class.new(url: "/foo")) do
13
+ UseContext.use_context(:rux, :form_builder) do |f|
14
+ builder = f
15
+ end
16
+ end
17
+
18
+ expect(builder).to be_a(ActionView::Helpers::FormBuilder)
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::HiddenField, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(Rails::FormWith.new(url: "/foo")) do
6
+ described_class.new(name: "bar").render_in(view_context)
7
+ end
8
+
9
+ expect(rendered_content).to include("<input autocomplete=\"off\" type=\"hidden\" name=\"bar\" id=\"bar\" />")
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::Label, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(Rails::FormWith.new(url: "/foo")) do
6
+ described_class.new(name: "bar").render_in(view_context)
7
+ end
8
+
9
+ expect(rendered_content).to include("<label for=\"bar\">Bar</label>")
10
+ end
11
+
12
+ it 'renders content within the tags' do
13
+ render_inline(Rails::FormWith.new(url: "/foo")) do
14
+ described_class.new(name: "bar").render_in(view_context) do
15
+ "Hello, world"
16
+ end
17
+ end
18
+
19
+ expect(rendered_content).to include("<label for=\"bar\">Hello, world</label>")
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::LinkTo, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(described_class.new(url: "http://example.com", label: "foo"))
6
+ expect(rendered_content).to eq("<a href=\"http://example.com\">foo</a>")
7
+ end
8
+
9
+ it 'renders the content between the tags' do
10
+ render_inline(described_class.new(url: "http://example.com")) do
11
+ "Hello, world"
12
+ end
13
+
14
+ expect(rendered_content).to eq("<a href=\"http://example.com\">Hello, world</a>")
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::PasswordField, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(Rails::FormWith.new(url: "/foo")) do
6
+ described_class.new(name: "bar").render_in(view_context)
7
+ end
8
+
9
+ expect(rendered_content).to include("<input type=\"password\" name=\"bar\" id=\"bar\" />")
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails::TextField, type: :component do
4
+ it 'renders with defaults' do
5
+ render_inline(Rails::FormWith.new(url: "/foo")) do
6
+ described_class.new(name: "bar").render_in(view_context)
7
+ end
8
+
9
+ expect(rendered_content).to include("<input type=\"text\" name=\"bar\" id=\"bar\" />")
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rux::Component, type: :component do
4
+ it 'renders the given instance' do
5
+ render_inline(Rux::Component.new(instance: Image.new(src: "foo.png")))
6
+
7
+ expect(rendered_content).to include("<img src=\"/images/foo.png\" />")
8
+ end
9
+ end
@@ -2,7 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  describe HomeController, type: :request do
4
4
  describe '#index' do
5
- it 'works' do
5
+ before(:each) do
6
+ # Force a recompile to avoid test pollution
7
+ HomeComponent.respond_to?(:__vc_compile) ? HomeComponent.__vc_compile : HomeComponent.compile
8
+ end
9
+
10
+ it 'transpiles the file' do
6
11
  get '/'
7
12
 
8
13
  expect(response).to have_http_status(:ok)
@@ -10,5 +15,36 @@ describe HomeController, type: :request do
10
15
  have_selector("div.container img[src='/images/cat.png'] + button", text: "Click Me!")
11
16
  )
12
17
  end
18
+
19
+ it "allows hot reloading" do
20
+ get "/"
21
+
22
+ expect(response).to have_http_status(:ok)
23
+ expect(response.body).to(
24
+ have_selector(".container", text: "Click Me!")
25
+ )
26
+
27
+ new_contents = <<~RUX
28
+ class HomeComponent < ViewComponent::Base
29
+ def call
30
+ <div class="container">
31
+ <Image src="cat.png" size="40" />
32
+ <Button outline={true} disabled size={:large}>
33
+ Click if you dare
34
+ </Button>
35
+ </div>
36
+ end
37
+ end
38
+ RUX
39
+
40
+ with_file_contents(Rails.root.join(*%w[app components home_component.rux]), new_contents) do
41
+ get "/"
42
+
43
+ expect(response).to have_http_status(:ok)
44
+ expect(response.body).to(
45
+ have_selector(".container", text: "Click if you dare")
46
+ )
47
+ end
48
+ end
13
49
  end
14
50
  end
@@ -0,0 +1,13 @@
1
+ class HtmlSafetyComponent < ViewComponent::Base
2
+ def initialize(value:)
3
+ @value = value
4
+ end
5
+
6
+ def call
7
+ Rux.tag("div") {
8
+ Rux.create_buffer.tap { |_rux_buf_|
9
+ _rux_buf_.append(@value)
10
+ }.to_s
11
+ }
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class HtmlSafetyComponent < ViewComponent::Base
2
+ def initialize(value:)
3
+ @value = value
4
+ end
5
+
6
+ def call
7
+ <div>{@value}</div>
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Image < ViewComponent::Base
4
+ include ActionView::Helpers::AssetUrlHelper
5
+
6
+ attr_reader :src, :params
7
+
8
+ def initialize(src:, **params)
9
+ @src = src
10
+ @params = params
11
+ end
12
+
13
+ def call
14
+ image_tag(src, **params)
15
+ end
16
+ end
@@ -1,3 +1,7 @@
1
+ # require both of these to support multiple versions of view_component
2
+ require 'view_component'
3
+ require 'view_component/engine'
4
+
1
5
  module RuxRails
2
6
  class DummyApplication < ::Rails::Application
3
7
  if config.respond_to?(:load_defaults)