se

A panel on accessibility, design inclusion and ethics, hiring and retaining diverse talent, and landing a job in UX.

It’s one thing to seek diverse talent to add to your team, another to retain the people you’ve hired. Why do so many folks we bring in to add depth and breadth of experience to our design and business decision-making process end up leaving? Hear thoughtful, useful answers to this question and other mysteries of […]

The post A panel on accessibility, design inclusion and ethics, hiring and retaining diverse talent, and landing a job in UX. appeared first on Zeldman on Web & Interaction Design.




se

Preparing for the Future with React Prereleases

To share upcoming changes with our partners in the React ecosystem, we’re establishing official prerelease channels. We hope this process will help us make changes to React with confidence, and give developers the opportunity to try out experimental features.

This post will be most relevant to developers who work on frameworks, libraries, or developer tooling. Developers who use React primarily to build user-facing applications should not need to worry about our prerelease channels.

React relies on a thriving open source community to file bug reports, open pull requests, and submit RFCs. To encourage feedback, we sometimes share special builds of React that include unreleased features.

Because the source of truth for React is our public GitHub repository, it’s always been possible to build a copy of React that includes the latest changes. However it’s much easier for developers to install React from npm, so we occasionally publish prerelease builds to the npm registry. A recent example is the 16.7 alpha, which included an early version of the Hooks API.

We would like to make it even easier for developers to test prerelease builds of React, so we’re formalizing our process with three separate release channels.

Release Channels

The information in this post is also available on our Release Channels page. We will update that document whenever there are changes to our release process.

Each of React’s release channels is designed for a distinct use case:

  • Latest is for stable, semver React releases. It’s what you get when you install React from npm. This is the channel you’re already using today. Use this for all user-facing React applications.
  • Next tracks the master branch of the React source code repository. Think of these as release candidates for the next minor semver release. Use this for integration testing between React and third party projects.
  • Experimental includes experimental APIs and features that aren’t available in the stable releases. These also track the master branch, but with additional feature flags turned on. Use this to try out upcoming features before they are released.

All releases are published to npm, but only Latest uses semantic versioning. Prereleases (those in the Next and Experimental channels) have versions generated from a hash of their contents, e.g. 0.0.0-1022ee0ec for Next and 0.0.0-experimental-1022ee0ec for Experimental.

The only officially supported release channel for user-facing applications is Latest. Next and Experimental releases are provided for testing purposes only, and we provide no guarantees that behavior won’t change between releases. They do not follow the semver protocol that we use for releases from Latest.

By publishing prereleases to the same registry that we use for stable releases, we are able to take advantage of the many tools that support the npm workflow, like unpkg and CodeSandbox.

Latest Channel

Latest is the channel used for stable React releases. It corresponds to the latest tag on npm. It is the recommended channel for all React apps that are shipped to real users.

If you’re not sure which channel you should use, it’s Latest. If you’re a React developer, this is what you’re already using.

You can expect updates to Latest to be extremely stable. Versions follow the semantic versioning scheme. Learn more about our commitment to stability and incremental migration in our versioning policy.

Next Channel

The Next channel is a prerelease channel that tracks the master branch of the React repository. We use prereleases in the Next channel as release candidates for the Latest channel. You can think of Next as a superset of Latest that is updated more frequently.

The degree of change between the most recent Next release and the most recent Latest release is approximately the same as you would find between two minor semver releases. However, the Next channel does not conform to semantic versioning. You should expect occasional breaking changes between successive releases in the Next channel.

Do not use prereleases in user-facing applications.

Releases in Next are published with the next tag on npm. Versions are generated from a hash of the build’s contents, e.g. 0.0.0-1022ee0ec.

Using the Next Channel for Integration Testing

The Next channel is designed to support integration testing between React and other projects.

All changes to React go through extensive internal testing before they are released to the public. However, there are myriad environments and configurations used throughout the React ecosystem, and it’s not possible for us to test against every single one.

If you’re the author of a third party React framework, library, developer tool, or similar infrastructure-type project, you can help us keep React stable for your users and the entire React community by periodically running your test suite against the most recent changes. If you’re interested, follow these steps:

  • Set up a cron job using your preferred continuous integration platform. Cron jobs are supported by both CircleCI and Travis CI.
  • In the cron job, update your React packages to the most recent React release in the Next channel, using next tag on npm. Using the npm cli:

    npm update react@next react-dom@next

    Or yarn:

    yarn upgrade react@next react-dom@next
  • Run your test suite against the updated packages.
  • If everything passes, great! You can expect that your project will work with the next minor React release.
  • If something breaks unexpectedly, please let us know by filing an issue.

A project that uses this workflow is Next.js. (No pun intended! Seriously!) You can refer to their CircleCI configuration as an example.

Experimental Channel

Like Next, the Experimental channel is a prerelease channel that tracks the master branch of the React repository. Unlike Next, Experimental releases include additional features and APIs that are not ready for wider release.

Usually, an update to Next is accompanied by a corresponding update to Experimental. They are based on the same source revision, but are built using a different set of feature flags.

Experimental releases may be significantly different than releases to Next and Latest. Do not use Experimental releases in user-facing applications. You should expect frequent breaking changes between releases in the Experimental channel.

Releases in Experimental are published with the experimental tag on npm. Versions are generated from a hash of the build’s contents, e.g. 0.0.0-experimental-1022ee0ec.

What Goes Into an Experimental Release?

Experimental features are ones that are not ready to be released to the wider public, and may change drastically before they are finalized. Some experiments may never be finalized — the reason we have experiments is to test the viability of proposed changes.

For example, if the Experimental channel had existed when we announced Hooks, we would have released Hooks to the Experimental channel weeks before they were available in Latest.

You may find it valuable to run integration tests against Experimental. This is up to you. However, be advised that Experimental is even less stable than Next. We do not guarantee any stability between Experimental releases.

How Can I Learn More About Experimental Features?

