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

Support Padrino's partial to accept block #1099

Closed
lolmaus opened this issue Nov 29, 2013 · 19 comments
Closed

Support Padrino's partial to accept block #1099

lolmaus opened this issue Nov 29, 2013 · 19 comments

Comments

@lolmaus
Copy link
Contributor

lolmaus commented Nov 29, 2013

Padrino now supports passing a block to a partial.

Partial:

%h1 prefix
.haml-block
  = yield
%h3 postfix

Page:

= partial 'foo' do
  Yay, a codeblock!

Resulting HTML:

<h1>prefix</h1>
<div class="haml-block">
  Yay, a codeblock!
</div>
<h3>postfix</h3>

This functionality is absolutely awesome. Now Pardrino doesn't fall behind Sass and Jade which have supported passing blocks to mixins since forever.

Unfortunately, this won't work in Middleman. Middleman produces the following HTML:

    Yay, a codeblock!
<h1>prefix</h1>
<div class="haml-block">
  0
</div>
<h3>postfix</h3>

@ujifgc, a Padrino maintainer who was kind to implement this feature, supposes that the problem in Middleman might take place due to this monkey patch. He suggests that we should:

  1. determine why this monkey patch is there in the first place and
  2. either get rid of it or modify it to support modern Padrino.

The reason for the issue may hide elsewhere though.

Here's a sandbox project that can be used to test the issue quickly: https://github.com/lolmaus/middleman-padrino-test-partial-block

PS Yes, i know that Padrino/Middleman partials can accept code blocks by processing them through capture_html, assigning the result to variables and passing the variables to partials. But this is just ugly. Partials should be able to accept code blocks naturally, just like mixins in Sass and Jade. Padrino already made that happen. Please make Middleman compatible.

@ujifgc
Copy link

ujifgc commented Nov 29, 2013

I must add that the feature is not yet released on rubygems. It works on Padrino edge with version 0.12.0.rc.

@tdreyno
Copy link
Member

tdreyno commented Nov 29, 2013

Thanks for the heads up. We've had to do a bit of monkey patching in the past for convoluted template chaining. People do insane things like call Slim partials from Haml inside an Erb layout. Maybe that's not necessary any more. When 0.12.0 ships, we'll see if we can remove our hacks and inherit this new functionality.

@ujifgc
Copy link

ujifgc commented Nov 30, 2013

Yes, we test mixed engines since padrino/padrino-framework@e0e0bf7. It should be working. Engine/block detection also more clean and precise now.

@tdreyno
Copy link
Member

tdreyno commented Nov 30, 2013

Sweet

@lolmaus
Copy link
Contributor Author

lolmaus commented Dec 3, 2013

I have come up with a way to do the requested functionality with existing Middleman implementation.

I've created a mixin helper which lets you provide a block to a partial. If a block is provided to a mixin, it is made available within a partial as options[:yield].

Source: https://gist.github.com/lolmaus/7772057

Example partial (Haml):

.comment
  %h2= options[:user]
  %p= options[:text]

  = options[:yield]

Example usage (Haml):

= mixin :comment, user: 'Pete', text: 'What is love?' do
  = mixin :comment, user: 'Julia', text: 'Baby don\'t hurt me'

Resulting HTML:

<div class="comment">
  <h2>Pete</h2>
  <p>What is love?</p>
  <div class="comment">
    <h2>Julia</h2>
    <p>Baby don't hurt me</p>
  </div>
</div>

To achieve the same with vanilla partial you'd have to do:

- second_comment = capture_html do
  - partial 'mixins/comment', locals: { options: {user: 'Julia', text: 'Baby don\'t hurt me'}}

= partial 'mixins/comment', locals: { options: {user: 'Pete', text: 'What is love?', yield: second_comment}}

...which is very inconvenient and kinda counter-intuitive.

