Trying to create a "view object" with yield self

Hi I’m having a problem creating a view widget inside my erb template.

Please see the following gist accordion_rails.rb · GitHub

Basically I’m trying to isolate a complex piece of html markup with
something like :

<%= Accordion.new(parent: “my-parent”) do |accordion| %>
accordion.element(“elem1”)
accordion.element(“elem2”)
<% end %>

But yielding self does not return my object instance but the erb
template. It seems in rails there is a need to “capture” a given block
but I can’t figure out how to do this. I’m able to do something similar
via a rails helper however I wanted to create an object to keep things
DRY. Any help much appreciated !

Hi pry_f !

Sorry but I’m not sure to have exactly understood what you’re trying to
do.
What I understand from the code you made available is that the lines
below
should display something like

opening

  • elem1: parent is my-parent
  • elem2: parent is my-parent
  • closing

    and it doesn’t ?

    Le jeudi 6 juin 2013 19:48:46 UTC+2, Ruby-Forum.com User a crit :

    Berlimioz wrote in post #1111637:

    Hi pry_f !

    Sorry but I’m not sure to have exactly understood what you’re trying to
    do.
    What I understand from the code you made available is that the lines
    below
    should display something like

    opening

  • elem1: parent is my-parent
  • elem2: parent is my-parent
  • closing

    and it doesn’t ?

    Le jeudi 6 juin 2013 19:48:46 UTC+2, Ruby-Forum.com User a crit :

    That’s right. This is not a model related problem. I’m trying
    to make view “widgets” basically.
    I created another gist. This time it’s just a ruby script demonstrating
    the concept by printing to standard out.
    https://gist.github.com/PryFlack/5732422

    I have a little bug as mentioned in the comment. I was pretty sure this
    was going to work in plain ruby. Anyways with rails I’ve had trouble
    implementing this idea even more. I don’t see how I could use partials
    for that so the only thing I can think of is what I’m doing here. Thanks
    for your feedback and interest !

    Ok, maybe this could help :

    When your method initialize returns a string, calling Accordion.new
    doesn’t
    return this string, because the initialize method is called in the new
    method, but that’s not what’s returned by the new class method.

    On the other hand, when you have this :

    <<-EOF


    #{yield self}

    EOF

    the expression “yield self” will here return the return value of the
    block
    you pass. When you pass a block like this :

    Accordion.new() do |accordion|
    “something here”
    “something there”
    end

    the return value of the block is only “something there” (last line of
    the
    block). So that

    <<-EOF

    #{yield self}
    EOF

    will actually results in something like :

    something there

    Hope it helped, enjoy your week end anyway !

    Le vendredi 7 juin 2013 23:31:01 UTC+2, Ruby-Forum.com User a crit :

    Berlimioz wrote in post #1111694:

    On the other hand, when you have this :

    <<-EOF


    #{yield self}

    EOF

    the expression “yield self” will here return the return value of the
    block
    you pass. When you pass a block like this :

    Yes that’s what I was trying to do. I found my mystake. I need to use an
    instance variable to build the output buffer. Here is a working ruby
    “prototype” https://gist.github.com/PryFlack/5732422

    Now I’m gonna have to bring this into my rails app and see how it goes
    because as I said yield self behaves differently inside an ERB template.

    Enjoy your week-end too !

    Pry F. wrote in post #1111699:

    Berlimioz wrote in post #1111694:

    On the other hand, when you have this :

    <<-EOF


    #{yield self}

    EOF

    the expression “yield self” will here return the return value of the
    block
    you pass. When you pass a block like this :

    Yes that’s what I was trying to do. I found my mystake. I need to use an
    instance variable to build the output buffer. Here is a working ruby
    “prototype” https://gist.github.com/PryFlack/5732422

    Now I’m gonna have to bring this into my rails app and see how it goes
    because as I said yield self behaves differently inside an ERB template.

    Enjoy your week-end too !

    Well I am failing miserably with this!

    My latest attempt here: https://gist.github.com/PryFlack/5723324

    Having so much difficulty with this I thought about going a different
    way. I realized i could also do the following:

    =====START=====
    <% parent_id = “myAccordion” %>

      <%= render layout: 'accordion', locals: { parent_id: parent_id }
    

    do |parent| %>

        <%= render layout: 'accordion_element',
          locals: { target_id: "collapseRow1", title: "Row1",
            parent_id: parent_id, in_or_out: "in" } do %>
    
          <p>inside child1</p>
        <% end %>
    
        <%= render layout: 'accordion_element',
          locals: { target_id: "collapseRow2", title: "Row2",
            parent_id: parent_id, in_or_out: nil } do %>
    
          <p>inside child2</p>
        <% end %>
    
      <% end %>
    

    =====END=====

    However this is still pretty verbose. So this adds more complexity and
    it’s pretty rigid (if I want to modify the rendering of the html
    block, I have to modify my calls to render everywhere)

    Also apart from creating an instance variable inside the erb template, I
    don’t see a good way to pass value in the nested rendered layout (other
    than repeating myself)

    Has anybody got any good info on how to generate and abstract complex
    html blocks ?