Redwood: Add generator for utils/helpers directory?

Created on 19 Mar 2020  ·  12Comments  ·  Source: redwoodjs/redwood

If I ran something like this

$ yarn redwood generate helper convertdate

It creates a new subfolder called ConvertDate in helpers directory. That have the following files,

📦helpers
 ┣ 📂ConvertDate
 ┃ ┗ 📜ConvertDate.js
 ┃ ┗ 📜ConvertDate.test.js
 ┗ 📜.keep

Example files

This is the file that it generate ConvertDate.js

export const Add = (a, b) => {
  return a + b
}

Here is the example test file ConvertDate.test.js

import { Add } from './ConvertDate'

test('ConvertDate works', () => {
  const value = Add(1, 2)

  expect(value).toBe(3)
}
kinimprovement generators

Most helpful comment

I like this idea!

All 12 comments

I like this idea!

@AryanJ-NYC Are you up for the task? The core team might have their hands full btw I loved your last livestream

Sure! I'd love to take a crack at it. I may not be able to start until tomorrow or so but would love to be assigned.

One question: I understand it was just meant to be an example but any preference with respect to a default export vs. named export? I'm imagining util files that I've written which normally have >1 functions being exported (which makes me sort of lean towards named exports).

P.S. I appreciate the kind words about the livestream! I actually hope to livestream this task!

It should be named export, I just updated the examples

Just want to fan the flame here, gents! Keep us in the loop early and often once you have some initial working examples.

@peterp and @cannikin any initial feedback or suggests before they start digging in? Especially relevant examples and/or lessons from the Rails world?

Thanks, all!! 🚀

I change the examples from utils to helpers, to resemble more like ruby on rails.

In my humble opinion helpers and utils are an anti-pattern. They're the name of a module where you shove function that doesn't have an appropriate place, but sometimes that's a thing that we have to do, here's an example from our own repository:

./redwood/packages/cli/src/commands/generate
$ ls
README.md  commands   helpers.js templates

(The helpers.js file in this case reduces boilerplate by adding common functionality to all the commands. I might just rename this to boilerplate.js).

I'm not happy with this code, but I'm OK with this code because it's colocated to the functionality that it supports. Colocation is one of the principles that I try to follow in order to simplify my code.

Colocation works well because I can focus on the task at hand and don't have to worry that something else is using this code.

So having said that I would hate to introduce a pattern that I don't think is a good idea, but I'm happy to be convinced otherwise, and in this case, maybe it's the name helpers or utils that I'm not happy about...

Maybe the idea is that you're abstracting some other module in convertDate and then placing it in src/lib/convertDate is ok.

Or maybe it's something completely separated from your codebase in which case adding it to packages/* and extending yarn workspaces might be more appropriate.

@cannikin Would ❤️a Rails perspective here:

  • Is there (or has there been) an equivalent concept in Rails?
  • If so, has is been sustainably helpful (specific to DX).. or did it end up evolving into something else?

https://mixandgo.com/learn/the-beginners-guide-to-rails-helpers

Rails provides a top-level helpers directory where you can put Ruby modules that get mixed in (kind of like a decorator) to any rendered View. The idea is to encapsulate complex view logic into methods. So instead of:

<% if current_user && current_user.active? && current_user.admin? %>
  <% link_to 'Admin', admin_path %>
<% end %>

You could put all those checks into a helper:

module AdminHelper
  def admin?
    current_user && current_user.active? && current_user.admin?
  end
end

And then your view becomes:

<% if admin? %>
  <% link_to 'Admin', admin_path %>
<% end %>

By default helpers are available across all views in all controllers. You can limit them, but in this particular example it's probably something you would want to be available everywhere.

I'm not sure what the equivalent paradigm would be in the React world. If you want something only in a single component then you can just add a function above your component definition, but if you want it shared in other places...put a file and function in /lib and then include that when needed? That sounds like what the OP is suggesting, but just codifying that idea into a directory named helpers instead, which I personally like.

This feels like an opportunity for Redwood to introduce The Redwood Way™ to handle these kinds of helping functions. Let's bring this up with @mojombo in our next weekly meeting!

I'm not sure what the equivalent paradigm would be in the React world.

I think we would just use a component in the React world. It's components all the way down.

Closing the loop here after the team had a chance to discuss this. Effectively, we don't think we're ready for this yet (e.g. starting to implement helpers as a part of core features). But we wanted to point the way with a foundation for how to do this in an app (not as a generator but as a kind of util).

See redwoodjs/create-redwood-app/issues/45

Further thoughts or questions before we close this one for now?

Lastly, don't take this as a "stop everything". Please feel free to carry this forward in the forums and in the future. Given the ability to find and share helpers, it would be very interesting to see how and if this concept is used amongst the community.

Closing this here. Given my previous comment, we’d still welcome continuing conversation about this in the forums (or looping back in the future). Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

weaversam8 picture weaversam8  ·  3Comments

tmeasday picture tmeasday  ·  4Comments

balaji-balu picture balaji-balu  ·  3Comments

cannikin picture cannikin  ·  3Comments

jeliasson picture jeliasson  ·  3Comments