As you can see, the mixin helper also does three useful things:

  • It encourages you to store all your partials under /source/mixins, just like layouts.
  • It accepts arbitrary options (key-value pairs) that appear inside a partial within an options local variable. When invoking the helper, you don't have to nest options under locals: { ... }.
  • When no arbitrary options are provided, the options local variable appears inside a partial as an empty hash. This lets you use options without if defined? option, thanks to Ruby returning nil for nonexisting keys rather than crashing Middleman.

The traditional partial-style usage is also supported:

= mixin :thumbnail, locals: { bem_class: 'foo' }, object: @teh_thumbnail

There's explicit usage info provided alongside helper's code.


I find this helper to be so useful and effective that i humbly ask you to consider including it into Middleman.

@bhollis
Copy link
Contributor

bhollis commented Mar 25, 2014

Any update - has anyone tried this since we upgraded Padrino?

@lolmaus
Copy link
Contributor Author

lolmaus commented Mar 28, 2014

Do you mean Git version of Middleman? The Gem version hasn't been updated since 3.2.2 in January.

PS I've just noticed that Padrino is not mentioned in the Gemfile.lock. I thought it should be.

@tdreyno
Copy link
Member

tdreyno commented Mar 28, 2014

Padrino is bundled with Middleman until the next release of Padrino which makes it possible to unbundle.

@lolmaus
Copy link
Contributor Author

lolmaus commented Mar 28, 2014

So do i have to use Git version of Middleman to try to answer @bhollis's question? If yes, which branch? I'm currently using a funny helper to mimic that functionality so i also want to try it out.

@bhollis
Copy link
Contributor

bhollis commented Mar 29, 2014

Use the v3-stable Git version.

@lolmaus
Copy link
Contributor Author

lolmaus commented Apr 15, 2014

I confirm that it's now working with Haml.

But it fails with ERB. When you do:

<%= partial :foo do %>
  Bar
<% end %>

You receive an error that says Middleman tries to do ( partial :partial do).to_s.

@lolmaus
Copy link
Contributor Author

lolmaus commented Apr 15, 2014

Oh, it's not supposed to. We've already discussed it here: #1250 .

Who needs ERB anyway when there's Haml. Right, guys? Guys?..

@lolmaus lolmaus closed this as completed Apr 15, 2014
@ujifgc
Copy link

ujifgc commented Apr 15, 2014

Is the gem used erubis or erb? The former should work.

@lolmaus
Copy link
Contributor Author

lolmaus commented Apr 15, 2014

@ujifgc It's erubis but it's not supposed to work. The the (fixed) link to discussion above for details.

@jgillich
Copy link

I know it has been a while, but this does in fact work:

<% partial "foo" do %>
  Bar
<% end %>

Then simply <%= yield %> in the partial.

I will look into adding that to the docs.

@davidsilvasmith
Copy link

@jgillich that looks like just what I need!

I wasn't able to get the do yield block to work. :(

in _homepage-slider.erb
<% partial "/feature-pieces/homepage-slider-1" do %>
test
<% end %>`

and in /feature-pieces/homepage-slider-1.erb

<div class="slider-content">
    <%= yield %>
</div>

I get this error:
Tried to render a layout (calls yield) at /Users/me/apps/myapp/source/_partials/feature-pieces/_homepage-slider-1.erb like it was a template. Non-default layouts need to be in source/_layouts.

@davidsilvasmith
Copy link

@jgillich I'm not sure what my issue was, but you are right your example works perfectly.

Sorry for the false alarm.

@dkeeghan
Copy link

I had the same issue as @davidsilvasmith and it was because I used <%= at the start of the partial (like a normal partial load) instead of <%. Just in case anyone comes here looking for the same error.

@ldonis
Copy link

ldonis commented Oct 5, 2021

Something interesting I just found:

This fails:

<% partial "partials/header" do %>
<% end %>

This works like a charm:

<% partial "partials/header" do %>

<% end %>

Do you notice the line between the "partial" and the close tag? :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants