nice_partials 0.1.6 → 0.9.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.
@@ -1,25 +1,12 @@
1
1
  require_relative "partial"
2
2
 
3
3
  module NicePartials::Helper
4
- def np
5
- NicePartials::Partial.new(self)
6
- end
7
-
8
- def nice_partials_push_t_prefix(prefix)
9
- @_nice_partials_t_prefixes ||= []
10
- @_nice_partials_t_prefixes << prefix
4
+ def nice_partial_with(local_assigns)
5
+ NicePartials::Partial.new(self, local_assigns)
11
6
  end
12
7
 
13
- def nice_partials_pop_t_prefix
14
- @_nice_partials_t_prefixes ||= []
15
- @_nice_partials_t_prefixes.pop
16
- end
17
-
18
- def t(key, options = {})
19
- if @_nice_partials_t_prefixes&.any? && key.first == '.'
20
- key = "#{@_nice_partials_t_prefixes.last}#{key}"
21
- end
22
-
23
- super(key, **options)
8
+ def nice_partial
9
+ NicePartials::Partial.new(self)
24
10
  end
11
+ alias_method :np, :nice_partial
25
12
  end
@@ -1,59 +1,121 @@
1
1
  # Monkey patch required to make `t` work as expected. Is this evil?
2
2
  # TODO Do we need to monkey patch other types of renderers as well?
3
- class ActionView::PartialRenderer
4
- alias_method :original_render, :render
5
-
6
- # See `content_for` in `lib/nice_partials/partial.rb` for something similar.
7
- def render(partial, context, block)
8
- if block
9
- partial_prefix = nice_partials_locale_prefix_from_view_context_and_block(context, block)
10
- context.nice_partials_push_t_prefix partial_prefix
11
- else
12
- # Render partial calls with no block should disable any prefix magic.
13
- context.nice_partials_push_t_prefix ''
3
+ module NicePartials::RenderingWithLocalePrefix
4
+ ActionView::Base.prepend self
5
+
6
+ def capture(*, &block)
7
+ with_nice_partials_t_prefix(lookup_context, block) { super }
8
+ end
9
+
10
+ def t(key, options = {})
11
+ if (prefix = @_nice_partials_t_prefix) && key.first == '.'
12
+ key = "#{prefix}#{key}"
14
13
  end
15
14
 
16
- begin
17
- result = original_render(partial, context, block)
18
- rescue Exception => exception
19
- # If there was some sort of exception thrown, we also need to pop the `t` prefix.
20
- # This provides compatibility with other libraries that depend on catching exceptions from the view renderer.
21
- context.nice_partials_pop_t_prefix
22
- raise exception
15
+ super(key, **options)
16
+ end
17
+
18
+ private
19
+
20
+ def with_nice_partials_t_prefix(lookup_context, block)
21
+ _nice_partials_t_prefix = @_nice_partials_t_prefix
22
+ @_nice_partials_t_prefix = block ? NicePartials.locale_prefix_from(lookup_context, block) : nil
23
+ yield
24
+ ensure
25
+ @_nice_partials_t_prefix = _nice_partials_t_prefix
26
+ end
27
+ end
28
+
29
+ require "active_support/deprecation"
30
+ NicePartials::DEPRECATOR = ActiveSupport::Deprecation.new("1.0", "nice_partials")
31
+
32
+ module NicePartials::RenderingWithAutoContext
33
+ ActionView::Base.prepend self
34
+
35
+ def __partials
36
+ @__partials ||= NicePartials::Partial::Stack.new
37
+ end
38
+ delegate :partial, to: :__partials
39
+
40
+ def p(*args)
41
+ if args.empty?
42
+ NicePartials::DEPRECATOR.deprecation_warning :p, :partial # In-branch printing so we don't warn on legit `Kernel.p` calls.
43
+ partial
44
+ else
45
+ super # …we're really Kernel.p
23
46
  end
47
+ end
24
48
 