Experimental features may or may not be documented. Usually, experiments aren’t documented until they are close to shipping in Next or Stable.

If a feature is not documented, they may be accompanied by an RFC.

We will post to the React blog when we’re ready to announce new experiments, but that doesn’t mean we will publicize every experiment.

You can always refer to our public GitHub repository’s history for a comprehensive list of changes.




se

Building Great User Experiences with Concurrent Mode and Suspense

At React Conf 2019 we announced an experimental release of React that supports Concurrent Mode and Suspense. In this post we’ll introduce best practices for using them that we’ve identified through the process of building the new facebook.com.

This post will be most relevant to people working on data fetching libraries for React.

It shows how to best integrate them with Concurrent Mode and Suspense. The patterns introduced here are based on Relay — our library for building data-driven UIs with GraphQL. However, the ideas in this post apply to other GraphQL clients as well as libraries using REST or other approaches.

This post is aimed at library authors. If you’re primarily an application developer, you might still find some interesting ideas here, but don’t feel like you have to read it in its entirety.

Talk Videos

If you prefer to watch videos, some of the ideas from this blog post have been referenced in several React Conf 2019 presentations:

This post presents a deeper dive on implementing a data fetching library with Suspense.

Putting User Experience First

The React team and community has long placed a deserved emphasis on developer experience: ensuring that React has good error messages, focusing on components as a way to reason locally about app behavior, crafting APIs that are predictable and encourage correct usage by design, etc. But we haven’t provided enough guidance on the best ways to achieve a great user experience in large apps.

For example, the React team has focused on framework performance and providing tools for developers to debug and tune application performance (e.g. React.memo). But we haven’t been as opinionated about the high-level patterns that make the difference between fast, fluid apps and slow, janky ones. We always want to ensure that React remains approachable to new users and supports a variety of use-cases — not every app has to be “blazing” fast. But as a community we can and should aim high. We should make it as easy as possible to build apps that start fast and stay fast, even as they grow in complexity, for users on varying devices and networks around the world.

Concurrent Mode and Suspense are experimental features that can help developers achieve this goal. We first introduced them at JSConf Iceland in 2018, intentionally sharing details very early to give the community time to digest the new concepts and to set the stage for subsequent changes. Since then we’ve completed related work, such as the new Context API and the introduction of Hooks, which are designed in part to help developers naturally write code that is more compatible with Concurrent Mode. But we didn’t want to implement these features and release them without validating that they work. So over the past year, the React, Relay, web infrastructure, and product teams at Facebook have all collaborated closely to build a new version of facebook.com that deeply integrates Concurrent Mode and Suspense to create an experience with a more fluid and app-like feel.

Thanks to this project, we’re more confident than ever that Concurrent Mode and Suspense can make it easier to deliver great, fast user experiences. But doing so requires rethinking how we approach loading code and data for our apps. Effectively all of the data-fetching on the new facebook.com is powered by Relay Hooks — new Hooks-based Relay APIs that integrate with Concurrent Mode and Suspense out of the box.

Relay Hooks — and GraphQL — won’t be for everyone, and that’s ok! Through our work on these APIs we’ve identified a set of more general patterns for using Suspense. Even if Relay isn’t the right fit for you, we think the key patterns we’ve introduced with Relay Hooks can be adapted to other frameworks.

Best Practices for Suspense

It’s tempting to focus only on the total startup time for an app — but it turns out that users’ perception of performance is determined by more than the absolute loading time. For example, when comparing two apps with the same absolute startup time, our research shows that users will generally perceive the one with fewer intermediate loading states and fewer layout changes as having loaded faster. Suspense is a powerful tool for carefully orchestrating an elegant loading sequence with a few, well-defined states that progressively reveal content. But improving perceived performance only goes so far — our apps still shouldn’t take forever to fetch all of their code, data, images, and other assets.

The traditional approach to loading data in React apps involves what we refer to as “fetch-on-render”. First we render a component with a spinner, then fetch data on mount (componentDidMount or useEffect), and finally update to render the resulting data. It’s certainly possible to use this pattern with Suspense: instead of initially rendering a placeholder itself, a component can “suspend” — indicate to React that it isn’t ready yet. This will tell React to find the nearest ancestor <Suspense fallback={<Placeholder/>}>, and render its fallback instead. If you watched earlier Suspense demos this example may feel familiar — it’s how we originally imagined using Suspense for data-fetching.

It turns out that this approach has some limitations. Consider a page that shows a social media post by a user, along with comments on that post. That might be structured as a <Post> component that renders both the post body and a <CommentList> to show the comments. Using the fetch-on-render approach described above to implement this could cause sequential round trips (sometimes referred to as a “waterfall”). First the data for the <Post> component would be fetched and then the data for <CommentList> would be fetched, increasing the time it takes to show the full page.

There’s also another often-overlooked downside to this approach. If <Post> eagerly requires (or imports) the <CommentList> component, our app will have to wait to show the post body while the code for the comments is downloading. We could lazily load <CommentList>, but then that would delay fetching comments data and increase the time to show the full page. How do we resolve this problem without compromising on the user experience?

Render As You Fetch

The fetch-on-render approach is widely used by React apps today and can certainly be used to create great apps. But can we do even better? Let’s step back and consider our goal.

In the above <Post> example, we’d ideally show the more important content — the post body — as early as possible, without negatively impacting the time to show the full page (including comments). Let’s consider the key constraints on any solution and look at how we can achieve them:

  • Showing the more important content (the post body) as early as possible means that we need to load the code and data for the view incrementally. We don’t want to block showing the post body on the code for <CommentList> being downloaded, for example.
  • At the same time we don’t want to increase the time to show the full page including comments. So we need to start loading the code and data for the comments as soon as possible, ideally in parallel with loading the post body.

This might sound difficult to achieve — but these constraints are actually incredibly helpful. They rule out a large number of approaches and spell out a solution for us. This brings us to the key patterns we’ve implemented in Relay Hooks, and that can be adapted to other data-fetching libraries. We’ll look at each one in turn and then see how they add up to achieve our goal of fast, delightful loading experiences:

  1. Parallel data and view trees
  2. Fetch in event handlers
  3. Load data incrementally
  4. Treat code like data

Parallel Data and View Trees

One of the most appealing things about the fetch-on-render pattern is that it colocates what data a component needs with how to render that data. This colocation is great — an example of how it makes sense to group code by concerns and not by technologies. All the issues we saw above were due to when we fetch data in this approach: upon rendering. We need to be able to fetch data before we’ve rendered the component. The only way to achieve that is by extracting the data dependencies into parallel data and view trees.

Here’s how that works in Relay Hooks. Continuing our example of a social media post with body and comments, here’s how we might define it with Relay Hooks:

// Post.js
function Post(props) {
  // Given a reference to some post - `props.post` - *what* data
  // do we need about that post?
  const postData = useFragment(graphql`
    fragment PostData on Post @refetchable(queryName: "PostQuery") {
      author
      title
      # ...  more fields ...
    }
  `, props.post);

  // Now that we have the data, how do we render it?
  return (
    <div>
      <h1>{postData.title}</h1>
      <h2>by {postData.author}</h2>
      {/* more fields  */}
    </div>
  );
}

Although the GraphQL is written within the component, Relay has a build step (Relay Compiler) that extracts these data-dependencies into separate files and aggregates the GraphQL for each view into a single query. So we get the benefit of colocating concerns, while at runtime having parallel data and view trees. Other frameworks could achieve a similar effect by allowing developers to define data-fetching logic in a sibling file (maybe Post.data.js), or perhaps integrate with a bundler to allow defining data dependencies with UI code and automatically extracting it, similar to Relay Compiler.

The key is that regardless of the technology we’re using to load our data — GraphQL, REST, etc — we can separate what data to load from how and when to actually load it. But once we do that, how and when do we fetch our data?

Fetch in Event Handlers

Imagine that we’re about to navigate from a list of a user’s posts to the page for a specific post. We’ll need to download the code for that page — Post.js — and also fetch its data.

Waiting until we render the component has problems as we saw above. The key is to start fetching code and data for a new view in the same event handler that triggers showing that view. We can either fetch the data within our router — if our router supports preloading data for routes — or in the click event on the link that triggered the navigation. It turns out that the React Router folks are already hard at work on building APIs to support preloading data for routes. But other routing frameworks can implement this idea too.

Conceptually, we want every route definition to include two things: what component to render and what data to preload, as a function of the route/url params. Here’s what such a route definition might look like. This example is loosely inspired by React Router’s route definitions and is primarily intended to demonstrate the concept, not a specific API:

// PostRoute.js (GraphQL version)

// Relay generated query for loading Post data
import PostQuery from './__generated__/PostQuery.graphql';

const PostRoute = {
  // a matching expression for which paths to handle
  path: '/post/:id',

  // what component to render for this route
  component: React.lazy(() => import('./Post')),

  // data to load for this route, as function of the route
  // parameters
  prepare: routeParams => {
    // Relay extracts queries from components, allowing us to reference
    // the data dependencies -- data tree -- from outside.
    const postData = preloadQuery(PostQuery, {
      postId: routeParams.id,
    });

    return { postData };
  },
};

export default PostRoute;

Given such a definition, a router can:

  • Match a URL to a route definition.
  • Call the prepare() function to start loading that route’s data. Note that prepare() is synchronous — we don’t wait for the data to be ready, since we want to start rendering more important parts of the view (like the post body) as quickly as possible.
  • Pass the preloaded data to the component. If the component is ready — the React.lazy dynamic import has completed — the component will render and try to access its data. If not, React.lazy will suspend until the code is ready.

This approach can be generalized to other data-fetching solutions. An app that uses REST might define a route like this:

// PostRoute.js (REST version)

// Manually written logic for loading the data for the component
import PostData from './Post.data';

const PostRoute = {
  // a matching expression for which paths to handle
  path: '/post/:id',

  // what component to render for this route
  component: React.lazy(() => import('./Post')),

  // data to load for this route, as function of the route
  // parameters
  prepare: routeParams => {
    const postData = preloadRestEndpoint(
      PostData.endpointUrl, 
      {
        postId: routeParams.id,
      },
    );
    return { postData };
  },
};

export default PostRoute;

This same approach can be employed not just for routing, but in other places where we show content lazily or based on user interaction. For example, a tab component could eagerly load the first tab’s code and data, and then use the same pattern as above to load the code and data for other tabs in the tab-change event handler. A component that displays a modal could preload the code and data for the modal in the click handler that triggers opening the modal, and so on.

Once we’ve implemented the ability to start loading code and data for a view independently, we have the option to go one step further. Consider a <Link to={path} /> component that links to a route. If the user hovers over that link, there’s a reasonable chance they’ll click it. And if they press the mouse down, there’s an even better chance that they’ll complete the click. If we can load code and data for a view after the user clicks, we can also start that work before they click, getting a head start on preparing the view.

Best of all, we can centralize that logic in a few key places — a router or core UI components — and get any performance benefits automatically throughout our app. Of course preloading isn’t always beneficial. It’s something an application would tune based on the user’s device or network speed to avoid eating up user’s data plans. But the pattern here makes it easier to centralize the implementation of preloading and the decision of whether to enable it or not.

Load Data Incrementally

The above patterns — parallel data/view trees and fetching in event handlers — let us start loading all the data for a view earlier. But we still want to be able to show more important parts of the view without waiting for all of our data. At Facebook we’ve implemented support for this in GraphQL and Relay in the form of some new GraphQL directives (annotations that affect how/when data is delivered, but not what data). These new directives, called @defer and @stream, allow us to retrieve data incrementally. For example, consider our <Post> component from above. We want to show the body without waiting for the comments to be ready. We can achieve this with @defer and <Suspense>:

