{"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-modularisering-med-packwerk-episode-ii","status":"publish","type":"post","link":"https:\/\/thecodest.co\/nb\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/","title":{"rendered":"Ruby on Rails-modularisering med Packwerk Episode II"},"content":{"rendered":"<h2 class=\"wp-block-heading\">S\u00f8knad som en pakke<\/h2>\n\n\n\n<p>Tiln\u00e6rmingen for \u00e5 modularisere applikasjonen v\u00e5r best\u00e5r i \u00e5 konvertere hele applikasjonen til en pakke.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Opprett strukturen<\/h3>\n\n\n\n<p>F\u00f8rst m\u00e5 vi opprette <code>app\/pakker<\/code> mappen der vi skal plassere alle pakkene v\u00e5re. For \u00e5 isolere pakkene v\u00e5re m\u00e5 vi skille hver <strong>MVC-konseptet<\/strong> i \u00e9n mappe. Ved \u00e5 ta <strong>CodeTriage <a href=\"https:\/\/thecodest.co\/nb\/dictionary\/why-do-projects-fail\/\">prosjekt<\/a><\/strong> som et eksempel vil vi ha noe som ligner p\u00e5 f\u00f8lgende bilde.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/2.png\" alt=\"pakkestruktur \" title=\"eksempel p\u00e5 pakkestruktur\"\/><\/figure>\n\n\n\n<p>Hvis vi pr\u00f8ver \u00e5 kj\u00f8re serveren, vil den ikke finne konstantene. Derfor m\u00e5 vi legge til en konfigurasjonslinje i <code>application.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>N\u00e5 fungerer applikasjonen, men den finner ikke visningene, s\u00e5 vi m\u00e5 legge til en ny konfigurasjonslinje i <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\/nb\/blog\/ways-to-increase-your-rails-performance\/\">Rails<\/a>.root.join('app\/packages\/*\/views')))<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Opprett pakkene<\/h3>\n\n\n\n<p>Strukturen v\u00e5r er klar, s\u00e5 n\u00e5 kan vi begynne \u00e5 opprette pakkene. For \u00e5 gj\u00f8re det trenger vi bare \u00e5 legge til en<code>package.yml<\/code> til hver mappe med f\u00f8lgende konfigurasjon:<\/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=\"eksempel p\u00e5 package.yml\"\/><\/figure>\n\n\n\n<p><code>enforce_privacy<\/code>gir <a href=\"https:\/\/thecodest.co\/nb\/blog\/why-us-companies-are-opting-for-polish-developers\/\">oss<\/a> muligheten til \u00e5 isolere alle konstantene i pakken og arbeide med en offentlig <a href=\"https:\/\/thecodest.co\/nb\/blog\/compare-staff-augmentation-firms-that-excel-in-api-team-staffing-for-financial-technology-projects\/\">API<\/a>. For \u00e5 eksponere de offentlige konstantene m\u00e5 vi legge til konstantene i for eksempel&nbsp;<code>pakker\/brukere\/app\/public.<\/code>Forel\u00f8pig skal vi sette denne konfigurasjonen til <em> falsk<\/em>.<\/p>\n\n\n\n<p><code>enforce_dependencies<\/code> vil h\u00e5ndheve avhengigheten til en pakke og se etter alle konstante referanser. Hvis en avhengighet ikke er eksplisitt definert, vil det v\u00e6re et brudd p\u00e5 grensene.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Validering av pakkesystemet<\/h3>\n\n\n\n<p><strong>Packwerk<\/strong> etablert et kriterium vi m\u00e5 f\u00f8lge for \u00e5 ha et gyldig pakkesystem. Vi kan begynne \u00e5 kj\u00f8re <code>packwerk validere<\/code> i konsollen v\u00e5r.<\/p>\n\n\n\n<p>&nbsp;Dette vil sjekke mappestrukturen v\u00e5r, <strong>pakkekonfigurasjon<\/strong>og autoload banebuffer.<\/p>\n\n\n\n<p>Akkurat n\u00e5 er ikke applikasjonen v\u00e5r gyldig, og vi m\u00e5 fikse lastestiene i<strong><code>packwerk.yml<\/code>.<\/strong> For \u00e5 gj\u00f8re dette trenger vi bare \u00e5 legge til de manglende stiene.<\/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#-brukere\n- app\/packages\/users\/controllers\n- app\/pakker\/brukere\/modeller\n- app\/pakker\/brukere\/package.yml\n- app\/pakker\/brukere\/visninger<\/code><\/pre>\n\n\n\n<p>N\u00e5 er vi klare til \u00e5 sjekke grenseoverskridelser i applikasjonen v\u00e5r. For \u00e5 sjekke brudd kan vi kj\u00f8re<code>packwerk update-deprecations<\/code> vil denne kommandoen generere <code>utdaterte_referanser.yml<\/code> fil for hver pakke. I hver fil finner vi pakkenavn, type brudd og filbane. Med all denne informasjonen vet vi hvor overtredelsen skjer, og vi kan ta en beslutning om \u00e5 l\u00f8se den.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/4.png\" alt=\"utdaterte_referanser.yml\" title=\"eksempel p\u00e5 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    brudd:\n    - avhengighet\n    filer:\n    - app\/packages\/users\/models\/user.rb<\/code><\/pre>\n\n\n\n<p>I dette eksemplet skal vi beskrive alle deler av informasjonen som genereres<br>av <strong>Packwerk<\/strong>.<\/p>\n\n\n\n<p>- <code>app\/packages\/repos<\/code> &nbsp;- pakke der konstantbruddet er<br>funnet.<\/p>\n\n\n\n<p>- <code>::Repo<\/code> &nbsp;- stien til filen som inneholder den brutte konstanten.<\/p>\n\n\n\n<p>- <code>avhengighet<\/code> &nbsp;- en type krenkelse, enten avhengighet eller personvern.<\/p>\n\n\n\n<p>- <code>app\/packages\/users\/models\/user.rb<\/code> &nbsp;- stien til filen som inneholder den brutte konstanten.<\/p>\n\n\n\n<p>Som et siste trinn i denne delen, ikke glem \u00e5 legge til de nye genererte filbanene i <code>packwerk.ym<\/code>l og kj\u00f8r valideringene p\u00e5 nytt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Visualisering av avhengighet<\/h3>\n\n\n\n<p>Med all informasjonen i package.yml og <code>utdaterte_referanser.yml<\/code>Vi kan da<br>visualisere en graf over avhengigheter. For \u00e5 gj\u00f8re det m\u00e5 vi legge til en annen perle, i dette tilfellet vil vi bruke <a href=\"https:\/\/github.com\/mquan\/pocky\" rel=\"nofollow\">Pocky<\/a>.<\/p>\n\n\n\n<p>L\u00f8pende rive <code>pocky:generere<\/code> vil vi generere en fil som heter <code>packwerk.png<\/code> der vi kan visualisere v\u00e5r f\u00f8rste graf over avhengigheter.<\/p>\n\n\n\n<p>N\u00e5r alle pakkene er definert, ser grafen v\u00e5r slik ut.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/5.png\" alt=\"graf uten aksepterte avhengigheter\" title=\"graf uten aksepterte avhengigheter eksempel\"\/><\/figure>\n\n\n\n<p>avhengigheter allerede eksisterer, men det betyr ikke at de er akseptert av <strong>Packwerk<\/strong>. Til<br>akseptere en avhengighet, m\u00e5 vi legge til avhengighetskonfigurasjon i <code>package.yml<\/code><br>i hver pakke. Vi vil fokusere p\u00e5 <code>mail_builders<\/code> siden det er en pakke uten sirkul\u00e6r avhengighet. Det er verdt \u00e5 nevne at <strong>Packwerk<\/strong> lar oss ikke akseptere sirkul\u00e6re avhengigheter.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\"># app\/packages\/mail_builders\/package.yml\n\n```ruby\nenforce_privacy: false\nenforce_dependencies: true\ndependencies:\n- app\/packages\/docs\n- app\/packages\/issues\n- app\/packages\/repos<\/code><\/pre>\n\n\n\n<p>Etter at du har lagt til denne konfigurasjonen, <strong>Pocky<\/strong> vil farge de aksepterte avhengighetene med gr\u00f8nt.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/6.png\" alt=\"graf med aksepterte avhengigheter \" title=\"graf uten aksepterte avhengigheter eksempel\"\/><\/figure>\n\n\n\n<p>Vi kan slette <code>utdaterte_referanser.yml<\/code> fra <code>app\/packages\/mail_builders<\/code> og kj\u00f8re<br><code>packwerk update-deprecations<\/code> igjen. Filen vil ikke bli generert p\u00e5 nytt, siden alle<br>brudd ble rettet for denne pakken. Det er viktig \u00e5 nevne at selv om vi ikke bruker Graph med aksepterte avhengigheter<\/p>\n\n\n\n<p><strong><a href=\"https:\/\/thecodest.co\/nb\/blog\/hire-ror-developer\/\">Ruby<\/a> on Rails-modularisering med Packwerk<\/strong> akseptere avhengigheter vil applikasjonen v\u00e5r fortsatt fungere som f\u00f8r, men n\u00e5 har vi flere<br>informasjon for \u00e5 ta beslutninger og gj\u00f8re endringer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Fjern sirkul\u00e6re avhengigheter<\/h3>\n\n\n\n<p>I den forrige grafen v\u00e5r hadde vi mange sirkul\u00e6re avhengigheter som m\u00e5tte l\u00f8ses p\u00e5 en eller annen m\u00e5te. Vi har ulike strategier for \u00e5 gj\u00f8re det:<\/p>\n\n\n\n<p>- Gj\u00f8r ingenting,<\/p>\n\n\n\n<p>- Godta avhengigheter, Sl\u00e5 sammen pakker,<\/p>\n\n\n\n<p>- Flytte <a href=\"https:\/\/thecodest.co\/nb\/dictionary\/what-is-code-refactoring\/\">kode<\/a> mellom pakkene,<\/p>\n\n\n\n<p>- Dupliser en funksjonalitet,&nbsp;<\/p>\n\n\n\n<p>- Utf\u00f8r avhengighetsinjeksjon eller avhengighetsinjeksjon med typing.<\/p>\n\n\n\n<p>Et problem her er at vi m\u00e5 kjenne kodebasen for \u00e5 kunne gj\u00f8re en skikkelig refaktorering. Jeg er ikke s\u00e5 godt kjent med kodebasen til dette prosjektet siden jeg tok det som et eksempel, s\u00e5 av praktiske grunner vil vi g\u00e5 for den f\u00f8rste strategien, \u00e5 ikke gj\u00f8re noe. Selv om vi vil unng\u00e5 det meste av refaktorering, \u00f8nsker vi \u00e5 jobbe med avhengighetene i <em>rot<\/em> pakke.<\/p>\n\n\n\n<p>Rotpakken inneholder alt limet fra <strong>Rails-rammeverket<\/strong>, alle klassene vi arver fra og f\u00e5r alle til \u00e5 fungere sammen. S\u00e5 for \u00e5 l\u00f8se de sirkul\u00e6re avhengighetene, skal vi opprette en ny pakke kalt rails i f\u00f8lgende trinn:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Flytt alle applikasjonsfiler og -mapper fra appen til <code>app\/packages\/rails<\/code>.<\/li>\n\n\n\n<li>Opprett en<code>package.yml<\/code> for pakken med samme konfigurasjon som de foreg\u00e5ende pakkene.<\/li>\n\n\n\n<li>Legg til alle de nye filbanene i <code>packwerk.yml<\/code>.<\/li>\n\n\n\n<li>Legg til <code>app\/packages\/rails<\/code> som en avhengighet fra resten av pakkene.<\/li>\n<\/ol>\n\n\n\n<p>N\u00e5r vi har opprettet pakken, vil vi begynne \u00e5 legge merke til mange filer som kan struktureres p\u00e5 nytt. Etter \u00e5 ha flyttet alt til den tilsvarende pakken og akseptert<br>avhengigheter f\u00e5r vi en ny struktur og en renere graf.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/graph.png\" alt=\"Pakningsstruktur med skinnepakke \" title=\"Eksempel p\u00e5 pakkestruktur med rails-pakke\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/8.png\" alt=\"Graf uten sirkul\u00e6re rotavhengigheter\" title=\"Eksempel p\u00e5 en graf uten sirkul\u00e6re rotavhengigheter\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Fjern avhengigheter fra rotpakken<\/h3>\n\n\n\n<p>N\u00e5 ser grafen v\u00e5r mye bedre ut, og det ville v\u00e6rt flott hvis vi kunne fjerne alle avhengighetene fra rotpakken. Hvis vi sjekker deprecated_references.yml i rotpakken, vil vi legge merke til at de fleste av dem er fra <code>test<\/code> , <code>lib\/tasks<\/code> , <code>db<\/code> og <code>konfigurasjon<\/code><br>mappe. For \u00e5 l\u00f8se disse avhengighetene skal vi opprette en testmappe i hver pakke. \u00c5 ha noe s\u00e5nt som <code>app\/pakker\/brukere\/test<\/code>. Deretter skal vi ekskludere <code>lib\/tasks<\/code> , <code>db<\/code> og <code>konfigurasjon<\/code>blant andre mapper fra <strong>Packwerk<\/strong> siden disse avhengighetene egentlig ikke er viktige i analysen v\u00e5r, og vi ikke har noen enkel m\u00e5te \u00e5 l\u00f8se dem p\u00e5. Vi vil legge til f\u00f8lgende i v\u00e5r <em>packwerk.yml<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">ekskluder:\n- \"{bin,node_modules,script,tmp,vendor,lib,db,config,perf_scripts}\/**\/*\"\n- \"lib\/tasks\/**\/*.rake\"<\/code><\/pre>\n\n\n\n<p>N\u00e5r vi har flyttet alle testene fra rotpakken og ekskludert mappene fra analysen, f\u00e5r vi en ny graf uten rotavhengigheter.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/9.png\" alt=\"Graf uten rotavhengigheter\" title=\"Graf uten rotavhengigheter\"\/><\/figure>\n\n\n\n<p>Som vi ser, har vi fortsatt sirkul\u00e6re avhengigheter i<code>brukere<\/code> , <code>repos<\/code> , og <code>dokumenter<\/code> . Selv om vi ikke l\u00f8ste dem, har vi viktig informasjon \u00e5 formidle n\u00e5. Vi vet at alle <a href=\"https:\/\/thecodest.co\/nb\/blog\/how-to-hire-the-best-outsourced-development-team-for-a-scaleup\/\">team<\/a> som utf\u00f8rer endringer i en av disse pakkene, vil sannsynligvis m\u00e5tte utf\u00f8re endringer i pakkene med den sirkul\u00e6re avhengigheten. P\u00e5 den annen side vet vi at et team kan jobbe med <code>github_fetchers<\/code> utelukkende \u00e5 vite hvilke pakker som er<br>blir p\u00e5virket av endringene i hvert \u00f8yeblikk.<\/p>\n\n\n\n<p>Det endelige resultatet av prosjektet finner du her <a href=\"https:\/\/github.com\/niconisoria\/codetriage-packwerk\" rel=\"nofollow\">her<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Neste trinn<\/h3>\n\n\n\n<p>Som et neste trinn kan du h\u00e5ndheve konstant personvern i hver pakke og bare eksponere det offentlige API-et som vil v\u00e6re tilgjengelig fra andre pakker. Du kan enkelt konfigurere hvor API-et ditt skal plasseres i <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: min\/tilpasset\/sti\/<\/code><\/pre>\n\n\n\n<p><code> <\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Konklusjoner<\/h2>\n\n\n\n<p><strong>Packwerk<\/strong> gir oss mye informasjon om applikasjonen v\u00e5r, og med den informasjonen kan vi ta beslutninger for \u00e5 forbedre arbeidsflyten til teamene v\u00e5re. Selv om prosessen s\u00e5 ut til \u00e5 v\u00e6re lang og med mange konfigurasjoner, trenger det ikke alltid \u00e5 v\u00e6re slik. Vi kan begynne med \u00e5 opprette pakker bare for den nye koden som legges til i applikasjonen, og deretter modulere gradvis. S\u00e5 n\u00e5 kan vi begynne \u00e5 snakke om gradvis modularisering, et konsept introdusert av Stephan Hagemann <em>\"For f\u00f8rste gang kan vi bestemme oss for \u00e5 begynne \u00e5 modularisere en del av koden p\u00e5 en ambisi\u00f8s m\u00e5te ... Dette gj\u00f8r det mulig for oss \u00e5 skape et gradvis voksende st\u00f8ttesystem mot en bedre applikasjonsstruktur.\"<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Kilder<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/leanpub.com\/package-based-rails-applications\" rel=\"nofollow\">Gradvis modularisering for Ruby on Rails - Stephan Hagemann<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/shopify.engineering\/enforcing-modularity-rails-apps-packwerk\">H\u00e5ndhevelse av modularitet i Rails-apper med 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\">Kildekoden til artikkelen<\/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=\"R\u00e5dgivning innen digital produktutvikling\"\/><\/a><\/figure>\n\n\n\n<p><strong>Les mer<\/strong><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/graphql-ruby-what-about-performance\">GraphQL Ruby. Hva med ytelse?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/rails-and-other-means-of-transport\">Skinner og andre transportmidler<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/rails-development-with-tmux-vim-fzf-ripgrep\">Rails-utvikling med TMUX, Vim, Fzf + Ripgrep<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>I den andre episoden av v\u00e5r Ruby on Rails-modularisering med Packwerk skal vi se n\u00e6rmere p\u00e5 konseptet med applikasjonen som en pakke.<\/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\/nb\/blogg\/ruby-on-rails-modularisering-med-packwerk-episode-ii\/\" \/>\n<meta property=\"og:locale\" content=\"nb_NO\" \/>\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\/nb\/blogg\/ruby-on-rails-modularisering-med-packwerk-episode-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 minutter\" \/>\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\":\"nb-NO\",\"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\":\"nb-NO\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"nb-NO\",\"@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\":\"nb-NO\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\",\"name\":\"The Codest\",\"url\":\"https:\\\/\\\/thecodest.co\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"nb-NO\",\"@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\":\"nb-NO\",\"@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\\\/nb\\\/author\\\/thecodest\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ruby on Rails modularisering med Packwerk Episode 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\/nb\/blogg\/ruby-on-rails-modularisering-med-packwerk-episode-ii\/","og_locale":"nb_NO","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\/nb\/blogg\/ruby-on-rails-modularisering-med-packwerk-episode-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 minutter"},"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":"nb-NO","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 modularisering med 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":"nb-NO","potentialAction":[{"@type":"ReadAction","target":["https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/"]}]},{"@type":"ImageObject","inLanguage":"nb-NO","@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":"nb-NO"},{"@type":"Organization","@id":"https:\/\/thecodest.co\/#organization","name":"The Codest","url":"https:\/\/thecodest.co\/","logo":{"@type":"ImageObject","inLanguage":"nb-NO","@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":"nb-NO","@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\/nb\/author\/thecodest\/"}]}},"_links":{"self":[{"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/posts\/3566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/comments?post=3566"}],"version-history":[{"count":10,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/posts\/3566\/revisions"}],"predecessor-version":[{"id":7983,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/posts\/3566\/revisions\/7983"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/media\/3567"}],"wp:attachment":[{"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/media?parent=3566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/categories?post=3566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thecodest.co\/nb\/wp-json\/wp\/v2\/tags?post=3566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}