Skip to Main Content

TWIL 2019-10-11

Image for the "TWIL" blog series featuring an array of web development icons representing topics like Rails, React, Heroku, and iTerm.

Welcome to another insightful installment of "TWIL," your weekly dose of micro-learning across various tech spheres! This week, our adept contributors invite you to explore the multifaceted world of web development and programming. Let's unwind the complexities of Rails HTML Preprocessors with Katie, who clarifies the essential ERB tags for dynamic content in Rails apps, or iterate through the steps of Creating a Basic Rails Generator, demystifying the customization of the Rails scaffolding process. Meanwhile, Marisa introduces the subtleties of state and effect synchronization in React with useEffect, while Frank reveals the synergy of Heroku, Django, and Webpack in deploying static assets seamlessly. And not to be outdone, Adam shares a swift productivity tip for simultaneous executions across iTerm with Send a Command to All iTerm Panes. Join us this week and enhance your development skills!

Rails HTML preprocessors

In ERB (Embedded Ruby) used in Rails, <% %> is for executing Ruby code without printing the result, while <%= %> executes and prints the result into the HTML. This distinction is crucial for managing the dynamic content display in Rails applications

<% %> will execute the ruby code within the brackets.

<%= %> puts something into erb file.

<%== %> is the same as <%= raw %> which puts something, without escaping it first, into an erb file. (Ruby on Rails Guides.)

<% -%> will not line break after the expression.

<%# %> will comment out code within brackets; and is not sent client side (unlike HTML comments, e.g. <!-- this comment will be sent client side -->).

Visit Ruby Doc for more infos about ERB.

  • Rails
  • Ruby
Katie Linero's profile picture
Katie Linero

Senior Software Engineer


Creating a basic Rails generator

While Rails provides many built-in generators to assist in building an application, you can also create your own custom generators to use with the rails generate command.

Create your generator class, e.g. lib/generators/nothing_generator.rb:

class NothingGenerator < Rails::Generators::Base
end

Note: If our generator inherits from Rails::Generators::NamedBase instead of Rails::Generators::Base, it will require at least one argument in the command line (rails g nothing name instead of rails g nothing), which will be magically available to our generator in the name variable.

Creating the file in lib/generators/ and having the class inherit from Rails::Generators::Base (or one of its subclasses) is all that Rails needs to make the rails generate nothing command available (even if it does nothing yet)!

A generator is capable of generating new files, either from simple string inputs or from complex templates that allow for things like variable interpolation.

To create a file from a string input, use the create_file Thor action:

class ThingGenerator < Rails::Generators::Base
	def create_thing_file
		create_file 'app/thing.rb', '# This creates a file containing this line <-'
	end
end

To create a file from a template, use the template Thor action:

class ThingGenerator < Rails::Generators::NamedBase
	source_root File.expand_path('templates', __dir__)

	def copy_thing_file
		template 'thing.tt', 'app/thing_named_#{name}.rb'
	end
end

In this example, we are inheriting from Rails::Generators::NamedBase to get a name when the generate command is run; we will then use that name to set the name of the file we are creating.

The source_root tells the generator where to look for template files. In our case, if our generator is in lib/generators/thing_generator.rb, we should put our template in lib/generators/templates/thing.tt for the generator to find it. Also note that our template file's extension is .tt (Thor template).

We can also use the name variable (as well as any other variables/methods from our generator) within our template file itself. For example:

# lib/generators/thing_generator.rb
class ThingGenerator < Rails::Generators::NamedBase
	source_root File.expand_path('templates', __dir__)

	def copy_thing_file
		template 'thing.tt', 'app/#{name}.rb'
	end

	private

	def name_as_class_name
		name.classify
	end
end
# lib/generators/templates/thing.tt
class <%= name_as_class_name %>
	# This is a thing created with the name <%= name %>
end

Thor templates use a ERB-like syntax for interpolation, so the output of rails g thing cats_and_dogs here will be:

# app/cats_and_dogs.rb
class CatsAndDogs
	# This is a thing created with the name cats_and_dogs
end

  • Rails
  • Ruby
Katie Linero's profile picture
Katie Linero

Senior Software Engineer


useEffect and Animations

const logoOpacity = new Animated.Value(0)
  const logoOpacityListener = result => {
    const { value } = result

    if (value === 1) {
      props.navigation.navigate("OnboardingIdentity")
      logoOpacity.removeAllListeners()
    }
  }

useEffect(() => {
    logoOpacity.addListener(logoOpacityListener)
    Animated.timing(
      // Animate value over time
      logoOpacity, // The value to drive
      {
        toValue: 1, // Animate to final value of 1
        duration: 1000,
      },
    ).start()
  }, [])

...

return (
    <Animated.View
        style={{
          opacity: logoOpacity,
        }}
      >
        <Icon
          icon="logoWord"
          style={{
            height: 27,
            marginTop: 15,
            resizeMode: "contain",
            width: 183,
          }}
        />
		</Animated.View>
)

For a deeper dive, visit Marisa's blog post: Animating with useEffect in React.

  • React
Marisa Gomez's profile picture
Marisa Gomez

Senior Software Engineer


Heroku, Django, Webpack and Collectstatic

Heroku runs collectstatic for you when you've properly configured static files in your Django application. This is cool, because before you'd have to get crafty with getting this command to run after your application completes the build. There was even once a Heroku buildpack that you added to a project just to run collectstatic after the main Python buildpack had completed.

Unfortunately, this isn't as helpful if you're using node and likely webpack to compile assets as part of the same build pipeline. What will happen is that Heroku will detect your Python app first, build it, run collectstatic, and then move on to your node buildpack. This means that collectstatic runs before your assets have been compiled and Django throws a 500 cause it can't find the stylesheet and main JS entrypoint.

But it's okay, we can handle this. Heroku will default to looking for a build command in your npm scripts but they also give us a unique command that it will use exclusively to build your node app; heroku-postbuild.

So the solution? Add && python manage.py collectstatic to the end of your npm build!

If your build command looks like: webpack -p --config webpack.prod.config.js. Then create a heroku-postbuild that looks like:

webpack -p --config webpack.prod.config.js && python manage.py collectstatic --noinput

Now collectstatic will run after you've compiled assets, and it will move them to the correct static file directory and add them to the manifest! Problem solved.

(I recommend using heroku-postbuild as a way to separate concerns. This will only run on Heroku, and you don't want to mess with existing CI that's already using your build command as is.)

To further optimize this, you can disable the automated collectstatic by adding the env variable DISABLE_COLLECTSTATIC = 1 to your project's config vars.

This way it will only run once... when you've told it to :)

Resources

  • Django
  • Heroku
  • Webpack
Frank Valcarcel's profile picture
Frank Valcarcel

Cofounder, Director of Operations


Send a command to all iTerm panes

You can run a command in all of your iTerm panes at the same time with:

⌘Command + ⇧Shift + I

  • Iterm
Adam Scarano's profile picture
Adam Scarano

Software Engineer


Get Flakey Tests to Fail

When trying to fix a flakey test in rails you can run:

while bundle exec rspec spec; do :; done

This will run you test or test suite until RSpec fails and returns a non-zero exit code.

  • Rails
  • rspec
Adam Scarano's profile picture
Adam Scarano

Software Engineer

Related Posts