// Post.js
function Post(props) {
  const postData = useFragment(graphql`
    fragment PostData on Post {
      author
      title

      # fetch data for the comments, but don't block on it being ready
      ...CommentList @defer
    }
  `, props.post);

  return (
    <div>
      <h1>{postData.title}</h1>
      <h2>by {postData.author}</h2>
      {/* @defer pairs naturally with <Suspense> to make the UI non-blocking too */}
      <Suspense fallback={<Spinner/>}>
        <CommentList post={postData} />
      </Suspense>
    </div>
  );
}

Here, our GraphQL server will stream back the results, first returning the author and title fields and then returning the comment data when it’s ready. We wrap <CommentList> in a <Suspense> boundary so that we can render the post body before <CommentList> and its data are ready. This same pattern can be applied to other frameworks as well. For example, apps that call a REST API might make parallel requests to fetch the body and comments data for a post to avoid blocking on all the data being ready.

Treat Code Like Data

But there’s one thing that’s still missing. We’ve shown how to preload data for a route — but what about code? The example above cheated a bit and used React.lazy. However, React.lazy is, as the name implies, lazy. It won’t start downloading code until the lazy component is actually rendered — it’s “fetch-on-render” for code!

To solve this, the React team is considering APIs that would allow bundle splitting and eager preloading for code as well. That would allow a user to pass some form of lazy component to a router, and for the router to trigger loading the code alongside its data as early as possible.

Putting It All Together

To recap, achieving a great loading experience means that we need to start loading code and data as early as possible, but without waiting for all of it to be ready. Parallel data and view trees allow us to load the data for a view in parallel with loading the view (code) itself. Fetching in an event handler means we can start loading data as early as possible, and even optimistically preload a view when we have enough confidence that a user will navigate to it. Loading data incrementally allows us to load important data earlier without delaying the fetching of less important data. And treating code as data — and preloading it with similar APIs — allows us to load it earlier too.

Using These Patterns

These patterns aren’t just ideas — we’ve implemented them in Relay Hooks and are using them in production throughout the new facebook.com (which is currently in beta testing). If you’re interested in using or learning more about these patterns, here are some resources:

  • The React Concurrent docs explore how to use Concurrent Mode and Suspense and go into more detail about many of these patterns. It’s a great resource to learn more about the APIs and use-cases they support.
  • The experimental release of Relay Hooks implements the patterns described here.
  • We’ve implemented two similar example apps that demonstrate these concepts:

    • The Relay Hooks example app uses GitHub’s public GraphQL API to implement a simple issue tracker app. It includes nested route support with code and data preloading. The code is fully commented — we encourage cloning the repo, running the app locally, and exploring how it works.
    • We also have a non-GraphQL version of the app that demonstrates how these concepts can be applied to other data-fetching libraries.

While the APIs around Concurrent Mode and Suspense are still experimental, we’re confident that the ideas in this post are proven by practice. However, we understand that Relay and GraphQL aren’t the right fit for everyone. That’s ok! We’re actively exploring how to generalize these patterns to approaches such as REST, and are exploring ideas for a more generic (ie non-GraphQL) API for composing a tree of data dependencies. In the meantime, we’re excited to see what new libraries will emerge that implement the patterns described in this post to make it easier to build great, fast user experiences.




se

It's time to upgrade those Ruby 2.4 apps

#497 — April 16, 2020

Read on the Web

Ruby Weekly

Bye Bye Ruby 2.4, Support Has Ended — From the end of April 2019 till now, Ruby 2.4 has been in its ‘security maintenance’ phase but now you won’t even get that, Ruby 2.4.10 should be the final 2.4 release. 2.5 will follow in 2.4’s footsteps next year, so upgrading to 2.6 or 2.7 should now be a priority for those older apps.

Ruby Core Team

Testing Ruby Decorators with super_method — Have you ever wondered how you can properly test the behavior of a method overridden by Module#prepend? Enter super_method which returns a Method object of which superclass method would be called when super is used or nil if none exists.

Simone Bravo

You Hacked the Gibson? Yeah, They Built Their Own Login — Don't let Crash Override pwn your app. FusionAuth adds secure login, registration and user management to your app in minutes not months. Download our community edition for free.

FusionAuth sponsor

Heya: A Sequence Mailer for Rails — “Think of it like ActionMailer, but for timed email sequences.” Note: It’s open source but not free for commercial use beyond a certain point.

Honeybadger Industries LLC

A Final Report on Ruby Concurrency Developments — A report on work funded by a 2019 Ruby Association Grant that puts forth a proposal of using non-blocking fibers to improve Ruby’s concurrency story.

Samuel Williams

Mocking in Ruby with Minitest — Minitest has basic mocking functionality baked in, but be judicious in your use of it.

Heidar Bernhardsson

???? Jobs

Ruby Backend Developer (Austria) — We’re seeking mid-level and senior devs to join us and build top-class backend infrastructure for our adidas apps, used by millions. Our stack includes: jRuby, Sinatra, Sidekiq, MySQL, & MongoDB.

Runtastic

Find a Job Through Vettery — Vettery specializes in tech roles and is completely free for job seekers. Create a profile to get started.

Vettery

▶️ Get ready for your next role: Pluralsight is free for the entire month of April. Stay Home. Skill Up. #FreeApril — SPONSORED

???? Articles & Tutorials

Predicting the Future With Linear Regression in Ruby — Linear regression is a mathematical approach to modelling a relationship between multiple variables and is demonstrated here by exploring whether the tempo of a song predicts its popularity on Spotify.

Julie Kent

Feature Flags: A Simple Way to 'De-Stress' Production Releases — Feature flags bridge a gap between the abstract concept of continuous delivery and tactical release of features.

Matt Swanson

A Guide to Deprecation Warnings in Rails — If you’ve upgraded Rails and you start seeing warnings screaming at you, you can either get Googling or.. read this ????

Luciano Becerra

What's the Difference Between Monitoring Webhooks and Background Jobs