25
- # Whether there was a block or not, pop off whatever we put on the stack.
26
- context.nice_partials_pop_t_prefix
49
+ # Overrides `ActionView::Helpers::RenderingHelper#render` to push a new `nice_partial`
50
+ # on the stack, so rendering has a fresh `partial` to store content in.
51
+ def render(options = {}, locals = {}, &block)
52
+ partial_locals = options.is_a?(Hash) ? options[:locals] : locals
53
+ __partials.prepend nice_partial_with(partial_locals)
54
+ super
55
+ ensure
56
+ __partials.shift
57
+ end
27
58
 
28
- return result
59
+ # Since Action View passes any `yield`s in partials through `_layout_for`, we
60
+ # override `_layout_for` to detects if it's a capturing yield and append the
61
+ # current partial to the arguments.
62
+ #
63
+ # So `render … do |some_object|` can become `render … do |some_object, partial|`
64
+ # without needing to find and update the inner `yield some_object` call.
65
+ def _layout_for(*arguments, &block)
66
+ if block && !arguments.first.is_a?(Symbol)
67
+ capture_with_outer_partial_access(*arguments, &block)
68
+ else
69
+ super
70
+ end
29
71
  end
30
72
 
31
- # This and ActionView::Template#render below are for compatibility
32
- # with Ruby 3, as opposed to altering the original functionality.
73
+ # Reverts `partial` to return the outer partial before the `render` call started.
74
+ #
75
+ # So we don't clobber the `partial` shown here:
76
+ #
77
+ # <%= render "card" do |inner_partial| %>
78
+ # <% inner_partial.content_for :title, partial.content_for(:title) %>
79
+ # <% end %>
80
+ #
81
+ # Note: this happens because the `@partial` instance variable is shared between all
82
+ # `render` calls since rendering happens in one `ActionView::Base` instance.
83
+ def capture_with_outer_partial_access(*arguments, &block)
84
+ __partials.locate_previous
85
+ __partials.first.capture(*arguments, &block)
86
+ ensure
87
+ __partials.reset_locator
88
+ end
89
+ end
90
+
91
+ module NicePartials::PartialRendering
92
+ ActionView::PartialRenderer.prepend self
93
+
94
+ # Automatically captures the `block` in case the partial has no manual capturing `yield` call.
95
+ #
96
+ # This manual equivalent would be inserting this:
97
+ #
98
+ # <% yield partial %>
33
99
  def render_partial_template(view, locals, template, layout, block)
34
- ActiveSupport::Notifications.instrument(
35
- "render_partial.action_view",
36
- identifier: template.identifier,
37
- layout: layout && layout.virtual_path
38
- ) do |payload|
39
- content = template.render(view, locals, ActionView::OutputBuffer.new, {add_to_stack: !block}) do |*name|
40
- view._layout_for(*name, &block)
41
- end
42
-
43
- content = layout.render(view, locals) { content } if layout
44
- payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path]
45
- build_rendered_template(content, template)
46
- end
100
+ view.capture_with_outer_partial_access(&block) if block && !template.has_capturing_yield?
101
+ super
47
102
  end
48
103
  end
49
104
 
