Skip to content

Commit

Permalink
Merge pull request #277 from nashby/initialize-requirement
Browse files Browse the repository at this point in the history
Remove initializer requirement.
  • Loading branch information
joelhawksley authored Mar 31, 2020
2 parents 600e187 + f68a015 commit bc44eed
Show file tree
Hide file tree
Showing 33 changed files with 32 additions and 78 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# master

* Remove initializer requirement from the component.

*Vasiliy Ermolovich*

# v2.1.0

* Support rendering collections (e.g., `render(MyComponent.with_collection(@items))`).
Expand Down
13 changes: 4 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ Which returns:
<span title="my title">Hello, World!</span>
```

`ViewComponent` requires the presence of an `initialize` method in each component.

#### Content Areas

A component can declare additional content areas to be rendered in the component. For example:
Expand All @@ -162,9 +160,6 @@ A component can declare additional content areas to be rendered in the component
```ruby
class ModalComponent < ViewComponent::Base
with_content_areas :header, :body

def initialize(*)
end
end
```

Expand Down Expand Up @@ -498,10 +493,10 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/github
|@mellowfish|@horacio|@dukex|@dark-panda|@smashwilson|
|Spring Hill, TN|Buenos Aires|São Paulo||Gambrills, MD|

|<img src="https://avatars.githubusercontent.com/blakewilliams?s=256" alt="blakewilliams" width="128" />|<img src="https://avatars.githubusercontent.com/seanpdoyle?s=256" alt="seanpdoyle" width="128" />|<img src="https://avatars.githubusercontent.com/tclem?s=256" alt="tclem" width="128" />|
|:---:|:---:|:---:|
|@blakewilliams|@seanpdoyle|@tclem|
|Boston, MA|New York, NY|San Francisco, CA|
|<img src="https://avatars.githubusercontent.com/blakewilliams?s=256" alt="blakewilliams" width="128" />|<img src="https://avatars.githubusercontent.com/seanpdoyle?s=256" alt="seanpdoyle" width="128" />|<img src="https://avatars.githubusercontent.com/tclem?s=256" alt="tclem" width="128" />|<img src="https://avatars.githubusercontent.com/nashby?s=256" alt="nashby" width="128" />
|:---:|:---:|:---:|:---:|
|@blakewilliams|@seanpdoyle|@tclem|@nashby|
|Boston, MA|New York, NY|San Francisco, CA|Minsk|

## License

Expand Down
8 changes: 3 additions & 5 deletions lib/rails/generators/component/component_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ def parent_class
end

def initialize_signature
if attributes.present?
attributes.map { |attr| "#{attr.name}:" }.join(", ")
else
"*"
end
return if attributes.blank?

attributes.map { |attr| "#{attr.name}:" }.join(", ")
end

def initialize_body
Expand Down
2 changes: 2 additions & 0 deletions lib/rails/generators/component/templates/component.rb.tt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
class <%= class_name %>Component < <%= parent_class %>
<%- if initialize_signature -%>
def initialize(<%= initialize_signature %>)
<%= initialize_body %>
end
<%- end -%>
end
20 changes: 4 additions & 16 deletions lib/view_component/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,15 @@ def request
@@test_controller = "ApplicationController"

class << self
attr_accessor :source_location

def inherited(child)
if defined?(Rails)
child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers
end

child.source_location = caller_locations(1, 1)[0].absolute_path

super
end

Expand All @@ -153,16 +157,6 @@ def call_method_name(variant)
end
end

def source_location
@source_location ||=
begin
# Require `#initialize` to be defined so that we can use `method#source_location`
# to look up the filename of the component.
initialize_method = instance_method(:initialize)
initialize_method.source_location[0] if initialize_method.owner == self
end
end

def compiled?
@compiled && ActionView::Base.cache_template_loading
end
Expand Down Expand Up @@ -252,12 +246,6 @@ def template_errors
@template_errors ||=
begin
errors = []
if source_location.nil?
# Require `#initialize` to be defined so that we can use `method#source_location`
# to look up the filename of the component.
errors << "#{self} must implement #initialize."
end

errors << "Could not find a template file for #{self}." if templates.empty?