AppSignal sponsor

Understanding webpacker.yml — Have you ever really gone through the Webpack config?

Ross Kaffenberger

Using Optimizer Hints in Rails — Rails 6 removes the need to write raw SQL to use optimizer hints, so that’s cool.

Prateek Choudhary

Dissecting Rails Migrations — You should pick up something new about migrations by reading this article as it covers all of the essentials and a little more.

Prathamesh Sonpatki

The Basics of Custom Exception Handling — Never hurts to revise the basics of effective exceptions.

Mark Michon

How to Improve Code Readability with Closures

Andrey Koleshko

???? Code and Tools

ruby-prolog: A Pure Ruby Prolog-like DSL for Logical Programming — Solve complex logic problems on the fly using a dynamic, Prolog-like DSL inline with your normal code.

Preston Lee

Anyway Config: Keep Your Ruby Configuration Sensible — Get your Ruby project out of ‘ENV Hell’ with anyway_config, a framework for managing configuration.

Vladimir Dementyev

The End of Heroku Alerts — Rails Autoscale keeps your app healthy. Simple and effective autoscaling for Web, Sidekiq, Delayed Job, and Que.

Rails Autoscale sponsor

Tomo 1.0: A Friendly CLI for Deploying Rails Apps — There’s a short tutorial for deploying Rails, and the documentation is thorough.

Matt Brictson

ActiveLdap 6.0: An Object Oriented Interface to LDAP — A very long standing project (16 years!) that has just had an update. LDAP stands for Lightweight Directory Access Protocol and while I don’t hear about it much anymore, it has plenty of established use cases.

Sutou Kouhei

Elasticsearch Integrations for ActiveModel/Record and Rails

Elastic

RubyMine 2020.1 Released

Natalie Kudanova




se

Stimulus Reflex, and sending thanks to Matz

#498 — April 23, 2020

Read on the Web

Ruby Weekly

Credit: Divina Epiphania / Shutterstock.com

Mining for Malicious Ruby Gems: 700+ Gems Affected — Breathe easy as this was all resolved a month ago (and was too obscure to pay off for the hackers anyway) but a security research team recently found over 700 malicious Ruby gems that were subtle typos/adjustments of more popular gems (e.g. atlas-client vs atlas_client – could you tell which one is real?)

Tomislav Maljic

You Can Now Sponsor Matz on GitHub — I appreciate these are challenging times, but if you’ve ever wanted to give a big thank you to Matz, the creator of Ruby, here’s one way to do it. We’re sponsoring Matz now as without him, this newsletter wouldn’t exist! ???? Alternatively, if you have little to spare, maybe send him a thanks on Twitter?

GitHub Sponsors

Ruby Performance Tips — Here’s a collection of practical tips for improving Ruby performance for better user experiences, brought to you by Raygun. Read the tips here.

Raygun sponsor

Full Text Search in Milliseconds with Rails and Postgres — If you’ve never played with full text search with Postgres and Rails, this is a fine place to start. It covers LIKE/ILIKE, trigrams, and ‘proper’ full text searching. We also get to see how Leigh took a query from taking 130ms down to 7ms.

Leigh Halliday

▶  Introduction to Stimulus Reflex — Stimiulus Reflex makes SPA-type interactions very simple by using ActionCable to render pages and then diffing them on the client.

GoRails

Rails Performance: When is Caching the Right Choice? — Before you say “always”, understand that caching is not free and, if done incorrectly, can even make things worse.

Jonathan Miles

???? Jobs

Find a Job Through Vettery — Vettery specializes in tech roles and is completely free for job seekers. Create a profile to get started.

Vettery

Ruby Backend Developer (Austria) — We’re seeking mid-level and senior devs to join us and build top-class backend infrastructure for our adidas apps, used by millions. Our stack includes: jRuby, Sinatra, Sidekiq, MySQL, & MongoDB.

Runtastic

ℹ️ Interested in running a job listing in Ruby Weekly? There's more info here.

???? Articles & Tutorials

How to Customize Webpack in Rails Apps — How to go about configuring webpack when tweaking webpacker.yml just isn’t enough.

Ross Kaffenberger

RSpec Given/When/Then with Symbols — An interesting, alternative way to structure a BDD feature in RSpec. I think I prefer the underscores but YMMV.

Caius Durling

Looking Inside a Ruby Gem — Piotr decomposes a .gem file which turns out to just be a collection of gzipped and tarred files, only some of which are the code.

Piotr Murach

eBook: The Most Important Events to Monitor in Your Postgres Logs — In this eBook, you will learn about the Top 6 Postgres log events for monitoring query performance and preventing downtime.

pganalyze sponsor

Passing Rails Controller Params to SidekiqActionController::Parameters can give Sidekiq issues.

Prathamesh Sonpatki

Catchup Subscriptions with Rails Event Store

Miroslaw Praglowski

Logic-less Ruby Templates with Mustache

David Santangelo

▶  Discussing Ruby for Good with Sean Marcia — Sean talks about founding Ruby For Good (an event about philanthropic Ruby development) and some of the projects it has been responsible for creating.

Ruby Rogues podcast

???? Code and Tools

Impressionist 2.0: A Plugin to Log Impressions in Rails Apps — Impressionist tracks page views and impressions. v2.0 has just dropped but they’re also are looking for new maintainers, so contact them if you want to get involved.

Charlotte Ruby Group

acli 0.3: A Command Line Client for Action Cable — Interesting on two fronts.. first, because it’s an mruby app, and we don’t see many of those, and second, because it lets you play with Action Cable channels in any easier way.

Vladimir Dementyev

Undercover: A Tool to Stop You Shipping Untested Code — It’s like RuboCop but for code coverage rather than code style.

Jan Grodowski

How to Monitor Your Host Metrics Automatically

AppSignal sponsor

Bridgetown: A Modern Ruby (JAMstack) Web Framework — Bridgetown is a new Ruby-based static-site generator based on a fork of Jekyll. It supports plugins and Webpack, so you can use your front-end framework of choice.

