‘select’ method does not work as expected in hanami-view Part. Probably overrided ?

It seems select method is overrided inside Parts. MWE : (context is Hanami 2.2)

# app/views/posts/index.rb
module MyApp
  module Views
    module Posts
      class Index < MyApp::View
        expose :posts do
          (1..9)
        end
        expose :filtered_posts do |posts|
          posts.select(&:even?)
        end
      end
    end
  end
end
# app/views/parts/posts.rb
module MyApp
  module Views
    module Parts
      class Posts < MyApp::Views::Part
        def even_filter
          select(&:even?) # this leads to "wrong number of arguments (given 0, expected 1..4)" error
        end

        def working_even_filter
          find_all(&:even?) # this works !
        end
      end
    end
  end
end
# app/templates/posts/index.html.erb
<%= posts.even_filter.map(&:value) %>
<%= posts.working_even_filter.map(&:value) %>
<%= filtered_posts.map(&:value) %>

I get a syntax error wrong number of arguments (given 0, expected 1..4) pointing the select line.
Replacing select(&:even?) by find_all(&:even?) leads to expected behavior. Note that inside view, select works as expected (see filtered_posts).

What the purpose of overrided select method inside parts ?

I think this is because HTML tag helpers are included in the part by default and it interprets it as an attempt to render an HTML select tag. Which is indeed unfortunate.

Would _value.select(&:even?) work?

  1. _value.select(&:even?) works, thanks.

  2. I thought tag helpers were accessible with helpers.tag not directly as is. So select tag would require helpers.tag.select .... Actually, (inside a Parts method)

   helpers.tag.select [
     helpers.tag.option( "you", value: 1 ),
     helpers.tag.option( "me", value: 2 )
   ].join.html_safe

renders the expected html code. But

select [
    helpers.tag.option( "you", value: 1 ),
    helpers.tag.option( "me", value: 2 )
 ]

raises a no implicit conversion of Hanami::View::HTML::SafeString into IO error. So select expects some kind of IO object… Still mysterious…

I think this is because Kernel#select is being called.

Part classes decorate your value object, and forward methods to the value via #method_missing. But because Kernel#select exists, the method isn’t missing, and therefore the value’s method is not being called.

Interestingly, after years of doing it this way (via dry-view before hanami-view), you’re the first person to hit this! Thank you for sharing!

I think this warrants a re-look at how we delegate methods from the part to the value, but for the time being, at least you should now be able to handle these more confidently in the future: if a same-named instance method already exists on Object, you’ll need to be more explicit in calling the value itself.

Thanks for replying and pointing out which object is hitted by select inside Parts.

My mistake : thinking that part “decorates” exposures by a kind of exposure.extend( Part ) mechanism. So I expected Enumerable methods still available when exposure is a collection… I will take care on that.

Perhaps Hanami Parts are not designed this way on purpose. Perhaps the Hanami way is to do this selection job inside views… Does Hanami team provide a ‘best practice’ in this area ?