Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create base component #38

Merged
merged 4 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ RSpec/DescribedClass:
SkipBlocks: true
RSpec/ExpectChange:
EnforcedStyle: block
RSpec/FilePath:
Exclude:
- spec/kangaru/components/**/*.rb
RSpec/LetSetup:
Enabled: false
RSpec/MultipleMemoizedHelpers:
Expand Down
5 changes: 5 additions & 0 deletions lib/kangaru.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
require "yaml"

module Kangaru
COLLAPSED_DIRS = [
"#{__dir__}/kangaru/components"
].freeze

DEFAULT_ENV = :runtime

INFLECTIONS = {
Expand All @@ -20,6 +24,7 @@ module Kangaru
warn_on_extra_files: false
).tap do |loader|
loader.inflector.inflect(INFLECTIONS)
loader.collapse(COLLAPSED_DIRS)
loader.setup
end

Expand Down
19 changes: 19 additions & 0 deletions lib/kangaru/components/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Kangaru
class Component
using Patches::Inflections
using Patches::Source

def render
Renderer.new(view_file).render(binding)
end

private

def view_file
dir = File.dirname(self.class.source)
name = File.basename(self.class.source, ".rb")

Pathname.new(dir).join("#{name}.erb")
end
end
end
11 changes: 10 additions & 1 deletion lib/kangaru/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Controller

def initialize(command)
@command = command
@renderer = Renderer.new(command)
@renderer = Renderer.new(view_path)
end

def execute
Expand All @@ -25,5 +25,14 @@ def self.const_missing(const)
end

private_class_method :const_missing

private

def view_path
Kangaru.application.view_path(
controller: command.controller,
action: command.action.to_s
)
end
end
end
11 changes: 11 additions & 0 deletions lib/kangaru/patches/source.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Kangaru
module Patches
module Source
refine Module do
def source
Object.const_source_location(name || raise)&.first || raise
end
end
end
end
end
19 changes: 5 additions & 14 deletions lib/kangaru/renderer.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
module Kangaru
class Renderer
attr_reader :command
attr_reader :path

def initialize(command)
@command = command
def initialize(path)
@path = path
end

def render(binding)
return unless view_path.exist?
return unless path.exist?

ERB.new(view_path.read, trim_mode: "-").run(binding)
end

private

def view_path
Kangaru.application.view_path(
controller: command.controller,
action: command.action.to_s
)
ERB.new(path.read, trim_mode: "-").run(binding)
end
end
end
2 changes: 2 additions & 0 deletions sig/kangaru.rbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Kangaru
VERSION: String

COLLAPSED_DIRS: Array[String]
DEFAULT_ENV: Symbol
INFLECTIONS: Hash[String, String]

Expand Down
9 changes: 9 additions & 0 deletions sig/kangaru/components/component.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Kangaru
class Component
def render: -> void

private

def view_file: -> Pathname
end
end
4 changes: 4 additions & 0 deletions sig/kangaru/controller.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ module Kangaru
def initialize: (Command) -> void

def execute: -> void

private

def view_path: -> Pathname
end
end
9 changes: 9 additions & 0 deletions sig/kangaru/patches/source.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Kangaru
module Patches
module Source : Module
class ::Module
def source: -> String
end
end
end
end
8 changes: 2 additions & 6 deletions sig/kangaru/renderer.rbs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
module Kangaru
class Renderer
attr_reader command: Command
attr_reader path: Pathname

def initialize: (Command) -> void
def initialize: (Pathname) -> void

def render: (Binding) -> void

private

def view_path: -> Pathname
end
end
31 changes: 31 additions & 0 deletions spec/kangaru/components/component_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
RSpec.describe Kangaru::Component do
subject(:component) { described_class.new }

let(:renderer) { instance_spy(Kangaru::Renderer) }

before do
allow(Kangaru::Renderer).to receive(:new).and_return(renderer)
end

describe "#render" do
subject(:render) { component.render }

let(:component_path) do
Object.const_source_location(described_class.name).first
end

let(:view_path) do
Pathname.new(component_path.gsub(/\.rb$/, ".erb"))
end

it "infers the correct view file path" do
render
expect(Kangaru::Renderer).to have_received(:new).with(view_path).once
end