Bridgetown

net-ssh 6.0: A Pure Ruby Implementation of the SSH2 Client Protocol — Yes, you can write programs that invoke and interact with processes on remote servers, via SSH2, all in Ruby.

Buck, Fazekas, et al.




se

Node 14 has been released

#335 — April 23, 2020

Read on the Web

Node Weekly

Node.js 14 Released — Woo-hoo another major release of Node.js is here. v14 now becomes the current ‘release’ line with it becoming a LTS (Long Term Support) release in October.. so production apps would, ideally, remain on v12 for now. So what’s new..?

  • Diagnostic reports are now a stable feature.
  • It's based on V8 8.1.
  • An experimental Async Local Storage API
  • Improvements to streams.
  • An experimental WebAssembly System Interface (WASI) to support future WebAssembly use cases.
  • Bye bye to the ESM module ‘experimental’ warning (though it still is experimental).

Michael Dawson and Bethany Griggs

Learn Hardcore Functional Programming in JavaScript — Join Brian Lonsdorf and learn how to apply such concepts as pure functions, currying, composition, functors, monads and more.

Frontend Masters sponsor

Puppeteer 3.0: Say Hello to Firefox — Best known as a way to headlessly control Chrome from Node, Puppeteer has recently seen some competition in the form of the cross-browser Playwright recently. But competition can be good and Puppeteer now supports Firefox too.

Mathias Bynens

ZEIT Is Now Vercel — You probably best know ZEIT as the creators and maintainers of the popular Next.js React framework and their ‘Now’ deployment and hosting platform.

Vercel

New OpenSSL Security Release To Require Node Updates? Maybe Not.. — A key security update to OpenSSL raised the possibility of widespread Node releases to incorporate the fixes, but initial suggestions are that Node isn’t affected. Fingers crossed!

Sam Roberts

???? Jobs

Node.js Developer at X-Team (Remote) — Join the most energizing community for developers. Work from anywhere with the world's leading brands.

X-Team

Find a Job Through Vettery — Vettery specializes in tech roles and is completely free for job seekers. Create a profile to get started.

Vettery

ℹ️ If you're interested in running a job listing in this newsletter, there's more info here.

???? Articles & Tutorials

OneTesselAway: Building a Real-Time Public Transit Status Device — A developer wanted to know when the next bus would arrive.. while using lots of cool tech, including Node, the OneBusAway API, and the Tessel 2 IoT platform.

Robert McGuire

What is the toJSON() Function? — If an object has a toJSON function, JSON.stringify() calls toJSON() and serializes the return value from toJSON() instead.

Valeri Karpov

Top GitHub Best Practices for Developers - Expanded Guide — Implementing these best practices could save you time, improve code maintainability, and prevent security risks.

Datree.io sponsor

Refactor Your Node and Express APIs to Serverless with Azure Functions — John Papa points out a Microsoft tutorial that walks through the process of taking a Node API serverless with Azure’s Functions service.

John Papa

Querying SQL Server from Node with async/await

Rob Tomlin

Why I Stopped Using Microservices

Robin Wieruch

???? Tools, Resources and Libraries

lazynpm: A Terminal UI for npm — One of those sort of things you don’t realize you need until you give it a go. There’s a four-minute screencast if you want to see how it works without downloading.

Jesse Duffield

node-sqlite3 4.2: Async, Non-blocking SQLite3 Bindings for Node4.2.0 just came out.

Mapbox

ts-gphoto2-driver: A Node Wrapper for libgphoto2libgphoto2 provides a way to control a variety of digital cameras/DSLRs.

Lenzotti Romain

AppSignal Now Supports Node.js: Roadmap for the Coming Weeks

AppSignal sponsor

Rosetta: A General Purpose Internationalization Library in 292 Bytes — Less than 300 bytes, but does have a few dependencies. Aims to be very simple and is targeted at basic string use cases.

Luke Edwards

nodejs-dns 2.0: The Google Cloud DNS Client for Node

Google

node-osc 5.0: Open Sound Control Protocol LibraryOSC is a protocol used to communicate between media devices.

Myles Borins

ts-node: TypeScript Execution and REPL for Node

TypeStrong

???? And One for Fun..

npm trends: Compare NPM Package Downloads — A site to compare package download counts over time. For example, what about koa vs restify vs fastify?

John Potter




se

Caddy 2.0 released, plus a little black hat Go

#311 — May 8, 2020

Unsubscribe  :  Read on the Web

Golang Weekly

Caddy 2: The Go-Powered Web Server with Automatic TLS — After over a year of redesign, Caddy 2 has a new architecture to v1. If you want a new HTTPS server that ‘just works’, Caddy is well worth a look IMO. Its lead creator, Matt Holt, answered lots of questions on this Hacker News thread about the release.

Caddy Web Server

Rek: An Easy HTTP Client for Go — The inspiration here is from Python’s very well known and highly esteemed Requests library.. so the Pythonistas among you might like this!

Luc Perkins

Modern Redis Features with RedisGreen — Online upgrades to the latest Redis 6.0 features, memory mapping, key size tracking, and more.

RedisGreen sponsor

Life Without Line Numbers — There’s a lot of buzz around reducing the size of Go binaries (1.15 does so by ~6%) and here’s another tactic: reduce the precision of the position information. The gain is 2-6%, depending on how far you take it.

Josh Bleecher Snyder

▶  Discussing Black Hat Go“Are you excited to learn about hacking and that?” Got an hour? Roberto Clapis, a security engineer at Google, and Tom Steele, a co-author of Black Hat Go, join the Go Time team to discuss security, penetration testing, and more.

Go Time Podcast

???? Jobs

Enjoy Building Scalable Infrastructure in Go? Stream Is Hiring — Like coding in Go? We do too. Stream is hiring in Amsterdam. Apply now.

Stream

Find a Job Through Vettery — Vettery specializes in tech roles and is completely free for job seekers. Create a profile to get started.

