{"id":3566,"date":"2022-01-10T15:47:14","date_gmt":"2022-01-10T15:47:14","guid":{"rendered":"http:\/\/the-codest.localhost\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/"},"modified":"2026-04-28T14:05:25","modified_gmt":"2026-04-28T14:05:25","slug":"ruby-on-rails-modularizacao-com-packwerk-episodio-ii","status":"publish","type":"post","link":"https:\/\/thecodest.co\/pt\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/","title":{"rendered":"Ruby on Rails modulariza\u00e7\u00e3o com Packwerk Episode II"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Aplica\u00e7\u00e3o como um pacote<\/h2>\n\n\n\n<p>A abordagem para modularizar a nossa aplica\u00e7\u00e3o consiste em converter toda a aplica\u00e7\u00e3o num pacote.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Criar a estrutura<\/h3>\n\n\n\n<p>Primeiro, precisamos de criar <code>app\/pacotes<\/code> onde colocaremos todos os nossos pacotes. Para isolar os nossos pacotes, temos de separar cada <strong>Conceito MVC<\/strong> numa pasta. Pegar no <strong>CodeTriage <a href=\"https:\/\/thecodest.co\/pt\/dictionary\/why-do-projects-fail\/\">projeto<\/a><\/strong> como exemplo, teremos algo parecido com a seguinte imagem.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/2.png\" alt=\"estrutura do pacote \" title=\"exemplo de estrutura de pacote\"\/><\/figure>\n\n\n\n<p>Se tentarmos executar o servidor, ele n\u00e3o conseguir\u00e1 encontrar as constantes. \u00c9 por isso que precisamos adicionar uma linha de configura\u00e7\u00e3o ao nosso <code>aplica\u00e7\u00e3o.rb<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">config.paths.add 'app\/packages', glob: '*\/{*,*\/concerns}', eager_load:true<\/code><\/pre>\n\n\n\n<p>Agora a aplica\u00e7\u00e3o funciona mas n\u00e3o consegue encontrar as vistas, por isso precisamos de adicionar outra linha de configura\u00e7\u00e3o ao nosso <code>application_controller.rb<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">append_view_path(Dir.glob(<a href=\"https:\/\/thecodest.co\/pt\/blog\/ways-to-increase-your-rails-performance\/\">Carris<\/a>.root.join('app\/packages\/*\/views')))<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Criar os pacotes<\/h3>\n\n\n\n<p>A nossa estrutura est\u00e1 pronta, por isso agora podemos come\u00e7ar a criar os pacotes. Para isso, s\u00f3 precisamos de adicionar um<code>package.yml<\/code> para cada pasta com a seguinte configura\u00e7\u00e3o:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">enforce_privacy: false\nenforce_dependencies: true<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/1.png\" alt=\"package.yml\" title=\"exemplo package.yml\"\/><\/figure>\n\n\n\n<p><code>impor_privacidade<\/code>d\u00e1 <a href=\"https:\/\/thecodest.co\/pt\/blog\/why-us-companies-are-opting-for-polish-developers\/\">n\u00f3s<\/a> a possibilidade de isolar todas as constantes do pacote e trabalhar com uma constante p\u00fablica <a href=\"https:\/\/thecodest.co\/pt\/blog\/compare-staff-augmentation-firms-that-excel-in-api-team-staffing-for-financial-technology-projects\/\">API<\/a>. Para expor as constantes p\u00fablicas, precisamos de adicionar as constantes, por exemplo&nbsp;<code>packages\/users\/app\/public.<\/code>Para j\u00e1, vamos definir esta configura\u00e7\u00e3o para <em> falso<\/em>.<\/p>\n\n\n\n<p><code>impor_depend\u00eancias<\/code> ir\u00e1 impor a depend\u00eancia de um pacote e verificar todas as refer\u00eancias constantes. Se uma depend\u00eancia n\u00e3o for explicitamente definida, ser\u00e1 uma viola\u00e7\u00e3o do limite.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Valida\u00e7\u00e3o do sistema de pacotes<\/h3>\n\n\n\n<p><strong>Packwerk<\/strong> estabeleceu um crit\u00e9rio que temos de seguir para termos um sistema de pacotes v\u00e1lido. Podemos come\u00e7ar a executar <code>packwerk validado<\/code> na nossa consola.<\/p>\n\n\n\n<p>&nbsp;Isto ir\u00e1 verificar a nossa estrutura de pastas, <strong>configura\u00e7\u00e3o do pacote<\/strong>e cache de caminho de carregamento autom\u00e1tico.<\/p>\n\n\n\n<p>Neste momento, a nossa aplica\u00e7\u00e3o n\u00e3o \u00e9 v\u00e1lida e temos de corrigir os caminhos de carregamento em<strong><code>packwerk.yml<\/code>.<\/strong> Para o fazer, s\u00f3 temos de acrescentar os caminhos em falta.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\"># packwerk.yml\n\nload_paths:\n.\n.\n.\n\n# Utilizadores\n- app\/pacotes\/utilizadores\/controladores\n- app\/pacotes\/utilizadores\/modelos\n- app\/pacotes\/utilizadores\/pacote.yml\n- app\/pacotes\/utilizadores\/visualiza\u00e7\u00f5es<\/code><\/pre>\n\n\n\n<p>Nesta altura, estamos prontos para verificar as viola\u00e7\u00f5es de limites na nossa aplica\u00e7\u00e3o. Para verificar as viola\u00e7\u00f5es, podemos executar<code>packwerk update-deprecations<\/code> , este comando ir\u00e1 gerar <code>deprecated_references.yml<\/code> para cada pacote. Em cada ficheiro, encontraremos o nome do pacote, o tipo de viola\u00e7\u00e3o e o caminho do ficheiro. Com todas estas informa\u00e7\u00f5es, sabemos onde est\u00e1 a ocorrer a viola\u00e7\u00e3o e podemos tomar uma decis\u00e3o para a resolver.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/4.png\" alt=\"deprecated_references.yml\" title=\"exemplo deprecated_references.yml\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\"># deprecated_references.yml\n\n.\n.\n.\n\napp\/packages\/repos:\n  \"::Repo\":\n    viola\u00e7\u00f5es:\n    - depend\u00eancia\n    ficheiros:\n    - app\/packages\/users\/models\/user.rb<\/code><\/pre>\n\n\n\n<p>Tomando o exemplo, vamos descrever cada parte da informa\u00e7\u00e3o gerada<br>por <strong>Packwerk<\/strong>.<\/p>\n\n\n\n<p>- <code>app\/pacotes\/repos<\/code> &nbsp;- pacote onde a viola\u00e7\u00e3o constante \u00e9<br>encontrado.<\/p>\n\n\n\n<p>- <code>::Repo<\/code> &nbsp;- caminho para o ficheiro que cont\u00e9m a constante violada.<\/p>\n\n\n\n<p>- <code>depend\u00eancia<\/code> &nbsp;- um tipo de viola\u00e7\u00e3o, seja de depend\u00eancia ou de privacidade.<\/p>\n\n\n\n<p>- <code>app\/packages\/users\/models\/user.rb<\/code> &nbsp;- caminho para o ficheiro que cont\u00e9m a constante violada.<\/p>\n\n\n\n<p>Como passo final nesta sec\u00e7\u00e3o, n\u00e3o se esque\u00e7a de adicionar os novos caminhos de ficheiros gerados ao <code>packwerk.ym<\/code>l e executar novamente as valida\u00e7\u00f5es.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Visualiza\u00e7\u00e3o de depend\u00eancias<\/h3>\n\n\n\n<p>Com todas as informa\u00e7\u00f5es em package.yml e <code>deprecated_references.yml<\/code>podemos ent\u00e3o<br>visualizar um gr\u00e1fico de depend\u00eancias. Para isso, precisamos de adicionar outra gem, neste caso vamos usar <a href=\"https:\/\/github.com\/mquan\/pocky\" rel=\"nofollow\">Pocky<\/a>.<\/p>\n\n\n\n<p>Ancinho de corrida <code>pocky:gerar<\/code> vamos gerar um ficheiro chamado <code>packwerk.png<\/code> onde podemos visualizar o nosso primeiro gr\u00e1fico de depend\u00eancias.<\/p>\n\n\n\n<p>Com todos os pacotes definidos, o nosso gr\u00e1fico ter\u00e1 o seguinte aspeto.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/5.png\" alt=\"gr\u00e1fico sem depend\u00eancias aceites\" title=\"exemplo de gr\u00e1fico sem depend\u00eancias aceites\"\/><\/figure>\n\n\n\n<p>as depend\u00eancias j\u00e1 existem, mas isso n\u00e3o significa que sejam aceites pelo <strong>Packwerk<\/strong>. Para<br>aceitar uma depend\u00eancia, precisamos de adicionar a configura\u00e7\u00e3o das depend\u00eancias ao <code>package.yml<\/code><br>em cada pacote. Concentrar-nos-emos em <code>criadores de correio<\/code> uma vez que se trata de um pacote sem depend\u00eancia circular. Vale a pena mencionar que <strong>Packwerk<\/strong> n\u00e3o nos deixa aceitar depend\u00eancias circulares.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\"># app\/packages\/mail_builders\/package.yml\n\n```rubi\nenforce_privacy: false\nenforce_dependencies: true\ndepend\u00eancias:\n- app\/packages\/docs\n- app\/pacotes\/assuntos\n- app\/pacotes\/repos<\/code><\/pre>\n\n\n\n<p>Depois de adicionar esta configura\u00e7\u00e3o, <strong>Pocky<\/strong> ir\u00e1 colorir de verde as depend\u00eancias aceites.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/6.png\" alt=\"gr\u00e1fico com depend\u00eancias aceites \" title=\"exemplo de gr\u00e1fico sem depend\u00eancias aceites\"\/><\/figure>\n\n\n\n<p>Podemos apagar <code>deprecated_references.yml<\/code> de <code>app\/packages\/mail_builders<\/code> e executar<br><code>packwerk update-deprecations<\/code> novamente. O ficheiro n\u00e3o ser\u00e1 gerado novamente, uma vez que todos os<br>foram corrigidas para este pacote. \u00c9 importante mencionar que mesmo que n\u00e3o fa\u00e7amos o Graph com depend\u00eancias aceites<\/p>\n\n\n\n<p><strong><a href=\"https:\/\/thecodest.co\/pt\/blog\/hire-ror-developer\/\">Rubi<\/a> modulariza\u00e7\u00e3o em Rails com Packwerk<\/strong> aceitar depend\u00eancias, a nossa aplica\u00e7\u00e3o continuar\u00e1 a funcionar como antes, mas agora temos mais<br>informa\u00e7\u00f5es para tomar decis\u00f5es e refactorizar.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Remover depend\u00eancias circulares<\/h3>\n\n\n\n<p>No nosso gr\u00e1fico anterior, t\u00ednhamos muitas depend\u00eancias circulares que precisavam de ser resolvidas de alguma forma. Temos diferentes estrat\u00e9gias para o fazer:<\/p>\n\n\n\n<p>- N\u00e3o fazer nada,<\/p>\n\n\n\n<p>- Aceitar depend\u00eancias, Mesclar pacotes,<\/p>\n\n\n\n<p>- Mover <a href=\"https:\/\/thecodest.co\/pt\/dictionary\/what-is-code-refactoring\/\">c\u00f3digo<\/a> entre pacotes,<\/p>\n\n\n\n<p>- Duplicar uma funcionalidade,&nbsp;<\/p>\n\n\n\n<p>- Executar inje\u00e7\u00e3o de depend\u00eancia ou inje\u00e7\u00e3o de depend\u00eancia com tipagem.<\/p>\n\n\n\n<p>Uma quest\u00e3o aqui \u00e9 que, para fazer uma refac\u00e7\u00e3o adequada, precisamos de conhecer a base de c\u00f3digo. N\u00e3o estou muito familiarizado com a base de c\u00f3digo deste projeto, uma vez que o tomei como exemplo, por isso, por raz\u00f5es pr\u00e1ticas, vamos optar pela primeira estrat\u00e9gia, n\u00e3o fazer nada. Mesmo que evitemos a maior parte da refatora\u00e7\u00e3o, queremos trabalhar nas depend\u00eancias do <em>raiz<\/em> pacote.<\/p>\n\n\n\n<p>O pacote raiz cont\u00e9m toda a cola do pacote <strong>Estrutura Rails<\/strong>Todas as classes de que herdamos e fazemos com que todas trabalhem em conjunto. Assim, para resolver as depend\u00eancias circulares, vamos criar um novo pacote chamado rails nos seguintes passos:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Mover todos os ficheiros e pastas da aplica\u00e7\u00e3o_ da aplica\u00e7\u00e3o para <code>app\/pacotes\/rails<\/code>.<\/li>\n\n\n\n<li>Criar um<code>package.yml<\/code> para o pacote com a mesma configura\u00e7\u00e3o que os pacotes anteriores.<\/li>\n\n\n\n<li>Adicione todos os novos caminhos de ficheiro a <code>packwerk.yml<\/code>.<\/li>\n\n\n\n<li>Adicionar <code>app\/pacotes\/rails<\/code> como uma depend\u00eancia do resto dos pacotes.<\/li>\n<\/ol>\n\n\n\n<p>Assim que criarmos o pacote, come\u00e7aremos a reparar em muitos ficheiros que podem ser reestruturados. Depois de mover tudo para o pacote correspondente e aceitar o<br>teremos uma nova estrutura e um gr\u00e1fico mais limpo.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/graph.png\" alt=\"Estrutura do pacote com pacote de carris \" title=\"Estrutura de pacotes com exemplo de pacote rails\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/8.png\" alt=\"Gr\u00e1fico sem depend\u00eancias circulares de raiz\" title=\"Exemplo de gr\u00e1fico sem depend\u00eancias circulares de raiz\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Remover depend\u00eancias do pacote raiz<\/h3>\n\n\n\n<p>Agora nosso gr\u00e1fico parece muito melhor, seria \u00f3timo se pud\u00e9ssemos remover todas as depend\u00eancias do pacote raiz. Se verificarmos o deprecated_references.yml no pacote raiz, notaremos que a maioria delas s\u00e3o do <code>teste<\/code> , <code>lib\/tasks<\/code> , <code>db<\/code> e <code>configura\u00e7\u00e3o<\/code><br>pasta. Para resolver estas depend\u00eancias, vamos criar uma pasta de teste dentro de cada pacote. Ter algo como <code>app\/pacotes\/utilizadores\/teste<\/code>. De seguida, vamos excluir <code>lib\/tasks<\/code> , <code>db<\/code> e <code>configura\u00e7\u00e3o<\/code>entre outras pastas de <strong>Packwerk<\/strong> uma vez que essas depend\u00eancias n\u00e3o s\u00e3o realmente importantes na nossa an\u00e1lise e n\u00e3o temos uma forma f\u00e1cil de as resolver. Vamos adicionar o seguinte ao nosso <em>packwerk.yml<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">exclude:\n- \"{bin,node_modules,script,tmp,vendor,lib,db,config,perf_scripts}\/**\/*\"\n- \"lib\/tasks\/**\/*.rake\"<\/code><\/pre>\n\n\n\n<p>Depois de mover todos os testes do pacote raiz e excluir as pastas da an\u00e1lise, teremos um novo gr\u00e1fico sem as depend\u00eancias raiz.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/9.png\" alt=\"Gr\u00e1fico sem depend\u00eancias de raiz\" title=\"Gr\u00e1fico sem depend\u00eancias de raiz\"\/><\/figure>\n\n\n\n<p>Como podemos ver, continuamos a ter depend\u00eancias circulares em<code>utilizadores<\/code> , <code>reposit\u00f3rios<\/code> e <code>documentos<\/code> . Embora n\u00e3o as tenhamos resolvido, temos informa\u00e7\u00f5es importantes para transmitir agora. Sabemos que todos os <a href=\"https:\/\/thecodest.co\/pt\/blog\/how-to-hire-the-best-outsourced-development-team-for-a-scaleup\/\">equipa<\/a> que realiza mudan\u00e7as em um desses pacotes provavelmente ter\u00e1 que realizar mudan\u00e7as nos pacotes com a depend\u00eancia circular. Por outro lado, sabemos que uma equipa pode trabalhar em <code>github_fetchers<\/code> apenas, saber quais s\u00e3o os pacotes<br>sendo afetado pelas mudan\u00e7as em cada momento.<\/p>\n\n\n\n<p>Pode encontrar o resultado final do projeto <a href=\"https:\/\/github.com\/niconisoria\/codetriage-packwerk\" rel=\"nofollow\">aqui<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pr\u00f3ximo passo<\/h3>\n\n\n\n<p>Como pr\u00f3ximo passo, pode impor uma privacidade constante em cada pacote e expor apenas a API p\u00fablica que ser\u00e1 acess\u00edvel a partir de outros pacotes. Voc\u00ea pode facilmente configurar onde sua API ser\u00e1 colocada em <em>package.yml<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">enforce_privacy: true\nenforce_dependencies: true\npublic_path: my\/custom\/path\/<\/code><\/pre>\n\n\n\n<p><code> <\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclus\u00f5es<\/h2>\n\n\n\n<p><strong>Packwerk<\/strong> d\u00e1-nos muitas informa\u00e7\u00f5es sobre a nossa aplica\u00e7\u00e3o e, com essas informa\u00e7\u00f5es, podemos tomar decis\u00f5es para melhorar o fluxo de trabalho das nossas equipas. Embora o processo pare\u00e7a ser longo e com muitas configura\u00e7\u00f5es, n\u00e3o precisa de ser sempre assim. Podemos come\u00e7ar a criar pacotes apenas para o novo c\u00f3digo adicionado \u00e0 nossa aplica\u00e7\u00e3o e depois modularizar gradualmente. Ent\u00e3o agora podemos come\u00e7ar a falar sobre Modulariza\u00e7\u00e3o Gradual, este \u00e9 o conceito introduzido por Stephan Hagemann <em>\"Podemos, pela primeira vez, decidir come\u00e7ar a modularizar uma parte do c\u00f3digo de uma forma aspiracional... Isto permite-nos criar um sistema de apoio que se expande gradualmente em dire\u00e7\u00e3o a uma melhor estrutura de aplica\u00e7\u00e3o\".<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fontes<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/leanpub.com\/package-based-rails-applications\" rel=\"nofollow\">Modulariza\u00e7\u00e3o gradual para Ruby on Rails - Stephan Hagemann<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/shopify.engineering\/enforcing-modularity-rails-apps-packwerk\">Impondo modularidade em aplica\u00e7\u00f5es Rails com Packwerk<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/Shopify\/packwerk\">Packwerk Github<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/niconisoria\/codetriage-packwerk\">C\u00f3digo fonte do artigo<\/a><\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/thecodest.co\/contact\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/cta_2.jpeg\" alt=\"Consultoria em desenvolvimento de produtos digitais\"\/><\/a><\/figure>\n\n\n\n<p><strong>Ler mais<\/strong><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/graphql-ruby-what-about-performance\">Ruby GraphQL. E quanto ao desempenho?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/rails-and-other-means-of-transport\">Carris e outros meios de transporte<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/rails-development-with-tmux-vim-fzf-ripgrep\">Desenvolvimento Rails com TMUX, Vim, Fzf + Ripgrep<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>No segundo epis\u00f3dio da nossa modulariza\u00e7\u00e3o Ruby on Rails com Packwerk, vamos analisar de perto o conceito de aplica\u00e7\u00e3o como um pacote.<\/p>","protected":false},"author":2,"featured_media":3567,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[8],"tags":[],"class_list":["post-3566","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-development"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Ruby on Rails modularization with Packwerk Episode II - The Codest<\/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:\/\/thecodest.co\/pt\/blogue\/ruby-on-rails-modularizacao-com-packwerk-episodio-ii\/\" \/>\n<meta property=\"og:locale\" content=\"pt_PT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ruby on Rails modularization with Packwerk Episode II\" \/>\n<meta property=\"og:description\" content=\"In the second episode of our Ruby on Rails modularization with Packwerk we will take a close look at the concept of application as an package.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/thecodest.co\/pt\/blogue\/ruby-on-rails-modularizacao-com-packwerk-episodio-ii\/\" \/>\n<meta property=\"og:site_name\" content=\"The Codest\" \/>\n<meta property=\"article:published_time\" content=\"2022-01-10T15:47:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-28T14:05:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"960\" \/>\n\t<meta property=\"og:image:height\" content=\"540\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"thecodest\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"thecodest\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\"},\"author\":{\"name\":\"thecodest\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/person\\\/7e3fe41dfa4f4e41a7baad4c6e0d4f76\"},\"headline\":\"Ruby on Rails modularization with Packwerk Episode II\",\"datePublished\":\"2022-01-10T15:47:14+00:00\",\"dateModified\":\"2026-04-28T14:05:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\"},\"wordCount\":1295,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png\",\"articleSection\":[\"Software Development\"],\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\",\"url\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\",\"name\":\"Ruby on Rails modularization with Packwerk Episode II - The Codest\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png\",\"datePublished\":\"2022-01-10T15:47:14+00:00\",\"dateModified\":\"2026-04-28T14:05:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#breadcrumb\"},\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#primaryimage\",\"url\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png\",\"contentUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/05\\\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png\",\"width\":960,\"height\":540},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/thecodest.co\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ruby on Rails modularization with Packwerk Episode II\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#website\",\"url\":\"https:\\\/\\\/thecodest.co\\\/\",\"name\":\"The Codest\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/thecodest.co\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-PT\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\",\"name\":\"The Codest\",\"url\":\"https:\\\/\\\/thecodest.co\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/03\\\/thecodest-logo.svg\",\"contentUrl\":\"https:\\\/\\\/thecodest.co\\\/app\\\/uploads\\\/2024\\\/03\\\/thecodest-logo.svg\",\"width\":144,\"height\":36,\"caption\":\"The Codest\"},\"image\":{\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/pl.linkedin.com\\\/company\\\/codest\",\"https:\\\/\\\/clutch.co\\\/profile\\\/codest\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#\\\/schema\\\/person\\\/7e3fe41dfa4f4e41a7baad4c6e0d4f76\",\"name\":\"thecodest\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g\",\"caption\":\"thecodest\"},\"url\":\"https:\\\/\\\/thecodest.co\\\/pt\\\/author\\\/thecodest\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ruby on Rails modulariza\u00e7\u00e3o com Packwerk Epis\u00f3dio II - The Codest","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:\/\/thecodest.co\/pt\/blogue\/ruby-on-rails-modularizacao-com-packwerk-episodio-ii\/","og_locale":"pt_PT","og_type":"article","og_title":"Ruby on Rails modularization with Packwerk Episode II","og_description":"In the second episode of our Ruby on Rails modularization with Packwerk we will take a close look at the concept of application as an package.","og_url":"https:\/\/thecodest.co\/pt\/blogue\/ruby-on-rails-modularizacao-com-packwerk-episodio-ii\/","og_site_name":"The Codest","article_published_time":"2022-01-10T15:47:14+00:00","article_modified_time":"2026-04-28T14:05:25+00:00","og_image":[{"width":960,"height":540,"url":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png","type":"image\/png"}],"author":"thecodest","twitter_card":"summary_large_image","twitter_misc":{"Written by":"thecodest","Est. reading time":"8 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#article","isPartOf":{"@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/"},"author":{"name":"thecodest","@id":"https:\/\/thecodest.co\/#\/schema\/person\/7e3fe41dfa4f4e41a7baad4c6e0d4f76"},"headline":"Ruby on Rails modularization with Packwerk Episode II","datePublished":"2022-01-10T15:47:14+00:00","dateModified":"2026-04-28T14:05:25+00:00","mainEntityOfPage":{"@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/"},"wordCount":1295,"commentCount":0,"publisher":{"@id":"https:\/\/thecodest.co\/#organization"},"image":{"@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#primaryimage"},"thumbnailUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png","articleSection":["Software Development"],"inLanguage":"pt-PT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/","url":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/","name":"Ruby on Rails modulariza\u00e7\u00e3o com Packwerk Epis\u00f3dio II - The Codest","isPartOf":{"@id":"https:\/\/thecodest.co\/#website"},"primaryImageOfPage":{"@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#primaryimage"},"image":{"@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#primaryimage"},"thumbnailUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png","datePublished":"2022-01-10T15:47:14+00:00","dateModified":"2026-04-28T14:05:25+00:00","breadcrumb":{"@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#breadcrumb"},"inLanguage":"pt-PT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/"]}]},{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#primaryimage","url":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png","contentUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/05\/ruby_on_rails_modularization_with_packwerk_-__-_episode_2.png","width":960,"height":540},{"@type":"BreadcrumbList","@id":"https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/thecodest.co\/"},{"@type":"ListItem","position":2,"name":"Ruby on Rails modularization with Packwerk Episode II"}]},{"@type":"WebSite","@id":"https:\/\/thecodest.co\/#website","url":"https:\/\/thecodest.co\/","name":"The Codest","description":"","publisher":{"@id":"https:\/\/thecodest.co\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/thecodest.co\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-PT"},{"@type":"Organization","@id":"https:\/\/thecodest.co\/#organization","name":"The Codest","url":"https:\/\/thecodest.co\/","logo":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/thecodest.co\/#\/schema\/logo\/image\/","url":"https:\/\/thecodest.co\/app\/uploads\/2024\/03\/thecodest-logo.svg","contentUrl":"https:\/\/thecodest.co\/app\/uploads\/2024\/03\/thecodest-logo.svg","width":144,"height":36,"caption":"The Codest"},"image":{"@id":"https:\/\/thecodest.co\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/pl.linkedin.com\/company\/codest","https:\/\/clutch.co\/profile\/codest"]},{"@type":"Person","@id":"https:\/\/thecodest.co\/#\/schema\/person\/7e3fe41dfa4f4e41a7baad4c6e0d4f76","name":"thecodest","image":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/secure.gravatar.com\/avatar\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5dbfe6a1e8c86e432e8812759e34e6fe82ebac75119ae3237a6c1311fa19caf4?s=96&d=mm&r=g","caption":"thecodest"},"url":"https:\/\/thecodest.co\/pt\/author\/thecodest\/"}]}},"_links":{"self":[{"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/posts\/3566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/comments?post=3566"}],"version-history":[{"count":10,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/posts\/3566\/revisions"}],"predecessor-version":[{"id":7983,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/posts\/3566\/revisions\/7983"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/media\/3567"}],"wp:attachment":[{"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/media?parent=3566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/categories?post=3566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thecodest.co\/pt\/wp-json\/wp\/v2\/tags?post=3566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}