Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Save Time (by Creating Custom Rails Generators)

Save Time (by Creating Custom Rails Generators)

Become skilled at quickly creating well-tested custom generators and turn those tedious and repetitive ten-minute distractions into ten-second commands—not just for you but for your entire team. With some curated knowledge and insights about custom generators and some advanced warning about the speed bumps, it can save time in far more scenarios than you might think.

Garrett Dimon

May 07, 2024
Tweet

More Decks by Garrett Dimon

Other Decks in Programming

Transcript

  1. 1

  2. 5

  3. 6

  4. 7

  5. 8 Custom Generators can save time and reduce tedium. But

    just because they can does not mean that they will. Thatʼs up to us.
  6. 9

  7. 10 Related Options Great for some scenarios, but they arenʼt

    entirely dedicated to the process of generating files. Generators – Rake Tasks – Ruby Scripts – Shell Scripts – Prose-based documentation – Snippet Tools – Copy/Paste + Search/Replace – Type from Memory –
  8. 13 Actions + Templates + Inflections + Arguments + Options

    + Tests + Documentation + Integration generators > sum_of_parts
  9. 14 What’s the generator generator generating for us? We can

    use the generator generator to generate a new generator in seconds.1 Thereʼs also a task , but theyʼre still not generators. 1. generator to quickly create Rake files
  10. 15

  11. 16 What’s in a name? A generator by any other

    name would still override a built-in generator by the same name.
  12. 17

  13. 18 Public methods are run by default. Less a speed

    bump and more just something key to know, but it can be easy to forget early on. no_commands do # or no_tasks # "Hidden" Public Methods end
  14. 19 Know where the magic happens. NamedBase or Base for

    a parent class? Most likely, NamedBase, but not just because itʼs the default.
  15. 20 NamedBase generators have a pre- defined “name” argument. Hence

    Named base and all of the wonderful inflections of the name.
  16. 21

  17. 22 NamedBase generators get greedy with “attributes” arguments. They create

    GeneratedAttribute values so we can create model attributes, so donʼt let that surprise you. price:decimal{10,2} pseudo:string{30} pseudo:string:uniq supplier:references{polymorphic} supplier:references{polymorphic}:index
  18. 23 It all boils down to sources, destinations, and high-level

    file system tools. Rubyʼs built-in file system libraries may as well be Assembly in comparison.
  19. 24

  20. 25

  21. 26

  22. 27

  23. 28

  24. 29

  25. 30 Directories are “templates” too! The directory action can recursively

    generate multiple files and directories with a single call.
  26. 31

  27. 32

  28. 34 Templates get access to everything. Not just ERb. Public

    methods. Private methods. Itʼs all fair game.1 The no_commands and no_tasks blocks can help, but private methods are my preferred approach. 1.
  29. 35 Know when to quote ’em. Strings will be “unquoted”

    when output through ERb, but the quote helper can fix that.
  30. 36

  31. 37 What’s whitespace got to do with it? Template whitespace

    is significant. Leading whitespace and line breaks can get ugly fast. <%- %> # Trim leading whitespace/indent. <% -%> # Trim trailing line break <%- -%> # Trim leading and trailing
  32. 38 Don’t sweat the indent. Make the most of the

    built-in indentation methods to dial it all in cleanly. Get help from optimize_indentation , indentation , and with_indentation
  33. 39 You got ERb in your ERb. Escape those delimiters

    with an extra %. <%% & %%> <%%- & -%%> <%%= <%%#
  34. 41 Reach for high-level tools first, mid-level second, and low-level

    almost never. The higher the level, the more leverage. (But also more magic to understand.)
  35. 42

  36. 43

  37. 44

  38. 45

  39. 46

  40. 47

  41. 48 Learn the Rails shortcuts. Take advantage of the Rails-centric

    generator tools even when the benefits seem minor.
  42. 49

  43. 50

  44. 52 Familiarity greases the skids. Rails devs already understand how

    to use generators so thereʼs less need to learn something new.
  45. 53 Generators are version-controlled and very shareable. Generators get used

    more. Team members become significant multipliers for time-savings.
  46. 54 Don’t reinvent the generator. Call a generator from a

    generator. Override and extend. Or just override the templates.
  47. 56 Generators have us covered on arguments and options. Arguments

    for the main stuff. Options for the extras.
  48. 57

  49. 59 Aim for one value argument and one collection argument.

    A few values can work, but too many arguments means more friction typing the command.
  50. 60

  51. 61 Command-line strings become easily accessible Ruby values. Strings, Numeric

    (Float or Integer), Array, and Hash. (Options can be boolean as well.)
  52. 62

  53. 63

  54. 64 The “free” coercion and type error-handling is (usually) enough.

    When weʼre on the command line everythingʼs a string until the generator steps in.
  55. 65 With arrays and hashes, it’s strings all the way

    down. No hashing with indifferent access. And no coercion either. 1 Options are hashed with indifferent access, but thatʼs it. 1.
  56. 66 Shell out with generator actions instead of standard Ruby

    options. The built-in tools for running system commands are smarter than they look.
  57. 67

  58. 68

  59. 69 Always be exiting. If a generator needs to stop,

    explicitly exit so the generator is a good citizen of the command line. exit(exit_code) 0 Success 1 Failure 126 Permissions Error 127 Command Not Found
  60. 71 Better documentation leads to increased usage. The defaults are

    great, but filling in a few blanks (and USAGE file) goes a long way.
  61. 72

  62. 73

  63. 74

  64. 75

  65. 76 Be judicious and practical with arguments and options. Usability

    and convenience are inversely proportional to the length of the documentation.
  66. 77 Small generators save time too. If we include the

    template and tests, the built-in rake task generator only has 30 lines of non-generated code.1 50 if we include generated code and blank lines. 1.
  67. 78

  68. 79

  69. 81

  70. 82 CLI-driven design can help keep commands concise. Write out

    the command you wouldnʼt mind typing regularly, and then translate it to a generator.
  71. 83 Make sure to say stuff. Most built-in actions will

    handle it, but itʼs still helpful to make sure our custom logic is helpful too.
  72. 84

  73. 85 Respect quiet time. Most actions will automatically respect the

    !"quiet option, but not all.1 We can check options.quiet? to know when a generator should suppress output. 1.
  74. 87 Don’t poke around the file system. The custom assertions

    are destination_root -aware. assert_file assert_method assert_class_method assert_instance_method
  75. 88 Always use the test helpers. The test file sets

    destination_root , but generator and run_generator are the only methods that care.
  76. 89

  77. 90 Take care when straying from the source or destination

    roots. We mostly donʼt have to think about it, but if we stray, it can get a little messy.
  78. 91

  79. 92 Listen to the tests. Stay in the generator wheelhouse.

    If a generator feels difficult to test, it might be trying to do too much.
  80. 93 The tests will clean up for us automatically if

    we let them. By default, generator tests route generated files to “tmp/generators” and reset it before each test.
  81. 94 But just in case, the cleanup happens before tests—not

    after. So running a single test will leave the generated files in “tmp/generators” for manual inspection.
  82. 95 Test interactive bits by pretending. Automated testing canʼt easily

    test interactive prompts. The !"pretend option can help.
  83. 96 Testing & RSpec. Like the rest of Rails, the

    testing benefits rely on Minitest. RSpec requires a little extra.1 Thoughtbotʼs suspenders gem has some , , and to streamline testing generators with RSpec. 1. custom generator matchers generator test helpers file operations
  84. 98 Generate any kind of text files. CSV, SVG, YAML,

    Markdown, HTML, CSS, JavaScript, ERb, Shell Scripts. And more.
  85. 99

  86. 100

  87. 101

  88. 102

  89. 103 What else? Site maps, humans.txt , robots.txt , shell

    scripts, fixtures, release notes, etc.
  90. 105 Git wild, but use a light touch. Even within

    teams, we all have subtly different git workflows.
  91. 106

  92. 107 Gather additional input. Relaying status information to the command

    line. Displaying errors. And requesting additional information.
  93. 108

  94. 109

  95. 111

  96. 112