it "renders the view file" do
render
expect(renderer).to have_received(:render).once
end
end
end
47 changes: 21 additions & 26 deletions spec/kangaru/controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@
RSpec.describe Kangaru::Controller do
subject(:controller) { described_class.new(command) }

let(:command) { instance_double(Kangaru::Command, action:) }
let(:command) do
instance_double(Kangaru::Command, controller: controller_name, action:)
end

let(:action) { :some_action }
let(:controller_name) { :some_controller }

let(:renderer) { instance_spy(Kangaru::Renderer) }
let(:action) { :some_action }

before do
allow(Kangaru::Renderer).to receive(:new).and_return(renderer)
let(:application) do
instance_spy(Kangaru::Application, namespace:, view_path:)
end

describe "#initialize" do
it "sets the command" do
expect(controller.command).to eq(command)
end
let(:namespace) { Namespace }

it "instantiates a renderer" do
controller
expect(Kangaru::Renderer).to have_received(:new).with(command).once
end
let(:view_path) { instance_spy(Pathname) }

it "sets the renderer" do
expect(controller.renderer).to eq(renderer)
end
let(:renderer) { instance_spy(Kangaru::Renderer) }

before do
stub_const "Namespace", Module.new

allow(Kangaru).to receive(:application).and_return(application)
allow(Kangaru::Renderer).to receive(:new).and_return(renderer)
end

describe "#execute" do
Expand All @@ -46,6 +46,11 @@
expect(controller).to have_received(action).once
end

it "instantiates a renderer" do
execute
expect(Kangaru::Renderer).to have_received(:new).with(view_path).once
end

it "renders the command output" do
execute
expect(renderer).to have_received(:render).with(a_kind_of(Binding)).once
Expand All @@ -57,16 +62,6 @@

let(:foobar) { Module.new }

let(:application) do
instance_spy(Kangaru::Application, namespace: Namespace)
end

before do
stub_const "Namespace", Module.new

allow(Kangaru).to receive(:application).and_return(application)
end

context "when specified const is not defined inside Controller" do
context "and const not defined in application namespace" do
it "raises an error" do
Expand Down
35 changes: 35 additions & 0 deletions spec/kangaru/patches/source_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
RSpec.describe Kangaru::Patches::Source do
using described_class

describe ".source" do
subject(:source) { target.source }

describe Module do
module SomeModule; end # rubocop:disable Lint,RSpec

subject(:target) { SomeModule }

it "returns a string" do
expect(source).to be_a(String)
end

it "returns the expected source path" do
expect(source).to eq(__FILE__)
end
end

describe Class do
class SomeClass; end # rubocop:disable Lint,RSpec

subject(:target) { SomeClass }

it "returns a string" do
expect(source).to be_a(String)
end

it "returns the expected source path" do
expect(source).to eq(__FILE__)
end
end
end
end
23 changes: 8 additions & 15 deletions spec/kangaru/renderer_spec.rb
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
RSpec.describe Kangaru::Renderer do
subject(:renderer) { described_class.new(command) }
subject(:renderer) { described_class.new(path) }

let(:command) { instance_spy(Kangaru::Command) }
let(:application) { instance_spy(Kangaru::Application, view_path:) }

let(:view_path) do
instance_spy(Pathname, read: view_file_contents, exist?: view_file_exists?)
let(:path) do
instance_spy(Pathname, read: view_contents, exist?: view_exists?)
end

let(:view_file_contents) do
let(:view_contents) do
<<~ERB
Your name is <%= @name %>, you are <%= @age %> years old.
ERB
end

before do
allow(Kangaru).to receive(:application).and_return(application)
end

describe "#render" do
subject(:render) { renderer.render(binding) }

context "when view file does not exist" do
let(:view_file_exists?) { false }
let(:view_exists?) { false }

it "does not output any text" do
expect { render }.not_to output.to_stdout
end
end

context "when view file exists" do
let(:view_file_exists?) { true }
let(:view_exists?) { true }

context "when instance variables do not exist in binding" do
context "and instance variables do not exist in binding" do
let(:expected_output) do
<<~STRING
Your name is , you are years old.
Expand All @@ -44,7 +37,7 @@
end
end

context "when instance variables exist in binding" do
context "and instance variables exist in binding" do
around do |spec|
instance_variable_set(:@name, "Foo Bar")
instance_variable_set(:@age, 30)
Expand Down