50
- class ActionView::Template
51
- def render(view, locals, buffer = ActionView::OutputBuffer.new, flag = {add_to_stack: true}, &block)
52
- instrument_render_template do
53
- compile!(view)
54
- view._run(method_name, self, locals, buffer, **flag, &block)
55
- end
56
- rescue => e
57
- handle_render_error(view, e)
105
+ module NicePartials::CapturingYieldDetection
106
+ ActionView::Template.include self
107
+
108
+ # Matches yields that'll end up calling `capture`:
109
+ # <%= yield %>
110
+ # <%= yield something_else %>
111
+ #
112
+ # Doesn't match obfuscated `content_for` invocations, nor custom yields:
113
+ # <%= yield :message %>
114
+ # <%= something.yield %>
115
+ #
116
+ # Note: `<%= yield %>` becomes `yield :layout` with no `render` `block`, though this method assumes a block is passed.
117
+ def has_capturing_yield?
118
+ defined?(@has_capturing_yield) ? @has_capturing_yield :
119
+ @has_capturing_yield = source.match?(/[^\.\b]yield[\(? ]+(%>|[^:])/)
58
120
  end
59
121
  end
@@ -0,0 +1,54 @@
1
+ class NicePartials::Partial::Content
2
+ class Options < Hash
3
+ def initialize(view_context)
4
+ @view_context = view_context
5
+ end
6
+
7
+ def to_s
8
+ @view_context.tag.attributes(self)
9
+ end
10
+ end
11
+
12
+ def initialize(view_context, content = nil)
13
+ @view_context, @options = view_context, Options.new(view_context)
14
+ @content = ActiveSupport::SafeBuffer.new and concat content
15
+ end
16
+ delegate :to_s, :present?, to: :@content
17
+
18
+ # Contains options passed to a partial:
19
+ #
20
+ # <% partial.title class: "post-title" %> # partial.title.options # => { class: "post-title" }
21
+ #
22
+ # # Automatically runs `tag.attributes` when `to_s` is called, e.g.:
23
+ # <h1 <% partial.title.options %>> # => <h1 class="post-title">
24
+ attr_reader :options
25
+
26
+ def write?(content = nil, **new_options, &block)
27
+ @options.merge! new_options
28
+ append content or capture block
29
+ end
30
+
31
+ def write(...)
32
+ write?(...)
33
+ self
34
+ end
35
+
36
+ private
37
+
38
+ def append(content)
39
+ case
40
+ when content.respond_to?(:render_in) then concat content.render_in(@view_context)
41
+ when content.respond_to?(:call) then capture content
42
+ else
43
+ concat content
44
+ end
45
+ end
46
+
47
+ def capture(block)
48
+ append @view_context.capture(&block) if block
49
+ end
50
+
51
+ def concat(string)
52
+ @content << string.to_s if string.present?
53
+ end
54
+ end
@@ -0,0 +1,48 @@
1
+ class NicePartials::Partial::Section < NicePartials::Partial::Content
2
+ def yield(*arguments)
3
+ chunks.each { append @view_context.capture(*arguments, &_1) }
4
+ self
5
+ end
6
+
7
+ def present?
8
+ chunks.present? || super
9
+ end
10
+
11
+ undef_method :p # Remove Kernel.p here to pipe through method_missing and hit tag proxy.
12
+
13
+ # Implements our proxying to the `@view_context` or `@view_context.tag`.
14
+ #
15
+ # `@view_context` proxying forwards the message and automatically appends any content, so you can do things like:
16
+ #
17
+ # <% partial.body.render "form", tangible_thing: @tangible_thing %>
18
+ # <% partial.body.link_to @document.name, @document %>
19
+ # <% partial.body.t ".body" %>
20
+ #
21
+ # `@view_context.tag` proxy lets you build bespoke elements based on content and options provided:
22
+ #
23
+ # <% partial.title "Some title content", class: "xl" %> # Write the content and options to the `title`
24
+ # <% partial.title.h2 ", appended" %> # => <h2 class="xl">Some title content, appended</h2>
25
+ #
26
+ # Note that NicePartials don't support deep merging attributes out of the box.
27
+ # For that, bundle https://github.com/seanpdoyle/attributes_and_token_lists
28
+ def method_missing(meth, *arguments, **keywords, &block)
29
+ if meth != :p && @view_context.respond_to?(meth)
30
+ append @view_context.public_send(meth, *arguments, **keywords, &block)
31
+ else
32
+ @view_context.tag.public_send(meth, @content + arguments.first.to_s, **options.merge(keywords), &block)
33
+ end
34
+ end
35
+ def respond_to_missing?(...) = @view_context.respond_to?(...)
36
+
37
+ private
38
+
39
+ def capture(block)
40
+ if block&.arity&.nonzero?
41
+ chunks << block
42
+ else
43
+ super
44
+ end
45
+ end
46
+
47
+ def chunks() = @chunks ||= []
48
+ end
@@ -0,0 +1,19 @@
1
+ class NicePartials::Partial::Stack
2
+ def initialize
3
+ @partials = []
4
+ reset_locator
5
+ end
6
+ delegate :prepend, :shift, :first, to: :@partials
7
+
8
+ def partial
9
+ @partials.public_send @locator
10
+ end
11
+
12
+ def locate_previous
13
+ @locator = :second
14
+ end
15
+
16
+ def reset_locator
17
+ @locator = :first
18
+ end
19
+ end
@@ -1,39 +1,111 @@
1
1
  module NicePartials
2
2
  class Partial
3
+ autoload :Content, "nice_partials/partial/content"
4
+ autoload :Section, "nice_partials/partial/section"
5
+ autoload :Stack, "nice_partials/partial/stack"
6
+
3
7
  delegate_missing_to :@view_context
4
8
 
5
- def initialize(view_context)
6
- @view_context = view_context
7
- @key = SecureRandom.uuid
9
+ def initialize(view_context, local_assigns = nil)
10
+ @view_context, @local_assigns = view_context, local_assigns
8
11
  end
9
12
 
10
- def yield(name = nil)
11
- raise "You can only use Nice Partial's yield method to retrieve the content of named content area blocks. If you're not trying to fetch the content of a named content area block, you don't need Nice Partials! You can just call the vanilla Rails `yield`." unless name
12
- content_for(name)
13
+ def yield(*arguments, &block)
14
+ if arguments.empty?
15
+ @captured_buffer
16
+ else
17
+ content_for(*arguments, &block)
18
+ end
13
19
  end
14
20
 
15
21
  def helpers(&block)
16
- class_eval &block
22
+ self.class.class_eval(&block)
17
23
  end
18
24
 
19
- # See the `ActionView::PartialRenderer` monkey patch in `lib/nice_partials/monkey_patch.rb` for something similar.
20
- def content_for(name, content = nil, options = {}, &block)
21
- if block_given?
22
- partial_prefix = nice_partials_locale_prefix_from_view_context_and_block(@view_context, block)
23
- @view_context.nice_partials_push_t_prefix(partial_prefix)
25
+ # `translate` is a shorthand to set `content_for` with content that's run through
26
+ # the view's `translate`/`t` context.
27
+ #
28
+ # partial.t :title # => partial.content_for :title, t(".title")
29
+ # partial.t title: :section # => partial.content_for :title, t(".section")
30
+ # partial.t title: "some.custom.key" # => partial.content_for :title, t("some.custom.key")
31
+ # partial.t :description, title: :header # Mixing is supported too.
32
+ #
33
+ # Note that `partial.t "some.custom.key"` can't derive a `content_for` name, so an explicit
34
+ # name must be provided e.g. `partial.t title: "some.custom.key"`.
35
+ def translate(*names, **renames)
36
+ names.chain(renames).each do |name, key = name|
37
+ content_for name, @view_context.t(key.is_a?(String) ? key : ".#{key}")
24
38
  end
39
+ end
40
+ alias t translate
25
41
 
26
- result = @view_context.content_for("#{name}_#{@key}".to_sym, content, options, &block)
42
+ # Allows an inner partial to copy content from an outer partial.
43
+ #
44
+ # Additionally a hash of keys to rename in the new partial context can be passed.
45
+ #
46
+ # First, an outer partial gets some content set:
47
+ # <% partial.title "Hello there" %>
48
+ # <% partial.byline "Somebody" %>
49
+ #
50
+ # Second, a new partial is rendered, but we want to extract the title, byline content but rename the byline key too:
51
+ # <%= render "shared/title" do |cp| %>
52
+ # <% cp.content_from partial, :title, byline: :name %>
53
+ # <% end %>
54
+ #
55
+ # # Third, the contents with any renames are accessible in shared/_title.html.erb:
56
+ # <%= partial.title %> # => "Hello there"
57
+ # <%= partial.name %> # => "Somebody"
58
+ def content_from(partial, *names, **renames)
59
+ names.chain(renames).each { |key, new_key = key| public_send new_key, partial.public_send(key).to_s }
60
+ end
27
61
 
28
- if block_given?
29
- @view_context.nice_partials_pop_t_prefix
30
- end
62
+ # Similar to Rails' built-in `content_for` except it defers any block execution
63
+ # and lets you pass arguments into it, like so:
64
+ #
65
+ # # Here we store a block with some eventual content…
66
+ # <% partial.title { |tag| tag.h1 } %>
67
+ #
68
+ # # …which we can then yield into with some predefined options later.
69
+ # <%= partial.title.yield tag.with_options(class: "text-bold") %>
70
+ def section(name, content = nil, **options, &block)
71
+ section_from(name).then { _1.write?(content, **options, &block) ? nil : _1 }
72
+ end
73
+
74
+ def section?(name)
75
+ @sections&.dig(name).present?
76
+ end
77
+ alias content_for? section?
78
+
79
+ def content_for(...)
80
+ section(...)&.to_s
81
+ end
82
+
83
+ def slice(*keys)
84
+ keys.index_with { content_for _1 }
85
+ end
86
+
87
+ def capture(*arguments, &block)
88
+ @captured_buffer = @view_context.capture(*arguments, self, &block)
89
+ end
31
90
 
32
- return result
91
+ private
92
+
93
+ def section_from(name)
94
+ @sections ||= {} and @sections[name] ||= Section.new(@view_context, @local_assigns&.dig(name))
95
+ end
96
+
97
+ def method_missing(meth, *arguments, **keywords, &block)
98
+ if @view_context.respond_to?(meth)
99
+ @view_context.public_send(meth, *arguments, **keywords, &block)
100
+ else
101
+ define_accessor meth and public_send(meth, *arguments, **keywords, &block)
102
+ end
33
103
  end
34
104
 
35
- def content_for?(name)
36
- @view_context.content_for?("#{name}_#{@key}".to_sym)
105
+ def define_accessor(name)
106
+ name = name.to_s.chomp("?").to_sym
107
+ self.class.define_method(name) { |content = nil, **options, &block| section(name, content, **options, &block) }
108
+ self.class.define_method("#{name}?") { section?(name) }
37
109
  end
38
110
  end
39
111
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NicePartials
4
- VERSION = "0.1.6"
4
+ VERSION = "0.9.0"
5
5
  end
data/lib/nice_partials.rb CHANGED
@@ -1,20 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "nice_partials/version"
4
- require_relative "nice_partials/helper"
5
- require_relative "nice_partials/monkey_patch"
6
4
 
7
5
  module NicePartials
8
- end
9
-
10
- # TODO Is there somewhere better we can put this?
11
- def nice_partials_locale_prefix_from_view_context_and_block(context, block)
12
- root_paths = context.view_renderer.lookup_context.view_paths.map(&:path)
13
- partial_location = block.source_location.first.dup
14
- root_paths.each { |path| partial_location.gsub!(/^#{path}\//, '') }
15
- partial_location.split('.').first.gsub('/_', '/').gsub('/', '.')
6
+ def self.locale_prefix_from(lookup_context, block)
7
+ partial_location = block.source_location.first.dup
8
+ lookup_context.view_paths.each { partial_location.delete_prefix!(_1.path)&.delete_prefix!("/") }
9
+ partial_location.split('.').first.gsub('/_', '/').gsub('/', '.')
10
+ end
16
11
  end
17
12
 
18
13
  ActiveSupport.on_load :action_view do
14
+ require_relative "nice_partials/monkey_patch"
15
+
16
+ require_relative "nice_partials/helper"
19
17
  include NicePartials::Helper
20
18
  end
@@ -12,9 +12,15 @@ Gem::Specification.new do |gem|
12
12
  gem.homepage = "https://github.com/bullet-train-co/nice_partials"
13
13
  gem.license = "MIT"
14
14
 
15
- gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^pkg/ }
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ gem.files = Dir.chdir(__dir__) do
18
+ `git ls-files -z`.split("\x0").reject do |f|
19
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
20
+ end
21
+ end
22
+ gem.bindir = "exe"
23
+ gem.executables = gem.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
18
24
  gem.require_paths = ["lib"]
19
25
 
20
26
  gem.required_ruby_version = ">= 2.0"
@@ -22,4 +28,5 @@ Gem::Specification.new do |gem|
22
28
  gem.add_dependency "actionview", '>= 4.2.6'
23
29
 
24
30
  gem.add_development_dependency "rails"
31
+ gem.add_development_dependency "standard"
25
32
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nice_partials
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  - Dom Christie
9
9
  autorequire:
10
- bindir: bin
10
+ bindir: exe
11
11
  cert_chain: []
12
- date: 2022-02-10 00:00:00.000000000 Z
12
+ date: 2023-01-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionview
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: standard
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  description: A little bit of magic to make partials perfect for components.
43
57
  email:
44
58
  - andrew.culver@gmail.com
@@ -47,8 +61,6 @@ executables: []
47
61
  extensions: []
48
62
  extra_rdoc_files: []
49
63
  files:
50
- - ".gitignore"
51
- - ".travis.yml"
52
64
  - CHANGELOG.md
53
65
  - CODE_OF_CONDUCT.md
54
66
  - Gemfile
@@ -59,13 +71,11 @@ files:
59
71
  - lib/nice_partials/helper.rb
60
72
  - lib/nice_partials/monkey_patch.rb
61
73
  - lib/nice_partials/partial.rb
74
+ - lib/nice_partials/partial/content.rb
75
+ - lib/nice_partials/partial/section.rb
76
+ - lib/nice_partials/partial/stack.rb
62
77
  - lib/nice_partials/version.rb
63
78
  - nice_partials.gemspec
64
- - test/fixtures/_basic.html.erb
65
- - test/fixtures/_card.html.erb
66
- - test/fixtures/card_test.html.erb
67
- - test/renderer_test.rb
68
- - test/test_helper.rb
69
79
  homepage: https://github.com/bullet-train-co/nice_partials
70
80
  licenses:
71
81
  - MIT
@@ -85,13 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
95
  - !ruby/object:Gem::Version
86
96
  version: '0'
87
97
  requirements: []
88
- rubygems_version: 3.2.22
98
+ rubygems_version: 3.4.1
89
99
  signing_key:
90
100
  specification_version: 4
91
101
  summary: A little bit of magic to make partials perfect for components.
92
- test_files:
93
- - test/fixtures/_basic.html.erb
94
- - test/fixtures/_card.html.erb
95
- - test/fixtures/card_test.html.erb
96
- - test/renderer_test.rb
97
- - test/test_helper.rb
102
+ test_files: []
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- Gemfile.lock
2
- /pkg
3
- *~
data/.travis.yml DELETED
@@ -1,18 +0,0 @@
1
- sudo: false
2
- language: ruby
3
-
4
- rvm:
5
- - 3.0
6
- - 2.7
7
- - 2.6
8
- - 2.5
9
- - 2.4
10
- - ruby-head
11
- - jruby-9.2.11.1
12
- - truffleruby-20.2.0
13
-
14
- matrix:
15
- allow_failures:
16
- - rvm: 2.4
17
- - rvm: ruby-head
18
- # fast_finish: true
@@ -1,2 +0,0 @@
1
- <% yield p = np %>
2
- <%= p.yield :message %>
@@ -1,13 +0,0 @@
1
- <% yield p = np %>
2
-
3
- <div class="card">
4
- <%= p.yield :image %>
5
- <div class="card-body">
6
- <h5 class="card-title"><%= title %></h5>
7
- <% if p.content_for? :body %>
8
- <p class="card-text">
9
- <%= p.content_for :body %>
10
- </p>
11
- <% end %>
12
- </div>
13
- </div>
@@ -1,9 +0,0 @@
1
- <%= render "card", title: "Some Title" do |p| %>
2
- <% p.content_for :body do %>
3
- Lorem Ipsum
4
- <% end %>
5
-
6
- <% p.content_for :image do %>
7
- <img src="https://example.com/image.jpg" />
8
- <% end %>
9
- <% end %>