{"id":55358,"date":"2020-12-15T10:14:49","date_gmt":"2020-12-15T18:14:49","guid":{"rendered":"https:\/\/github.blog\/?p=55358"},"modified":"2021-12-20T14:44:52","modified_gmt":"2021-12-20T22:44:52","slug":"encapsulating-ruby-on-rails-views","status":"publish","type":"post","link":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/","title":{"rendered":"Encapsulating Ruby on Rails views"},"content":{"rendered":"<p>With the recent release of version 6.1, Ruby on Rails now supports the\u00a0<a href=\"https:\/\/guides.rubyonrails.org\/layouts_and_rendering.html#rendering-objects\" rel=\"nofollow\">rendering of objects<\/a>\u00a0that respond to\u00a0<code>render_in<\/code>, a change\u00a0<a href=\"https:\/\/github.com\/rails\/rails\/pull\/36388\">we<\/a>\u00a0<a href=\"https:\/\/github.com\/rails\/rails\/pull\/37919\">introduced<\/a>\u00a0to the framework. It may be small (the two pull requests were less than a dozen lines), but this change has enabled us to develop a framework for building encapsulated views called\u00a0<a href=\"https:\/\/github.com\/github\/view_component\">ViewComponent<\/a>.<\/p>\n<h2 ><a class=\"heading-link\" href=\"#\"><a id=\"user-content-why-encapsulation-matters\" class=\"anchor\" href=\"https:\/\/gist.github.com\/leereilly\/4ef2395d9a6d72aa02341f00029afabe#why-encapsulation-matters\" aria-hidden=\"true\"><\/a>Why encapsulation matters<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Unlike models and controllers, Rails views are not encapsulated. All Rails views in an application exist in a single execution context, meaning they can share state. This makes them hard to reason about and difficult to test, as they cannot be easily isolated.<\/p>\n<p>The need for a new way of building views in our application emerged as the number of templates in the GitHub application grew into the thousands. We depended on a combination of presenters and partials with inline Ruby, tested by expensive integration tests that exercise the routing and controller layers in addition to the view layer.<\/p>\n<p>Inspired by our experience building component-based UI with\u00a0<a href=\"https:\/\/primer.style\/components\" rel=\"nofollow\">React<\/a>, we set off to build a framework to bring these ideas to server-rendered Rails views.<\/p>\n<h2 ><a class=\"heading-link\" href=\"#\"><a id=\"user-content-enter-viewcomponent\" class=\"anchor\" href=\"https:\/\/gist.github.com\/leereilly\/4ef2395d9a6d72aa02341f00029afabe#enter-viewcomponent\" aria-hidden=\"true\"><\/a>Enter ViewComponent<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>We created the ViewComponent framework for building reusable, testable &amp; encapsulated view components in Ruby on Rails. A ViewComponent is the combination of a Ruby file and a template file. For example:<\/p>\n<p><strong>test_component.rb<\/strong><\/p>\n<pre><code class=\"ruby\">class TestComponent &lt; ViewComponent::Base\n  def initialize(title:)\n    @title = title\n  end\nend\n<\/code><\/pre>\n<p><strong>test_component.html.erb<\/strong><\/p>\n<pre><code class=\"ruby\">&lt;span title=\"&lt;%= @title %&gt;\"&gt;\n  &lt;%= content %&gt;\n&lt;\/span&gt;\n<\/code><\/pre>\n<p>Which is rendered in a view:<\/p>\n<pre><code class=\"ruby\">&lt;%= render(TestComponent.new(title: \"my title\")) do %&gt;\n  Hello, World!\n&lt;% end %&gt;<\/code><\/pre>\n<p>Returning:<\/p>\n<pre><code>&lt;span title=\"my title\"&gt;Hello, World!&lt;\/span&gt;<\/code><\/pre>\n<p>Unlike traditional Rails views, ViewComponent templates are executed within the context of the ViewComponent object, encapsulating their state and allowing them to be unit tested in isolation.<\/p>\n<p>For example, to test our TestComponent, we can write:<\/p>\n<pre><code class=\"ruby\">require \"view_component\/test_case\"\n\nclass MyComponentTest &lt; ViewComponent::TestCase\n  def test_render_component\n    render_inline(TestComponent.new(title: \"my title\")) { \"Hello, World!\" }\n\n    assert_selector(\"span[title='my title']\", text: \"Hello, World!\")\n    # or, to just assert against the text:\n    assert_text(\"Hello, World!\")\n  end\nend\n<\/code><\/pre>\n<p>These kinds of unit tests enable us to test our view code directly, instead of via controller tests. They are also significantly faster: in the GitHub codebase, component unit tests take around 25 milliseconds each, compared to about six seconds for controller tests.<\/p>\n<h2 ><a class=\"heading-link\" href=\"#\"><a id=\"user-content-in-practice\" class=\"anchor\" href=\"https:\/\/gist.github.com\/leereilly\/4ef2395d9a6d72aa02341f00029afabe#in-practice\" aria-hidden=\"true\"><\/a>In practice<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Over the past two years, we\u2019ve made significant strides in using ViewComponent: we now have over 400 components used in over 1600 of our 4500+ templates. For example, every <a href=\"https:\/\/primer.style\/view-components\/components\/counter\" rel=\"nofollow\">Counter<\/a>\u00a0and\u00a0<a href=\"https:\/\/primer.style\/view-components\/components\/blankslate\" rel=\"nofollow\">Blankslate<\/a>\u00a0on GitHub.com is rendered with a ViewComponent.<\/p>\n<p>We\u2019re seeing several significant benefits from this architecture. Because ViewComponents can be unit tested against their rendered DOM, we\u2019ve been able to reduce duplication of test coverage for shared templates, which we previously covered with controller tests. And since ViewComponent tests are so fast, we\u2019re finding ourselves writing more of them, leading to higher confidence in our view code.<\/p>\n<p>We\u2019ve also seen the positive impact of the consistency that component-driven view architecture can provide. When we implemented a ViewComponent for the status of pull requests, we discovered several locations where we had not updated our previous, copy-pasted implementation, to handle the then-recently-shipped draft pull request status. By standardizing on a source of truth for the UI pattern, we now have a single, consistent implementation.<\/p>\n<p>To see some of the ViewComponents we\u2019re using in the GitHub application, check out the\u00a0<a href=\"https:\/\/primer.style\/view-components\/\" rel=\"nofollow\">Primer ViewComponents<\/a>\u00a0library.<\/p>\n<p><em>Support for 3rd-party component frameworks such as ViewComponent is just one of many contributions GitHub engineers contributed to Rails 6.1. Other notable additions include\u00a0<a href=\"https:\/\/github.com\/rails\/rails\/pull\/38531\">support for horizontal sharding<\/a>,\u00a0<a href=\"https:\/\/github.com\/rails\/rails\/pull\/37400\">strict loading<\/a>, and\u00a0<a href=\"https:\/\/github.com\/rails\/rails\/pull\/38848\">template annotations<\/a>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn more about how we are bringing encapsulation to our views as we scale to over 4,500 templates in our Ruby on Rails monolith.<\/p>\n","protected":false},"author":1624,"featured_media":57452,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_gh_post_show_toc":"","_gh_post_is_no_robots":"","_gh_post_is_featured":"","_gh_post_is_excluded":"","_gh_post_is_unlisted":"","_gh_post_related_link_1":"","_gh_post_related_link_2":"","_gh_post_related_link_3":"","_gh_post_sq_img":"","_gh_post_sq_img_id":"","_gh_post_cta_title":"","_gh_post_cta_text":"","_gh_post_cta_link":"","_gh_post_cta_button":"","_gh_post_recirc_hide":"","_gh_post_recirc_col_1":"","_gh_post_recirc_col_2":"","_gh_post_recirc_col_3":"","_gh_post_recirc_col_4":"","_featured_video":"","_gh_post_additional_query_params":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false,"_links_to":"","_links_to_target":""},"categories":[3298,3304],"tags":[1925],"coauthors":[2252],"class_list":["post-55358","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developer-skills","category-programming-languages-and-frameworks","tag-rails"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.4 (Yoast SEO v28.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Encapsulating Ruby on Rails views - The GitHub Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Encapsulating Ruby on Rails views\" \/>\n<meta property=\"og:description\" content=\"Learn more about how we are bringing encapsulation to our views as we scale to over 4,500 templates in our Ruby on Rails monolith.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/\" \/>\n<meta property=\"og:site_name\" content=\"The GitHub Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-12-15T18:14:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-12-20T22:44:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2019\/03\/engineering-social.png?fit=1201%2C630\" \/>\n\t<meta property=\"og:image:width\" content=\"1201\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Joel Hawksley\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2019\/03\/engineering-social.png?fit=1201%2C630\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joel Hawksley\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/\"},\"author\":{\"name\":\"Joel Hawksley\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/1493bf99d0dcc105879b2f11f7f4702f\"},\"headline\":\"Encapsulating Ruby on Rails views\",\"datePublished\":\"2020-12-15T18:14:49+00:00\",\"dateModified\":\"2021-12-20T22:44:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/\"},\"wordCount\":531,\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Blog_ENGINEERING_for-social.png?fit=1200%2C630\",\"keywords\":[\"Rails\"],\"articleSection\":[\"Developer skills\",\"Programming languages &amp; frameworks\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/\",\"url\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/\",\"name\":\"Encapsulating Ruby on Rails views - The GitHub Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Blog_ENGINEERING_for-social.png?fit=1200%2C630\",\"datePublished\":\"2020-12-15T18:14:49+00:00\",\"dateModified\":\"2021-12-20T22:44:52+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/1493bf99d0dcc105879b2f11f7f4702f\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#primaryimage\",\"url\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Blog_ENGINEERING_for-social.png?fit=1200%2C630\",\"contentUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2021\\\/04\\\/Blog_ENGINEERING_for-social.png?fit=1200%2C630\",\"width\":1200,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/encapsulating-ruby-on-rails-views\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/github.blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Developer skills\",\"item\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Programming languages &amp; frameworks\",\"item\":\"https:\\\/\\\/github.blog\\\/developer-skills\\\/programming-languages-and-frameworks\\\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Encapsulating Ruby on Rails views\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/github.blog\\\/#website\",\"url\":\"https:\\\/\\\/github.blog\\\/\",\"name\":\"The GitHub Blog\",\"description\":\"Updates, ideas, and inspiration from GitHub to help developers build and design software.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/github.blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/1493bf99d0dcc105879b2f11f7f4702f\",\"name\":\"Joel Hawksley\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9acd7f15f77c08ff2d131d9ff1c76bbeabc87100cbb412651a6f53a6d34ed487?s=96&d=mm&r=g24099d9650f3dac8bdd4467ab7e411da\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9acd7f15f77c08ff2d131d9ff1c76bbeabc87100cbb412651a6f53a6d34ed487?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9acd7f15f77c08ff2d131d9ff1c76bbeabc87100cbb412651a6f53a6d34ed487?s=96&d=mm&r=g\",\"caption\":\"Joel Hawksley\"},\"url\":\"https:\\\/\\\/github.blog\\\/author\\\/joelhawksley\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Encapsulating Ruby on Rails views - The GitHub Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/","og_locale":"en_US","og_type":"article","og_title":"Encapsulating Ruby on Rails views","og_description":"Learn more about how we are bringing encapsulation to our views as we scale to over 4,500 templates in our Ruby on Rails monolith.","og_url":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/","og_site_name":"The GitHub Blog","article_published_time":"2020-12-15T18:14:49+00:00","article_modified_time":"2021-12-20T22:44:52+00:00","og_image":[{"width":1201,"height":630,"url":"https:\/\/github.blog\/wp-content\/uploads\/2019\/03\/engineering-social.png?fit=1201%2C630","type":"image\/png"}],"author":"Joel Hawksley","twitter_card":"summary_large_image","twitter_image":"https:\/\/github.blog\/wp-content\/uploads\/2019\/03\/engineering-social.png?fit=1201%2C630","twitter_misc":{"Written by":"Joel Hawksley","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#article","isPartOf":{"@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/"},"author":{"name":"Joel Hawksley","@id":"https:\/\/github.blog\/#\/schema\/person\/1493bf99d0dcc105879b2f11f7f4702f"},"headline":"Encapsulating Ruby on Rails views","datePublished":"2020-12-15T18:14:49+00:00","dateModified":"2021-12-20T22:44:52+00:00","mainEntityOfPage":{"@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/"},"wordCount":531,"image":{"@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2021\/04\/Blog_ENGINEERING_for-social.png?fit=1200%2C630","keywords":["Rails"],"articleSection":["Developer skills","Programming languages &amp; frameworks"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/","url":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/","name":"Encapsulating Ruby on Rails views - The GitHub Blog","isPartOf":{"@id":"https:\/\/github.blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#primaryimage"},"image":{"@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2021\/04\/Blog_ENGINEERING_for-social.png?fit=1200%2C630","datePublished":"2020-12-15T18:14:49+00:00","dateModified":"2021-12-20T22:44:52+00:00","author":{"@id":"https:\/\/github.blog\/#\/schema\/person\/1493bf99d0dcc105879b2f11f7f4702f"},"breadcrumb":{"@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#primaryimage","url":"https:\/\/github.blog\/wp-content\/uploads\/2021\/04\/Blog_ENGINEERING_for-social.png?fit=1200%2C630","contentUrl":"https:\/\/github.blog\/wp-content\/uploads\/2021\/04\/Blog_ENGINEERING_for-social.png?fit=1200%2C630","width":1200,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/encapsulating-ruby-on-rails-views\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/github.blog\/"},{"@type":"ListItem","position":2,"name":"Developer skills","item":"https:\/\/github.blog\/developer-skills\/"},{"@type":"ListItem","position":3,"name":"Programming languages &amp; frameworks","item":"https:\/\/github.blog\/developer-skills\/programming-languages-and-frameworks\/"},{"@type":"ListItem","position":4,"name":"Encapsulating Ruby on Rails views"}]},{"@type":"WebSite","@id":"https:\/\/github.blog\/#website","url":"https:\/\/github.blog\/","name":"The GitHub Blog","description":"Updates, ideas, and inspiration from GitHub to help developers build and design software.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/github.blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/github.blog\/#\/schema\/person\/1493bf99d0dcc105879b2f11f7f4702f","name":"Joel Hawksley","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/9acd7f15f77c08ff2d131d9ff1c76bbeabc87100cbb412651a6f53a6d34ed487?s=96&d=mm&r=g24099d9650f3dac8bdd4467ab7e411da","url":"https:\/\/secure.gravatar.com\/avatar\/9acd7f15f77c08ff2d131d9ff1c76bbeabc87100cbb412651a6f53a6d34ed487?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9acd7f15f77c08ff2d131d9ff1c76bbeabc87100cbb412651a6f53a6d34ed487?s=96&d=mm&r=g","caption":"Joel Hawksley"},"url":"https:\/\/github.blog\/author\/joelhawksley\/"}]}},"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/pamS32-eoS","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/github.blog\/wp-content\/uploads\/2021\/04\/Blog_ENGINEERING_for-social.png?fit=1200%2C630","_links":{"self":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/55358","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/users\/1624"}],"replies":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/comments?post=55358"}],"version-history":[{"count":12,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/55358\/revisions"}],"predecessor-version":[{"id":55375,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/55358\/revisions\/55375"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media\/57452"}],"wp:attachment":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media?parent=55358"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/categories?post=55358"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/tags?post=55358"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/coauthors?post=55358"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}