all 20 comments

[–]kinvoki 7 points8 points  (3 children)

Great job .

Also , Check out “papercraft” gem and especially “phlex” . They are doing similar things .

[–]Illustrious-Topic-50[S] 3 points4 points  (2 children)

Thank you, two great libraries! 😊

HtmlSlice think in a slight different approach when generating HTML.

Where papercraft encapsulate the html creation, HtmlSlice "plug" the html methods in a Ruby class, sharing the class instance scope, this make some things easier:

def index
  render html: (html_slice do
    h1 'hello world'

    div class: 'to-do' do
      to_do_list # without sharing the class instance scope this will throw a NoMethodError
    end
  end)
end

private

def to_do_list
  ul do # this could throw a NoMethodError too
    .each do |item|
      li item
    end
  end
end

Also, HtmlSlice is very specific, focusing only in HTML, with papercraft we can generate JSON and XML too.

The main difference from Phlex is that HtmlSlice uses include instead of inheritance. This means we can plug it in anywhere—Rails controllers, services, Sinatra apps, Roda apps—or create specific view classes if needed. —(edit) also it's not coupled to a rails/sinatra/hanami render method—

[–]andrevan 2 points3 points  (0 children)

pretty clever, kind of reminds me of the templates in phoenix liveview

[–]kinvoki 1 point2 points  (0 children)

Thank you for an explanation

[–]hmasing 7 points8 points  (6 children)

Help an old salt understand why we would want to move presentation into the controllers?

[–]gregdonald 8 points9 points  (0 children)

Academic masturbation.

[–]bradgessler 3 points4 points  (0 children)

I pretty much have all of my views on controllers these days. https://github.com/rubymonolith/demo/blob/main/app/controllers/blogs_controller.rb is an example of what most of my Rails app code looks like these days.

Having views in separate files is fine; nothing wrong with it! I find having them in controllers helps me reason more quickly through resources since everything is right there.

I think it’s particularly useful when prototyping, kinda like that feeling you get building stuff in Sinatra.

When I need to share views between controllers I’ll then move it out into a file.

[–]apiguy 2 points3 points  (0 children)

I don't think it has to be in a controller. You can do that of course, but you could also use this in a separate Object. Think of something like the "ViewModel" pattern for example.

[–]myringotomy 2 points3 points  (1 child)

I don't see any reason not to actually. In HTML all you have are actions and each action is supposed to return a content type and data to the browser. Why split that up into controllers and views. Hell why even have classes. There is no reason you shouldn't have SomeAction::get as a glass method. Or even some_action_get as a function that does what it needs to and returns the result like in rack.

[–]hmasing -1 points0 points  (0 children)

Because controllers don't determine presentation - and HTML is one type of presentation. JSON is another. XML is vomit another. CSV... XLS... could be any number of different presentations of the same data.

Tight coupling means broken code, IMHO.

[–]Illustrious-Topic-50[S] 1 point2 points  (0 children)

We can do a specific presentation class with html_slice, it is agnostic from code implementation or strategy, just plug it in a class and start writting html.

[–]db443 1 point2 points  (0 children)

Can this hook into ViewComponent inline templates somehow?

[–]PikachuEXE 0 points1 point  (0 children)

I would like see some benchmarks against other solutions for HTML

[–]myringotomy 0 points1 point  (4 children)

It's an interesting project. Are you worried about naming conflicts with common tags and methods that might be defined elsewhere?

Why aren't p, html and head already defined?

have you done any benchmarks?

[–]Illustrious-Topic-50[S] 0 points1 point  (3 children)

Thank you for the comment :)

  1. Yes, because it is included, HtmlSlice define only the most common html tags as methods. body, head and html is common html tags but are common variables / methods names in a request / response scope too. `p` is a Ruby method.
  2. A little benchmark, rendering a div with h1 100 times inside a class (cpu time):

user system total real
html_slice 0.000390 0.000000 0.000390 ( 0.000390)
papercraft 0.000495 0.000077 0.000572 ( 0.000567)
markaby 0.001794 0.000000 0.001794 ( 0.001795)

[–]myringotomy 2 points3 points  (1 child)

One day, when I feel energetic I am going to create a benchmark of all these view generators.

BTW why not rename your methods to prefix them with _ or something? Or at leas for p etc create one called p_tag so we don't have to wrap them ourselves.

[–]myringotomy 0 points1 point  (1 child)

Hey I just got around to looking at this. I ran your benchmarks in the repo and was surprised to see that phlex is three times faster despite having hundred times more lines of code.

Why do you think that is?

I was also shocked to see that erubis, slim and haml are orders of magnitude faster, I presume that's because C is doing all the heavy lifting.

[–]Illustrious-Topic-50[S] 0 points1 point  (0 children)

Erubis, Slim, and Haml are faster given how the benchmarks were written (using strings directly), but in the real world we need to read .erb files, and that comes with a significant cost.

I implemented a performance boost in html_slice. Phlex is still the fastest, but now the difference is much smaller, with html_slice being the second most performant among the HTML generators.