{"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-modularisointi-packwerkin-avulla-episodi-ii","status":"publish","type":"post","link":"https:\/\/thecodest.co\/fi\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/","title":{"rendered":"Ruby on Rails:n modulaarisointi Packwerk Episode II:n avulla"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Hakemus pakettina<\/h2>\n\n\n\n<p>Sovelluksen modulaaristaminen tapahtuu muuntamalla koko sovellus paketiksi.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Luo rakenne<\/h3>\n\n\n\n<p>Ensin meid\u00e4n on luotava <code>app\/packages<\/code> kansioon, johon sijoitamme kaikki pakettimme. Jotta voimme erist\u00e4\u00e4 pakettimme, meid\u00e4n t\u00e4ytyy erottaa jokainen <strong>MVC-k\u00e4site<\/strong> yhdess\u00e4 kansiossa. Kun <strong>CodeTriage <a href=\"https:\/\/thecodest.co\/fi\/dictionary\/why-do-projects-fail\/\">projekti<\/a><\/strong> Esimerkkin\u00e4 seuraavanlainen kuva.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/2.png\" alt=\"paketin rakenne \" title=\"esimerkki paketin rakenteesta\"\/><\/figure>\n\n\n\n<p>Jos yrit\u00e4mme ajaa palvelinta, se ei l\u00f6yd\u00e4 vakioita. Siksi meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 konfiguraatiorivi tiedostoon <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>Nyt sovellus toimii, mutta se ei l\u00f6yd\u00e4 n\u00e4kymi\u00e4, joten meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 toinen rivi konfiguraatioita meid\u00e4n <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\/fi\/blog\/ways-to-increase-your-rails-performance\/\">Kiskot<\/a>.root.join('app\/packages\/*\/views'))))<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Luo paketit<\/h3>\n\n\n\n<p>Rakenteemme on valmis, joten nyt voimme aloittaa pakettien luomisen. Sit\u00e4 varten meid\u00e4n tarvitsee vain lis\u00e4t\u00e4 tiedosto<code>package.yml<\/code> jokaiseen kansioon seuraavalla kokoonpanolla:<\/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=\"package.yml esimerkki\"\/><\/figure>\n\n\n\n<p><code>enforce_privacy<\/code>antaa <a href=\"https:\/\/thecodest.co\/fi\/blog\/why-us-companies-are-opting-for-polish-developers\/\">us<\/a> mahdollisuus erist\u00e4\u00e4 kaikki paketin vakiot ja ty\u00f6skennell\u00e4 julkisella <a href=\"https:\/\/thecodest.co\/fi\/blog\/compare-staff-augmentation-firms-that-excel-in-api-team-staffing-for-financial-technology-projects\/\">API<\/a>. Jotta julkiset vakiot voidaan paljastaa, meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 vakiot esimerkiksi seuraaviin kohtiin&nbsp;<code>packages\/users\/app\/public.<\/code>Toistaiseksi asetamme t\u00e4m\u00e4n kokoonpanon arvoon <em> v\u00e4\u00e4r\u00e4<\/em>.<\/p>\n\n\n\n<p><code>enforce_dependencies<\/code> varmistaa paketin riippuvuuden ja tarkistaa kaikki vakioviittaukset. Jos riippuvuutta ei ole nimenomaisesti m\u00e4\u00e4ritelty, se on rajan rikkominen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pakettij\u00e4rjestelm\u00e4n validointi<\/h3>\n\n\n\n<p><strong>Packwerk<\/strong> vahvisti kriteerin, jota meid\u00e4n on noudatettava, jotta meill\u00e4 olisi p\u00e4tev\u00e4 pakettij\u00e4rjestelm\u00e4. Voimme aloittaa <code>packwerk kelpuuttaa<\/code> konsolissamme.<\/p>\n\n\n\n<p>&nbsp;T\u00e4m\u00e4 tarkistaa kansiorakenteemme, <strong>paketin kokoonpano<\/strong>ja automaattinen polkuv\u00e4limuisti.<\/p>\n\n\n\n<p>Juuri nyt sovelluksemme ei ole voimassa, ja meid\u00e4n on korjattava kuormituspolut osoitteessa<strong><code>packwerk.yml<\/code>.<\/strong> T\u00e4t\u00e4 varten meid\u00e4n on vain lis\u00e4tt\u00e4v\u00e4 puuttuvat polut.<\/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# K\u00e4ytt\u00e4j\u00e4t\n- app\/packages\/k\u00e4ytt\u00e4j\u00e4t\/ohjaimet\n- app\/packages\/users\/mallit\n- app\/packages\/users\/package.yml\n- app\/packages\/users\/n\u00e4kym\u00e4t<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 vaiheessa olemme valmiita tarkistamaan rajarikkomukset sovelluksessamme. Rikkomusten tarkistamiseksi voimme suorittaa<code>packwerk update-deprecations<\/code> , t\u00e4m\u00e4 komento luo <code>deprecated_references.yml<\/code> tiedosto jokaiselle paketille. Jokaisesta tiedostosta l\u00f6ytyy paketin nimi, rikkomustyyppi ja tiedostopolku. Kaikkien n\u00e4iden tietojen avulla tied\u00e4mme, miss\u00e4 rikkomus tapahtuu, ja voimme tehd\u00e4 p\u00e4\u00e4t\u00f6ksen sen ratkaisemisesta.<\/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=\"deprecated_references.yml esimerkki\"\/><\/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    :\n    - dependency\n    tiedostot:\n    - rb: app\/packages\/users\/models\/user.rb: app\/packages\/users\/models\/user.rb<\/code><\/pre>\n\n\n\n<p>Esimerkin avulla kuvaamme kaikki tuotetun tiedon osat.<br>by <strong>Packwerk<\/strong>.<\/p>\n\n\n\n<p>- <code>app\/packages\/repos<\/code> &nbsp;- paketti, jossa vakion rikkominen on<br>l\u00f6ytyi.<\/p>\n\n\n\n<p>- <code>::Repo<\/code> &nbsp;- polku tiedostoon, joka sis\u00e4lt\u00e4\u00e4 rikotun vakion.<\/p>\n\n\n\n<p>- <code>riippuvuus<\/code> &nbsp;- jonkinlainen rikkomus, joko riippuvuus tai yksityisyys.<\/p>\n\n\n\n<p>- <code>app\/packages\/users\/models\/user.rb<\/code> &nbsp;- polku tiedostoon, joka sis\u00e4lt\u00e4\u00e4 rikotun vakion.<\/p>\n\n\n\n<p>Viimeisen\u00e4 askeleena t\u00e4ss\u00e4 osiossa, \u00e4l\u00e4 unohda lis\u00e4t\u00e4 uusia luotuja tiedostopolkuja tiedostoon <code>packwerk.ym<\/code>l ja suorita validointi uudelleen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Riippuvuuden visualisointi<\/h3>\n\n\n\n<p>Kun kaikki package.yml:n tiedot ja <code>deprecated_references.yml<\/code>voimme sitten<br>visualisoida riippuvuuksien kuvaaja. T\u00e4t\u00e4 varten meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 toinen helmi, t\u00e4ss\u00e4 tapauksessa k\u00e4yt\u00e4mme seuraavaa komentoa <a href=\"https:\/\/github.com\/mquan\/pocky\" rel=\"nofollow\">Pocky<\/a>.<\/p>\n\n\n\n<p>Juokseva harava <code>pocky:generate<\/code> luomme tiedoston nimelt\u00e4 <code>packwerk.png<\/code> jossa voimme visualisoida ensimm\u00e4isen riippuvuuskaavion.<\/p>\n\n\n\n<p>Kun kaikki paketit on m\u00e4\u00e4ritelty, kuvaajamme n\u00e4ytt\u00e4\u00e4 t\u00e4lt\u00e4.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/5.png\" alt=\"graafi ilman hyv\u00e4ksyttyj\u00e4 riippuvuuksia\" title=\"graafi ilman hyv\u00e4ksyttyj\u00e4 riippuvuuksia esimerkki\"\/><\/figure>\n\n\n\n<p>riippuvuudet ovat jo olemassa, mutta se ei tarkoita, ett\u00e4 ne hyv\u00e4ksyt\u00e4\u00e4n <strong>Packwerk<\/strong>. Osoitteeseen<br>hyv\u00e4ksy\u00e4 riippuvuuden, meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 riippuvuuksien m\u00e4\u00e4ritys tiedostoon <code>package.yml<\/code><br>jokaisessa pakkauksessa. Keskitymme <code>mail_builders<\/code> koska se on paketti ilman kiert\u00e4v\u00e4\u00e4 riippuvuutta. On syyt\u00e4 mainita, ett\u00e4 <strong>Packwerk<\/strong> ei anna meid\u00e4n hyv\u00e4ksy\u00e4 py\u00f6reit\u00e4 riippuvuuksia.<\/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>Kun olet lis\u00e4nnyt t\u00e4m\u00e4n kokoonpanon, <strong>Pocky<\/strong> v\u00e4ritt\u00e4\u00e4 hyv\u00e4ksytyt riippuvuudet vihre\u00e4ll\u00e4.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/6.png\" alt=\"graafi, jossa on hyv\u00e4ksyttyj\u00e4 riippuvuuksia \" title=\"graafi ilman hyv\u00e4ksyttyj\u00e4 riippuvuuksia esimerkki\"\/><\/figure>\n\n\n\n<p>Voimme poistaa <code>deprecated_references.yml<\/code> osoitteesta <code>app\/packages\/mail_builders<\/code> ja ajaa<br><code>packwerk update-deprecations<\/code> j\u00e4lleen. Tiedostoa ei luoda uudestaan, koska kaikki<br>rikkomukset on korjattu t\u00e4t\u00e4 pakettia varten. On t\u00e4rke\u00e4\u00e4 mainita, ett\u00e4 vaikka emme Graph hyv\u00e4ksyisik\u00e4\u00e4n hyv\u00e4ksyttyj\u00e4 riippuvuuksia.<\/p>\n\n\n\n<p><strong><a href=\"https:\/\/thecodest.co\/fi\/blog\/hire-ror-developer\/\">Ruby<\/a> Railsin modularisointi Packwerkin avulla<\/strong> hyv\u00e4ksy\u00e4 riippuvuuksia, sovelluksemme toimii edelleen kuten ennenkin, mutta nyt meill\u00e4 on enemm\u00e4n riippuvuuksia.<br>tietoa p\u00e4\u00e4t\u00f6sten tekemiseen ja muokkaamiseen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Poista ymp\u00e4ripy\u00f6re\u00e4t riippuvuudet<\/h3>\n\n\n\n<p>Edellisess\u00e4 kuvaajassamme oli paljon ympyr\u00e4m\u00e4isi\u00e4 riippuvuuksia, jotka oli ratkaistava jotenkin. Meill\u00e4 on siihen erilaisia strategioita:<\/p>\n\n\n\n<p>- \u00c4l\u00e4 tee mit\u00e4\u00e4n,<\/p>\n\n\n\n<p>- Hyv\u00e4ksy riippuvuudet, Yhdist\u00e4 paketit,<\/p>\n\n\n\n<p>- Siirr\u00e4 <a href=\"https:\/\/thecodest.co\/fi\/dictionary\/what-is-code-refactoring\/\">koodi<\/a> pakettien v\u00e4lill\u00e4,<\/p>\n\n\n\n<p>- Toiminnon kopiointi,&nbsp;<\/p>\n\n\n\n<p>- Suorita riippuvuusinjektio tai riippuvuusinjektio tyypittelyn avulla.<\/p>\n\n\n\n<p>Yksi ongelma t\u00e4ss\u00e4 on se, ett\u00e4 voidaksemme tehd\u00e4 kunnollisen refaktoroinnin meid\u00e4n on tunnettava koodipohja. En tunne t\u00e4m\u00e4n projektin koodipohjaa kovin hyvin, koska otin sen esimerkkin\u00e4, joten k\u00e4yt\u00e4nn\u00f6n syist\u00e4 k\u00e4yt\u00e4mme ensimm\u00e4ist\u00e4 strategiaa, emme tee mit\u00e4\u00e4n. Vaikka v\u00e4lt\u00e4mme suurimman osan refaktoroinnista, haluamme ty\u00f6skennell\u00e4 riippuvuuksien parissa vuonna <em>root<\/em> paketti.<\/p>\n\n\n\n<p>Juuripaketti sis\u00e4lt\u00e4\u00e4 kaikki liimaukset paketin <strong>Rails-kehys<\/strong>, kaikki luokat, joista periydymme ja jotka saadaan toimimaan yhdess\u00e4. Jotta voimme ratkaista kiert\u00e4v\u00e4t riippuvuudet, luomme uuden paketin nimelt\u00e4 rails seuraavien vaiheiden avulla:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Siirr\u00e4 kaikki sovelluksen_ tiedostot ja kansiot sovelluksesta osoitteeseen <code>app\/packages\/rails<\/code>.<\/li>\n\n\n\n<li>Luo<code>package.yml<\/code> paketille, jolla on sama kokoonpano kuin edellisill\u00e4 paketeilla.<\/li>\n\n\n\n<li>Lis\u00e4\u00e4 kaikki uudet tiedostopolut osoitteeseen <code>packwerk.yml<\/code>.<\/li>\n\n\n\n<li>Lis\u00e4\u00e4 <code>app\/packages\/rails<\/code> muiden pakettien riippuvuussuhteena.<\/li>\n<\/ol>\n\n\n\n<p>Kun olemme luoneet paketin, alamme huomata paljon tiedostoja, jotka voidaan j\u00e4rjest\u00e4\u00e4 uudelleen. Kun kaikki on siirretty vastaavaan pakettiin ja hyv\u00e4ksyttyjen<br>riippuvuuksia, meill\u00e4 on uusi rakenne ja puhtaampi graafi.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/graph.png\" alt=\"Pakettirakenne kiskopaketin kanssa \" title=\"Pakettirakenne ja rails-pakettiesimerkki\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/8.png\" alt=\"Graafi ilman juuren ympyr\u00e4nmuotoisia riippuvuuksia\" title=\"Esimerkki kuvaajasta ilman juuren ympyr\u00e4nmuotoisia riippuvuuksia\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Poista riippuvuudet juuripaketista<\/h3>\n\n\n\n<p>Nyt kuvaajamme n\u00e4ytt\u00e4\u00e4 paljon paremmalta. Olisi hienoa, jos voisimme poistaa kaikki riippuvuudet juuripaketista. Jos tarkistamme deprecated_references.yml-tiedoston juuripaketista, huomaamme, ett\u00e4 suurin osa niist\u00e4 on per\u00e4isin tiedostosta <code>testi<\/code> , <code>lib\/tasks<\/code> , <code>db<\/code> ja <code>config<\/code><br>kansio. N\u00e4iden riippuvuuksien ratkaisemiseksi luomme testikansiot jokaiseen pakettiin. Jotain sellaista kuin <code>app\/packages\/users\/test<\/code>. Seuraavaksi j\u00e4t\u00e4mme pois <code>lib\/tasks<\/code> , <code>db<\/code> ja <code>config<\/code>muiden kansioiden joukossa osoitteesta <strong>Packwerk<\/strong> analyysi, koska n\u00e4m\u00e4 riippuvuudet eiv\u00e4t ole todella t\u00e4rkeit\u00e4 analyysimme kannalta, eik\u00e4 meill\u00e4 ole helppoa tapaa ratkaista niit\u00e4. Lis\u00e4\u00e4mme seuraavat asiat <em>packwerk.yml<\/em>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"ruby\" class=\"language-ruby\">sulkea pois:\n- {bin,node_modules,script,tmp,vendor,lib,db,config,perf_scripts}\/**\/*\"\n- \"lib\/tasks\/**\/*.rake\"<\/code><\/pre>\n\n\n\n<p>Kun kaikki testit on siirretty juuripaketista ja kansiot on j\u00e4tetty analyysin ulkopuolelle, meill\u00e4 on uusi kuvaaja ilman juuririippuvuuksia.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/app\/uploads\/2024\/05\/9.png\" alt=\"Graafi ilman juuririippuvuuksia\" title=\"Graafi ilman juuririippuvuuksia\"\/><\/figure>\n\n\n\n<p>Kuten n\u00e4emme, meill\u00e4 on edelleen ympyr\u00e4m\u00e4isi\u00e4 riippuvuuksia osoitteessa<code>k\u00e4ytt\u00e4j\u00e4t<\/code> , <code>repot<\/code> ja <code>docs<\/code> . Vaikka emme ratkaisseet niit\u00e4, meill\u00e4 on nyt t\u00e4rke\u00e4\u00e4 tietoa v\u00e4litett\u00e4v\u00e4n\u00e4. Tied\u00e4mme, ett\u00e4 jokainen <a href=\"https:\/\/thecodest.co\/fi\/blog\/how-to-hire-the-best-outsourced-development-team-for-a-scaleup\/\">joukkue<\/a> joka tekee muutoksia johonkin n\u00e4ist\u00e4 paketeista, joutuu todenn\u00e4k\u00f6isesti tekem\u00e4\u00e4n muutoksia paketteihin, joilla on kiert\u00e4v\u00e4 riippuvuus. Toisaalta tied\u00e4mme, ett\u00e4 tiimi voi ty\u00f6skennell\u00e4 seuraavilla aloilla <code>github_fetchers<\/code> yksinomaan, tiet\u00e4en mit\u00e4 paketteja ovat<br>joka hetki tapahtuvien muutosten vaikutuksesta.<\/p>\n\n\n\n<p>L\u00f6yd\u00e4t projektin lopputuloksen <a href=\"https:\/\/github.com\/niconisoria\/codetriage-packwerk\" rel=\"nofollow\">t\u00e4\u00e4ll\u00e4<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Seuraava vaihe<\/h3>\n\n\n\n<p>Seuraavana askeleena voisit varmistaa jatkuvan yksityisyyden suojan jokaisessa paketissa ja paljastaa vain julkisen API:n, johon muut paketit p\u00e4\u00e4sev\u00e4t k\u00e4siksi. Voit helposti m\u00e4\u00e4ritt\u00e4\u00e4, minne API sijoitetaan pakettien <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\">P\u00e4\u00e4telm\u00e4t<\/h2>\n\n\n\n<p><strong>Packwerk<\/strong> antaa meille paljon tietoa sovelluksestamme, ja n\u00e4iden tietojen avulla voimme tehd\u00e4 p\u00e4\u00e4t\u00f6ksi\u00e4 tiimien ty\u00f6nkulun parantamiseksi. Vaikka prosessi vaikutti pitk\u00e4lt\u00e4 ja paljon konfiguraatioita sis\u00e4lt\u00e4v\u00e4lt\u00e4, sen ei tarvitse olla aina samanlaista. Voimme aloittaa pakettien luomisen vain sovellukseemme lis\u00e4tty\u00e4 uutta koodia varten ja modulaarisoida sitten v\u00e4hitellen. Nyt voimme siis alkaa puhua asteittaisesta modulaarisoinnista. Stephan Hagemann esitteli t\u00e4m\u00e4n k\u00e4sitteen. <em>\"Voimme ensimm\u00e4ist\u00e4 kertaa p\u00e4\u00e4tt\u00e4\u00e4 aloittaa osan koodin modulaarisoinnin tavoitteellisesti... N\u00e4in voimme luoda asteittain laajenevan tukij\u00e4rjestelm\u00e4n kohti parempaa sovellusrakennetta\".<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">L\u00e4hteet<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/leanpub.com\/package-based-rails-applications\" rel=\"nofollow\">Asteittainen modulaarisointi Ruby on Rails:lle - Stephan Hagemann<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/shopify.engineering\/enforcing-modularity-rails-apps-packwerk\">Modulaarisuuden pakottaminen Rails-sovelluksissa Packwerkin avulla<\/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\">Artikkelin l\u00e4hdekoodi<\/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=\"Digitaalisen tuotekehityksen konsultointi\"\/><\/a><\/figure>\n\n\n\n<p><strong>Lue lis\u00e4\u00e4<\/strong><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/graphql-ruby-what-about-performance\">GraphQL Ruby. Ent\u00e4 suorituskyky?<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/rails-and-other-means-of-transport\">Kiskot ja muut liikennev\u00e4lineet<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/thecodest.co\/blog\/rails-development-with-tmux-vim-fzf-ripgrep\">Rails-kehitys TMUX, Vim, Fzf + Ripgrep -ohjelmilla<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Packwerkin kanssa toteutetun Ruby on Rails-modulaarisuuden toisessa jaksossa tarkastelemme sovelluksen k\u00e4sitett\u00e4 pakettina.<\/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\/fi\/blogi\/ruby-on-rails-modularisointi-packwerkin-avulla-episodi-ii\/\" \/>\n<meta property=\"og:locale\" content=\"fi_FI\" \/>\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\/fi\/blogi\/ruby-on-rails-modularisointi-packwerkin-avulla-episodi-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 minuuttia\" \/>\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\":\"fi\",\"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\":\"fi\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/thecodest.co\\\/blog\\\/ruby-on-rails-modularization-with-packwerk-episode-ii\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fi\",\"@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\":\"fi\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/thecodest.co\\\/#organization\",\"name\":\"The Codest\",\"url\":\"https:\\\/\\\/thecodest.co\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fi\",\"@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\":\"fi\",\"@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\\\/fi\\\/author\\\/thecodest\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Ruby on Rails modulaarisointi Packwerk Episode II:lla - The Codest - 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\/fi\/blogi\/ruby-on-rails-modularisointi-packwerkin-avulla-episodi-ii\/","og_locale":"fi_FI","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\/fi\/blogi\/ruby-on-rails-modularisointi-packwerkin-avulla-episodi-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 minuuttia"},"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":"fi","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 modulaarisointi Packwerk Episode II:lla - The Codest - 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":"fi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/thecodest.co\/blog\/ruby-on-rails-modularization-with-packwerk-episode-ii\/"]}]},{"@type":"ImageObject","inLanguage":"fi","@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":"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":"fi"},{"@type":"Organization","@id":"https:\/\/thecodest.co\/#organization","name":"Codest","url":"https:\/\/thecodest.co\/","logo":{"@type":"ImageObject","inLanguage":"fi","@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":"fi","@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\/fi\/author\/thecodest\/"}]}},"_links":{"self":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts\/3566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/comments?post=3566"}],"version-history":[{"count":10,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts\/3566\/revisions"}],"predecessor-version":[{"id":7983,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/posts\/3566\/revisions\/7983"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/media\/3567"}],"wp:attachment":[{"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/media?parent=3566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/categories?post=3566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thecodest.co\/fi\/wp-json\/wp\/v2\/tags?post=3566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}