if templates.count { |template| template[:variant].nil? } > 1
Expand Down
1 change: 0 additions & 1 deletion test/app/components/another_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class AnotherComponent < ViewComponent::Base
def initialize(*); end
end
1 change: 0 additions & 1 deletion test/app/components/asset_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class AssetComponent < ViewComponent::Base
def initialize(*); end
end
1 change: 0 additions & 1 deletion test/app/components/button_to_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class ButtonToComponent < ViewComponent::Base
def initialize(*); end
end
1 change: 0 additions & 1 deletion test/app/components/content_for_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class ContentForComponent < ViewComponent::Base
def initialize(*); end
end
2 changes: 0 additions & 2 deletions test/app/components/css_sidecar_file_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class CssSidecarFileComponent < ViewComponent::Base
def initialize(*)
end
end
1 change: 0 additions & 1 deletion test/app/components/editorb_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class EditorbComponent < ViewComponent::Base
def initialize(*); end
end
2 changes: 0 additions & 2 deletions test/app/components/exception_in_template_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class ExceptionInTemplateComponent < ViewComponent::Base
def initialize(*)
end
end
1 change: 0 additions & 1 deletion test/app/components/helpers_proxy_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class HelpersProxyComponent < ViewComponent::Base
def initialize(*); end
end
2 changes: 0 additions & 2 deletions test/app/components/inline_component.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

class InlineComponent < ViewComponent::Base
def initialize(*); end

def call
text_field_tag :name
end
Expand Down
2 changes: 0 additions & 2 deletions test/app/components/missing_template_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class MissingTemplateComponent < ViewComponent::Base
def initialize(*)
end
end
1 change: 0 additions & 1 deletion test/app/components/my_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class MyComponent < ViewComponent::Base
def initialize(*); end
end
1 change: 0 additions & 1 deletion test/app/components/no_format_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class NoFormatComponent < ViewComponent::Base
def initialize(*); end
end
2 changes: 0 additions & 2 deletions test/app/components/no_validations_component.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

class NoValidationsComponent < ViewComponent::Base
def initialize(*); end

def before_render_check
#noop
end
Expand Down
1 change: 0 additions & 1 deletion test/app/components/partial_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class PartialComponent < ViewComponent::Base
def initialize(*); end
end
2 changes: 0 additions & 2 deletions test/app/components/path_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class PathComponent < ViewComponent::Base
def initialize(*)
end
end
2 changes: 0 additions & 2 deletions test/app/components/path_container_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class PathContainerComponent < ViewComponent::Base
def initialize(*)
end
end
2 changes: 0 additions & 2 deletions test/app/components/render_check_component.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

class RenderCheckComponent < ViewComponent::Base
def initialize(*); end

def render?
!view_context.cookies[:shown]
end
Expand Down
1 change: 0 additions & 1 deletion test/app/components/request_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class RequestComponent < ViewComponent::Base
def initialize(*); end
end
2 changes: 0 additions & 2 deletions test/app/components/too_many_sidecar_files_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class TooManySidecarFilesComponent < ViewComponent::Base
def initialize(*)
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class TooManySidecarFilesForVariantComponent < ViewComponent::Base
def initialize(*)
end
end
2 changes: 0 additions & 2 deletions test/app/components/translations_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class TranslationsComponent < ViewComponent::Base
def initialize(*)
end
end
2 changes: 0 additions & 2 deletions test/app/components/unreferenced_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class UnreferencedComponent < ViewComponent::Base
def initialize(*)
end
end
2 changes: 0 additions & 2 deletions test/app/components/url_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class UrlComponent < ViewComponent::Base
def initialize(*)
end
end
2 changes: 0 additions & 2 deletions test/app/components/validations_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ class ValidationsComponent < ViewComponent::Base

validates :content, presence: true

def initialize(*); end

def before_render_check
validate!
end
Expand Down
2 changes: 0 additions & 2 deletions test/app/components/variants_component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# frozen_string_literal: true

class VariantsComponent < ViewComponent::Base
def initialize(*)
end
end
1 change: 0 additions & 1 deletion test/app/components/wrapper_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

class WrapperComponent < ViewComponent::Base
def initialize(*); end
end
10 changes: 10 additions & 0 deletions test/generators/component_generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ def test_component

assert_file "app/components/user_component.rb" do |component|
assert_match(/class UserComponent < /, component)
assert_no_match(/def initialize/, component)
end
end

def test_component_with_arguments
run_generator %w[user name]

assert_file "app/components/user_component.rb" do |component|
assert_match(/class UserComponent < /, component)
assert_match(/def initialize\(name:\)/, component)
end
end

Expand Down
12 changes: 5 additions & 7 deletions test/view_component/view_component_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,14 @@ def test_compiles_unreferenced_component
assert UnreferencedComponent.compiled?
end

def test_does_not_compile_components_without_initializers
refute MissingInitializerComponent.compiled?
def test_compiles_components_without_initializers
assert MissingInitializerComponent.compiled?
end

def test_raises_error_when_initializer_is_not_defined
exception = assert_raises ViewComponent::TemplateError do
render_inline(MissingInitializerComponent.new)
end
def test_renders_when_initializer_is_not_defined
render_inline(MissingInitializerComponent.new)

assert_includes exception.message, "must implement #initialize"
assert_selector("div", text: "Hello, world!")
end

def test_raises_error_when_sidecar_template_is_missing
Expand Down

0 comments on commit bc44eed

Please sign in to comment.