Vettery

???? Articles & Tutorials

Mid-Stack Inlining in Go — Inlining a function can lead to serious performance gains, so why not do it for everything? Well, there are always trade-offs.

Dave Cheney

Asynchronous Preemption in Go 1.14 — How the new preemption implementation works, including the use of a lesser-known signal (SIGURG).

Vincent Blanchon

Why Are My Go Executable Files Larger Than My Source Code? — We built a data visualization tool to find out. Here’s how we built it, and what we learned.

Cockroach Labs sponsor

Accelerating Aggregate MD5 Hashing Up to 800% with AVX512 — The culmination of this work is md5-simd, a Go library that performs such rapid MD5 hashing (when running concurrently). The use cases here are quite restricted but you may appreciate seeing how such things are implemented for any high end SIMD wrangling you need to do one day.

MinIO Blog

▶  A Beginner's Guide to gRPC in Go — There’s a written version of the tutorial if you dislike videos.

TutorialEdge

Four Steps to Daemonize Your Go Programs — Daemons are programs that run as non-interactive background processes (e.g. background job processors, Web servers, database systems).

Ilija Eftimov

Go as a Scripting Language? — There’s plenty of folks that use Go as a scripting language, but there are challenges around REPLs and shebang support. Some of these challenges are being addressed today.

Segio De Simone

???? Code & Tools

UUID 3.3: A Pure Go Implementation of UUIDs — A pure Go implementation of Universally Unique Identifiers (UUID) as defined in RFC-4122 covering versions 1 through 5.

The Go Commune

Reed-Solomon: A Reed-Solomon Erasure Coding Library — A Go port of a Java library built by Backblaze that does Reed Solomon erasure coding (a way to send or store data in a larger form that’s resilient to data loss). Boasts operation of over 1GB/sec per core.

Klaus Post

ko 0.5: Build and Deploy Go Apps on Kubernetes — ko’s objective is to “to make containers invisible infrastructure.” It’s been rapidly maturing in the past few months too.

Google

Monitor the Health and Performance of Your Golang Apps with Datadog APM. Free Trial

Datadog APM sponsor

Tengo 2.2: A Fast Embeddable Script Language for Go — Quite a mature project now and worth a look if you need to add some dynamic scripting to your code.

Daniel Kang

UniPDF 3.7: A Library for Creating and Processing PDF Files — Pure Go, which is neat, but note it’s dual licensed: AGPL for open source, commercial for closed source projects.

UniDoc

Mockery: A Mock Code Generator for Go Interfaces

Vektra

Dynamo: An Expressive DynamoDB Library

Greg Greg

???? Two Fun Side Projects

gasm: An Experimental WASM Virtual Machine for Gophers“I did this just for fun and for learning WASM specification.” Nonetheless, it works with basic examples.

Takeshi Yoneda

thdwb: A Homebrew Web Browser and Rendering Engine — Another experimental, fun learning project. You won’t be using it for your day to day browsing any time soon but projects like this keep the imagination fueled up.

Danilo Fragoso

It'd be quite cool to link to more fun Go experiments and side projects actually, so let us know if you work on any. Bonus points for games, musical, or Web experiences ????




se

'My search for the boy in a child abuse video'

Lucy Proctor was horrified when she was WhatsApped a sex abuse video. And she wanted to find out if the boy was safe.




se

The volunteer army helping self-isolating neighbours

The coronavirus outbreak has left many feeling trapped indoors, but for some help may not be far away.




se

Coronavirus: Where has all the hand sanitiser gone?

Shelves all over the world are empty - it turns out more alcohol is needed, to ramp up production.




se

Extreme piercing: A festival of self-inflicted pain

Since time immemorial, a village in West Bengal has paid tribute to Shiva by self-inflicting pain. This year coronavirus put a stop to it.




se

Stop and search: the controversial police power

Reporter Aaron Roach Bridgeman speaks to suspects, police and campaigners.




se

Electrosensitivity: 'I didn't believe people had it, then it happened to me'

Velma, Emma and Dean believe mobile phone signals, wi-fi and other modern technology makes them ill.




se

Dirty streaming: The internet's big secret

Figures suggest that IT now generates as much CO2 as flying, with some arguing it's nearly double.




se

Sex, Disability, and Sex and Disability

Disability and sex is a topic around which there are a lot of misconceptions, but what do disabled people think when people get awkward talking about sex with them?




se

Bill Gates: Few countries will get 'A-grade' for coronavirus response

The Microsoft billionaire says we find ourselves in uncharted territory with the coronavirus pandemic.




se

Virus vaccine research 'enormously accelerated'

A vaccine normally takes a decade to develop, but GSK and Sanofi want a viable coronavirus vaccine by the end of next year, GSK chief executive Emma Walmsley says.




se

Coronavirus: The unexpected items deemed 'essential'

Cheese shops and gun stores are among the services still open in locked down places around the world.




se

Coronavirus: UK chancellor on new microloan scheme for small businesses

Firms will be able to borrow up to £50,000, which will be interest free for the first year.




se

Coronavirus: Pint delivery service to challenge Belfast ban

A pub delivering Guinness to people's homes during lockdown says it was operating within the law.




se

Coronavirus: Aer Lingus flight had 'no social distancing' says passenger

Sean Mallon's photos of an Aer Lingus Belfast-Heathrow flight showed passengers sitting close together.




se

Coronavirus: Bread and cake tips from a self-isolating baker

Ray normally runs his family bakery, Rinkoffs, but is currently staying at home with his wife.




se

Coronavirus: Disease meets deforestation at heart of Brazil's Amazon

Coronavirus has overwhelmed Manaus, the Amazon's biggest city, and the worst is yet to come.




se

Life for asylum seekers in lockdown on the US-Mexico border

Magaly Contreras has spent nine months in a Tijuana shelter and is worried about her future.




se

The Diverse React Navigation Ecosystem

