9 ms·
Build a minimal decorator with Ruby in 30 minutes
- inopinatus 1y agoconsisting of: 1. spend 30 minutes beating around the bush, reinventing the wheel etc for your own education and interest; then 2. throw that away and use SimpleDelegator from the standard library and to be clear, I don’t mean this negatively at all.
- pantulis 1y agoSounds similar to begin building your own class and end up using an OpenStruct.
- byroot 1y agoAs a rule of thumb you never want to use OpenStruct. It's basically soft deprecated at this point because of its atrocious performance.
- Mystery-Machine 1y agoJust use the new Data class: https://docs.ruby-lang.org/en/3.2/Data.html https://docs.ruby-lang.org/en/3.2/Data.html
- deleted 1y ago[deleted]
- estsauver 1y agoDoesn't this thrash the ruby VM's virtual method cache? (It's been ~7 years since I was working on production ruby code, but I remember it being a really painful performance issue for us when using dynamic method missing routing. I might be getting it confused with class extensions though.)
- julienbourdeau 1y agoVery good question! The docs doesn't mention anything (unlike OpenStruct for instance)
- byroot 1y agoNot certain what you mean by "virtual method cache", the Ruby VM has multiple layers of method cache (or call cache) but I've never heard any of them referred to as the "virtual method cache". For the inline call caches in the interpreter loop, they are monomorphic, so if you call the same codepath with the decorator and the actual object, they will indeed flip flop. The second layer of cache is class based, so after the inline cache is defeated you will end up doing a single hash-table lookup on the class. As for YJIT, IIRC it does handle polymorphic call caches, so it won't mind such situation at all unless you have more than a handful of different implementations of that method being called at a given callsite.
- deleted 1y ago[deleted]
- firecall 1y agoMaybe I'm doing it wrong, but I've regretted my previous choice of using the Draper Gem and Decorators when coming back to old projects. I found Decorators just obscured display logic away in an inconvenient way.
- RangerScience 1y agoMight've been wise at the time, but nowadays I think the recommendation is to use View Components to package up view logic. (I'm personally so-so on VCs; I think the core idea is pretty good but I'm not super sold on some of the implementation details - too OOP, not enough `yield`)
- pmontra 1y agoRails has view helpers for that. Instead of <td class="<%= teacher.colour_coded_availability %>"> there would be <td class="<%= colour_coded_availability(teacher) %>"> but no metaprogramming, no decorators/ directory, no new concepts, only standard plain Rails. As a bonus it's even an instance of functional programming.
- arthurlewis 1y agoWell, until you need different `colour_coded_availability` methods for different contexts. Helpers get a lot done, but there are absolutely use cases for a separate presentation layer.
- ht85 1y ago(maximum_number_of_students <=> students.size).clamp(0..) Holy... Is this better or worse than write-once perl regexes?
- ricardobeat 1y agoI don’t get how this works. Won’t the spaceship operator always return 1, 0, -1?
- onli 1y agoYes. And then clamp(0..) removes the -1, maps it to a 0. Why you'd want that? No idea.
- mdoliwa 1y agoso this just says if we have free places or not? students.size < maximum_number_of_students
- jackbracken 1y agoIt gives the number of free places, hinted by the method name `available_places` Needlessly ugly way to write it imo though
- onli 1y agoBut it doesn't. The code will only ever output 0 or 1. With a regular <=> operator at least.
- mdoliwa 1y agoyeah, so basically 1 we have available places, 0 we do not.
- vidarh 1y agoI think it probably made sense to the author because they've used all three (-1,0,1) for other examples, and would've been fine until separated out to a method reused to show the actual number. I think they tried to be a bit too clever, basically.
- sathishmanohar 1y agoWait. are we confusing decorator pattern where a Teacher can be AvailableTeacher or UnavailableTeacher with decorating the web page which is the role of view and view helpers?
- sunfox 1y ago[dead]
- berkes 1y agoWhat annoys me (only slightly) in the Ruby community, is it's loose and often "wrong" usage of design patterns. IMHO, the whole idea of "design patterns" is that they are a standardized way of doing stuff. So that when someone, regardless of language, says "use an abstract factory" we know what it does, how it can be used, what it doesn't do, it's pitfalls etc. What ruby calls "decorators" aren't "decorators". That's for this DIY implementation, but even more so for "Draper". It's not only that an actual Decorator should not introduce new methods, but also how it's set-up and used. And therefore, what it's pitfalls and downsides are. In the case of Draper or this DIY: the views now rely on a concrete and specific subclass - losing both LSP and DIP. Worse: the layer using it -views- aren't the one setting it up or controlling it - the controllers. So it introduces very hard dependencies between different domains - the views/partials/serializers now depend on whether or not you've remembered to actually decorate the model. Something that in my experience will go wrong and will crash in production - or if you're lucky and have lots of E2E tests, in CI. The same "imprecise use of design patterns" happen with MVC, Models, ActiveRecord, "interfaces" and so forth. Often because of limitations of Ruby, but rather often because the Ruby community just uses the term "wrong".
- baobun 1y ago> Often because of limitations of Ruby wat. If anything I think Rubys lack of limitations could be the issue. There's a thousand different ways to do anything, and people do.
- deleted 1y ago[deleted]
- berkes 1y agoRuby doesn't have "interfaces" - obviously, because it doesn't have types or a type-enforcement. So any design pattern, architecture or concept that relies on types, or interfaces, are "limited" in that sense. Ports, Adapters, Strategy, for example " require" interfaces in their definition. Their benefits rely on interfaces, so if a language lacks this, you really only get the downsides. Factory, Observer, Decorators, etc mention them, and use them, but can be implemented without them. Maybe "limitations" isn't the best word, because e.g. "an interface" is a deliberate limitation, imposed and designed by the developer.
- lmz 1y agoReminds me of this recent comment in another thread re: Rails: https://news.ycombinator.com/item?id=44253645 https://news.ycombinator.com/item?id=44253645
- byroot 1y agoThe `method_missing` signature isn't correct since Ruby 3.0, as it doesn't handle keyword arguments. It should be: def method_missing(name, *args, **kwargs, &block) Starting from 3.1 it can be: def method_missing(name, ...)
- rmerci 1y ago[dead]
- sirk390 1y agoAll that complexity when you could simply do: <td class="<%= @teacher.available_places> 0 ? 'bg-colour-green' : 'bg-colour-red' %>">
- deleted 1y ago[deleted]