The routing ecosystem around React and React Native is quite different. One is characterized by a strong incumbent, and the other is plagued by rapid change.

React JS

No question about it, React Router (ReactTraining/react-router) is king here. They have the benefit of several years of active development, along with an active community submitting PR’s, fixes, etc. Supplement that with myriad tutorials and how-to’s and you end up with a well-supported, stable product. To be fair, React Router has suffered some major API upsets, and is nearly the poster-child for javascript fatigue but the maintainers have declared their lasting support for a few specific versions, which means you can plop down with V3 and be good to go for the next 12 to 24 months.

React Native

Ok, this is where things start to get really, really crazy. The most important thing to keep in mind is that the React Native team has produced three navigation helpers: NavigatorIOS, Navigator, and NavigatorExperimental.

  • NavigatorIOS was quickly deprecated, as it was supported only by (you guessed it) IOS.
  • Navigator is the currently endorsed solution for navigation, at least if you are following the official docs. However, its about to be upset by-
  • NavigationExperimental. This is an updated navigator that has learned some lessons from Navigator, and has some solid integration with Redux. ‘Navigator’ is (or was!) sleighted to be deprecated in favor of NavigationExperimental at some point.

Already you have three ‘official’ navigators supported by the React Native team. The big issue with all three of these is that they are somewhat lightweight and don’t include a lot of common navigation situations out of the box, like sidebars, tab bars, headers, etc. To solve that, the community has introduced…

  • React Native Router Flux (aksonov/react-native-router-flux). My personal favorite, this is router is based upon NavigationExperimental. You can imagine that the authors looked at NavigationExperimental, realized that everyone would be writing the same wrapper code around it, and so created this project.
  • React Native Router (t4t5/react-native-router). Haven’t used it, but it is colossally popular.
  • React Router Native (jmurzy/react-router-native). Strives for API conformity with React Router (the above mentioned one). The great approach here is that they bring in the concept of a URL in native apps, where one doesn’t otherwise exist. This is a great approach that simplifies a lot of common routing situations. Of course, there’s one more big solution that is supposedly going to become the standard:
  • React Navigation (react-community/react-navigation). Seen as a solution that will soon be ‘official’ in the community, it is intended to replaced NavigationExperimental. This package is still in active development, so I expect at least a bit of API upset over the coming months. If you want to use official solutions, go with this, if you want a tried and true solution, go with React Native Router Flux.




se

2012 Club World Cup Final: Corinthians 1-0 Chelsea

Corinthians and Chelsea met in the FIFA Club World Cup Cup Japan 2012 final. Watch highlights from the match when the South American champions defeated their European counterparts. 




se

Claudio Gomes of France and Abel Ruiz of Spain pose for photos

GUWAHATI, INDIA - OCTOBER 17: Claudio Gomes of France and Abel Ruiz of Spain pose for photos with referees prior to the FIFA U-17 World Cup India 2017 Round of 16 match between France and Spain at Indira Gandhi Athletic Stadium on October 17, 2017 in Guwahati, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Players of Mali pose for photos during the FIFA U-17 World Cup India 2017 3rd Place

KOLKATA, INDIA - OCTOBER 28: Players of Mali pose for photos during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Yuri Alberto (R) of Brazil celebrates scoring his sides second goal with Rodrigo Guth

Yuri Alberto (R) of Brazil celebrates scoring his sides second goal with Rodrigo Guth during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Yuri Alberto of Brazil scores his side's second goal

KOLKATA, INDIA - OCTOBER 28: Yuri Alberto of Brazil scores his side's second goal during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Yuri Alberto of Brazil celebrates scoring his side's second goal

Yuri Alberto of Brazil celebrates scoring his side's second goal during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Yuri Alberto of Brazil celebrates scoring his sides second goal

KOLKATA, INDIA - OCTOBER 28: Yuri Alberto (C) of Brazil celebrates scoring his sides second goal with Rodrigo Guth (L) during the FIFA U-17 World Cup India 2017 3rd Place match between Brazil and Mali at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain scores the opening goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain scores the opening goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates the first goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates the first goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring their second goal

Sergio Gomez of Spain celebrates scoring their second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Serio Gomez of Spain celebrates after scoring a goal against England

Serio Gomez of Spain celebrates after scoring a goal against England during their final FIFA U-17 World Cup football match at the Vivekananda Yuba Bharati Krirangan stadium in Kolkata on October 28, 2017. / AFP / Dibyangshu SARKAR




se

Sergio Gomez of Spain celebrates scoring their second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates scoring their second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring their second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates scoring their second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring their second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates scoring their second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain scores their second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain scores their second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates a scored goal with his teammates

Sergio Gomez of Spain celebrates a scored goal with his teammates during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring his sides second goal

Sergio Gomez of Spain celebrates scoring his sides second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring his sides second goal

Sergio Gomez of Spain celebrates scoring his sides second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates a scored goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates a scored goal with his teammates during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates a scored goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates a scored goal with his teammates during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Buda Mendes - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring his sides second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates scoring his sides second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




se

Team of Spain pose for a group photograph

KOLKATA, INDIA - OCTOBER 28: Team of Spain pose for a group photograph during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain scores his sides second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain scores his sides second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




se

Sergio Gomez of Spain celebrates scoring his sides second goal

KOLKATA, INDIA - OCTOBER 28: Sergio Gomez of Spain celebrates scoring his sides second goal during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Jan Kruger - FIFA/FIFA via Getty Images)




se

Tashan Oakley-Boothe of England and Sergio Gomez of Spain in action

KOLKATA, INDIA - OCTOBER 28: Tashan Oakley-Boothe of England and Sergio Gomez of Spain in action during the FIFA U-17 World Cup India 2017 Final match between England and Spain at Vivekananda Yuba Bharati Krirangan on October 28, 2017 in Kolkata, India. (Photo by Tom Dulat - FIFA/FIFA via Getty Images)