wagons 0.6.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +143 -0
- data/Rakefile +20 -17
- data/lib/tasks/wagons.rake +14 -17
- data/lib/wagons/extensions/migration.rb +40 -12
- data/lib/wagons/extensions/test_case.rb +5 -1
- data/lib/wagons/installer.rb +1 -1
- data/lib/wagons/version.rb +1 -1
- data/lib/wagons/wagon.rb +3 -3
- data/test/ci/{rails52.gemfile → rails61.gemfile} +2 -1
- data/test/ci/rails61.gemfile.lock +167 -0
- data/test/ci/rails70.gemfile +11 -0
- data/test/dummy/Gemfile +2 -1
- data/test/dummy/Gemfile.lock +190 -120
- data/test/dummy/config/application.rb +0 -13
- data/test/dummy/config/environments/development.rb +0 -5
- data/test/dummy/config/environments/production.rb +0 -9
- data/test/dummy/config/initializers/secret_token.rb +1 -5
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/development.sqlite3-shm +0 -0
- data/test/dummy/db/development.sqlite3-wal +0 -0
- data/test/dummy/db/schema.rb +4 -5
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3-shm +0 -0
- data/test/dummy/db/test.sqlite3-wal +0 -0
- data/test/dummy/log/development.log +543 -0
- data/test/dummy/log/test.log +25331 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-H/-HtXnef0HYbCf4IQCm3aqe59wL4bpgzS_yqaHC7iD7I.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0w/0w13MOsljskmRGYd7h_dmRxupsbtm1UGG8UKWdpgqxE.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1I/1IDB5qr1TR6_Ex6y1wfpAnPPcuGNbDqKAFp-bicMdJw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1Q/1Q--32pSu0X8tgKnQKviniT1f9fr270Siz7MLazfjY0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1q/1qLm_ssdtiWjLGDfOyEXLBpOpSFyDftrTe-J5A-x0fM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/22/22jeSha1gQut3uUfoP44m3l99L_7N8usml4LS737Q9w.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/24/24_tNLrmt-so6UcYfOScWzfJ9eMRN-Vr2TlQdp4rMwc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2r/2rLBgIivfRbzIntqLcL4qIWdGUayQDXzPX4Zs7z5nyw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3H/3HRYOSvPLUiLY8pL0DrEsH7doLosVFAhNEPYzRJvBJ4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3c/3cK6cxzebN6u3koHiOwekBT0V7sOWJ1fSJi7NNdNm6c.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3c/3cq6SBzo29D833trP4SsvTdbQFZVgHc4l1F0H3zSXv4.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4H/4HmxH_jTqYtN8qzSD6B1E5zoly7Us6enPW634qmOqhw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5p/5pIt6wS1BhH8MCXj73QMvG-ydW4NYZGwK0LtqRWWijk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6P/6P5A7JnNeGH2r_6lUbaJbwJjgp52R5WYy9FXdMzAP5M.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6u/6uAmv-3XxnNSicBxCQxV6qa6uf-paBhbcGlMQKVgLfc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7E/7EF_s-ENUfH9-gY_3l3BqtEvz1eR5lA1RIIXtQrPTfA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8E/8ER8figK9NszHC0GERob9QKvw4FqifCDmXMRFBU8lBY.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8a/8aRdJtxvRmSy8nbyfzd_38EOvQDCI6lNv31LaqtpGuQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9S/9SKoByIXxOhEZpdYEljQDxQO3klZtZo_q0da5mM7AMs.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9j/9jqgHrQ7pZsKefNZU7qkNWAuu9doJE34xxfgRxrPZHQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/AU/AUcrNcDCsowVJZSQHQcQw0Vd2y-bl_JwYlxVV_Fm5u0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CQ/CQ-eB4eoQoV4KyNA1L69J-e1PJUhh-1afQdrey7YjWo.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Db/DbmLC3wtG7ztEvkzmVAubW8vf37XdD0bT3Kh73oed1A.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/E_/E_9AuEMLlN8ewb_6kPjLBen7_maGlmUctv0og1oBLHA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ej/EjlPEjuWuoa8ddDFxYmNJcDBJciSdyi7top8aI8Qhi0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Em/Emyq6KCg079U1cAHGJ8ldkvAH0_vjape2X0DuypLkHA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fk/FkfYCBdaahKiox0qtLhN8JdG8c8kKscddoj1hZFyKss.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/GL/GLfgFsH7gYztSz8KqppT6RAF-xlterP4wlPr49DaqY0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Hv/Hv2IxpRjvLKwwO-zzNWLMJSyL2xRH9QRNFGUP-r_PMg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/JC/JCL1JaTAfMuWVygoApJocm0bfiJVcGMUpTlyCbWRcTE.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/NO/NOvhBx5Ck6mzR9lbTh4oYkFyZuBhW8kL0xq2fXYNZvc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Nx/Nx6PN_fylzZexApM9JmmnNNw-uLk71OfIgJ9zdGNLu4.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/OR/ORoJxKNF59Ei4Yg_hIlxcVpLhFmKUXQWKpedcRPHqnw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PH/PHWXANBrMyYy54Iv8E_E-1rVQTumNJ3u7NUIB5BRApA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pc/PcK1T7ShesfXYFQ5W0iDvn5_NCn9mdRY-iKLYmErizs.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Q7/Q7XEjIX6hH0eYgyYXzK_eRM0b3cYXuvkR48xX2IbTe4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QM/QMwgAVHjwvL_AddHLU5X3p9JND42X7g7zuNQh4FStEU.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QW/QWYLzm_V5roD5W780sxbErySkEfXH9TP6U5wp1kTAsQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RY/RYblxQYTWrFsoTHUoRPMM5nsWzp7OdBla5t3WxqCJk4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Rk/RkNi1mU3vLaSmMYTSCSnlwE-9oKy_W3zbtGnebp8giM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Sh/ShZe4Yd3d4ey6lkV51RLsCo0xviOwe17edjrzNs6xKw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Tg/TgTcVvqf5KTGti25aDSVdPzdEFSzFCA7TIgv36nVcSw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Tt/TtCo1neXEwVGrBDA9g7KFKfHfrw24_xMjrxpTWj6hqU.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/V0/V0xH9hW5hqbm6BDG8n6Ax2lqGsz0MfR1iXOxPDDU9J0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/WR/WR6tsay9cs1pVib3TaKDHXbSLwDXgEFi7yI6zAsdIos.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/XA/XAHwGWu2FidHKKPWHkXTeqsL616yZD-bj78n2tifQiw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Z1/Z1xiE6AeOFjmwb1QypT0chrrYtEfojQh9xF6dvo15Oc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_Z/_ZGxbIs0pIikJpeITx66Vj5HZlTlwPjBtTIxZY4Llhw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_c/_cATGhGdtRwYqswf2eDhF248i27ZoWhL6JUOJztaDRs.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_f/_fALMSlqEIAoEcArNZCH9a0pmK-9extGEC3rN19EE0Q.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_m/_mEPYNj4UPh88JyBBGxj9LlOgG2hUfzgmdLqzqBQQBE.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aF/aFYi0QN0ocrEJd5NcK0n5oruPgfi0bbV_yoiKJQIRcc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aU/aUji3Ouh9B82G7bYfgs1QcgsrCBmS4-f4ILsN_C_zFw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aY/aYZRIcKNgaTkEdL-ujKXKwqxK2cVyZole5qthnSYTz8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/b7/b7lBpkBxQaCxHBBRf-QF0CiQKnRE8kYGLUzgAPTjf_k.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bP/bPNHnuI52miVtJqlBT_g5qG18I0oAHSYE9bI7Ptrofg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bU/bUpMjwfdKLlejY8OWALhTYtESG4S5xUg9LOEryfqsh8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bd/bdrnMYD4qOAIIdZCbT39Wkn2wzabKadpCmgWLT56Lq8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dg/dgjHA3yS-cfHM6U2pIHqfOZ9E-ooNW7JbqArpn5_DSI.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eu/euosPQOlq1xNPPLzxhZKDyWfm75qDMlfXRK5pzbPDk0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/h4/h41FBu5275MRJYh-QtgDJZpvJQ4TD6nnvTv93-yfw8s.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ig/ig0NZPffrlU5nyvxScGhp9RbX-ztkRcop-W3z_0GOxg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ix/ixZDJv3nUs5OyxiRdK1zZ7AnmYUHoPTk0uF-f1CZ-IQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jv/jvhMb4IFtynnfkP-m13mfrg9gYy4iDEjYnZiK2YBuWg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/l_/l_tJ9WwBL9Q8XjxQN56nGuGtCrP7kGBvE8e76g8tRC0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/m5/m5Zzglx0goFadTvj77IDwqNQpO6-UAKhPq6cpeKq-ks.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mH/mHAhTi2hfFhPk9Q0Q_fl1eh_7Za4SNRUevCoJRLcZb0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oi/oifW-FoUUBJZovp7spCmtZ2nV0p36Sm-3pdjeOd_MBI.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pg/pg4_Xb9Jpu2-lF5UTFVEdSygm2el9xcJ_PTt5bSXGos.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qP/qP3gEansoZiP9AhSv2BIJUz5hq2qwkMBjj-NJ3Ibdt0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/qYvyX-tPRbBGYCkP1_8f6fthjekc2G7Eq6V_afdgbrY.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/rG/rGDKy38JC9huYGZLtA-wiM_C5tv0OChr97sVU-HUesQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s9/s9hTotMjw4ddx-wmP0kGle-EXqVg-CaCo1LMpDTZeKQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/w3/w38rfd6qdVo1aV28n_6tWWrNnwrxR55-kEZc6pyA5zk.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/wx/wxwvso5wh0QLD0Vwu4VJimRWxLDGYfCaGMOsrLYrLg8.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xG/xGMnO4s6f7EDeEia5H8zPU1p-Z-MmsO0Val4gsFgpYk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xR/xRih9fv1y9PmtOktqzUIrowdEqL2bBp6EAxyNIdZ9yw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xT/xTjKotv2c8rw6rRSG5MFPKuThESil_pEyLnT0NMaQ0c.cache +0 -0
- data/test/dummy/vendor/wagons/superliner/Gemfile.lock +171 -123
- data/test/test_helper.rb +1 -4
- metadata +310 -162
- data/README.rdoc +0 -146
- data/test/ci/rails52.gemfile.lock +0 -146
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy/config/initializers/inflections.rb +0 -15
- data/test/dummy/config/initializers/mime_types.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 115a339a7bcdac6dcaa1421a9c10b721ccbe58274b02fd88913c9a0c6c012bc1
|
4
|
+
data.tar.gz: 8b75fa6188d5742edc1468d07b07ecc9b7c4464c4f42eb52f4a12bf30af24c4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb5f39ce863e8540db973fcb4882b35e8e3734edc380e58df0b72ed9da53412081b94389782ac6dccb431b204f400470bb88aeabecea37644e49b78f8acd71e0
|
7
|
+
data.tar.gz: 1f6330feb1ceaf5bf001c126a95dd661432e4ac96cf170031e26db94da183a3955406adc0491d65ce480057c2137c58bdf5971e0608ed8e62d1c9bc856a1bdde
|
data/MIT-LICENSE
CHANGED
data/README.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# Here Be Wagons
|
2
|
+
|
3
|
+
[![Build Status](https://github.com/codez/wagons/actions/workflows/build.yml/badge.svg)](https://github.com/codez/wagons/actions/workflows/build.yml)
|
4
|
+
[![Code Climate](https://api.codeclimate.com/v1/badges/32a0d860544681cf718c/maintainability)](https://codeclimate.com/github/codez/wagons/maintainability)
|
5
|
+
|
6
|
+
Wagons are extensions to your application train running on Rails. You can see them as plugins that
|
7
|
+
extend the behavior of your specific Rails application. This framework makes it easy to create and
|
8
|
+
manage them.
|
9
|
+
|
10
|
+
First of all, wagons are basically [Rails Engines](http://api.rubyonrails.org/classes/Rails/Engine.html),
|
11
|
+
so make sure you are familiar with them. Wagons provide a handful of additions so your wagon
|
12
|
+
engines actually know your application.
|
13
|
+
|
14
|
+
Wagons differ from engines in a few points:
|
15
|
+
|
16
|
+
- Wagons extend your application, engines extend Rails.
|
17
|
+
- Wagon migrations are kept separately from your application's migrations to enable easy addition and removal of wagons.
|
18
|
+
- When developing and testing, wagons use the main application instead of a dummy application.
|
19
|
+
|
20
|
+
## Setup
|
21
|
+
|
22
|
+
As always, add this declaration to your application's Gemfile:
|
23
|
+
|
24
|
+
gem 'wagons'
|
25
|
+
|
26
|
+
Now you are ready for your first wagon. Generate it with
|
27
|
+
|
28
|
+
rails generate wagon [name]
|
29
|
+
|
30
|
+
This creates the structure of your wagon in `vendor/wagons/[name]`. In there, you find the file `lib/[name]/wagon.rb`,
|
31
|
+
which defines the `Rails::Engine` and includes the `Wagon` module. Here, you may also extend your application
|
32
|
+
classes in a `config.to_prepare` block.
|
33
|
+
|
34
|
+
In order to load wagons with the application, an entry in the `Gemfile` would be sufficient.
|
35
|
+
To keep things flexible, wagons come with an additional file `Wagonfile`. Generate one for development purposes with:
|
36
|
+
|
37
|
+
rake wagon:file
|
38
|
+
|
39
|
+
This will include all wagons found in `vendor/wagons` in development mode.
|
40
|
+
Do not check `Wagonfile` into source control. In your deployments, you might want to have different entries in there.
|
41
|
+
|
42
|
+
Once your wagon is ready to ship, a gem can be built with `rake build`. The name of a wagon gem must always start
|
43
|
+
with the application name, followed with an underscore and the actual name of the wagon. In production, you may
|
44
|
+
simply install the wagon gem and explicitly add a declaration to your `Wagonfile`.
|
45
|
+
|
46
|
+
If your wagon contains migrations and probably seed data, update your database with
|
47
|
+
|
48
|
+
rake wagon:setup WAGON=[name]
|
49
|
+
|
50
|
+
Leave off the `WAGON` parameter to setup all wagons in your `Wagonfile`. This should not interfere with wagons that are
|
51
|
+
already set up. Migrations are only run if they are not loaded yet, as usual.
|
52
|
+
|
53
|
+
## Extending your application with a wagon
|
54
|
+
|
55
|
+
Ruby and Rails provide all the magic required to extend your application from within a wagon.
|
56
|
+
|
57
|
+
To add new models, controllers or views, simply create them in the `app` directory of your wagon, as you would in a regular engine.
|
58
|
+
|
59
|
+
To extend existing models and controllers, you may create modules with the required functionality.
|
60
|
+
Include them into your application classes in a `config.to_prepare` block in `lib/[wagon_name]/wagon.rb`.
|
61
|
+
|
62
|
+
To extend views, wagons provides a simple view helper that looks for partials in all view paths. Any template that
|
63
|
+
might be extended by a wagon can include a call like this:
|
64
|
+
|
65
|
+
<%= render_extensions :details %>
|
66
|
+
|
67
|
+
Any partials living in an equally named subfolder as the calling template and starting with the given key are rendered at this place.
|
68
|
+
|
69
|
+
## Wagon dependencies
|
70
|
+
|
71
|
+
Wagons may depend on each other and/or have certain requirements on their load order. To make sure something
|
72
|
+
is loaded before the current wagon, add a `require '[app_name]_[other_wagon]'` on top of the
|
73
|
+
`lib/[app_name]_[current_wagon].rb` file. For development dependencies, there is an extra `require_optional`
|
74
|
+
method that will not raise a `LoadError` if the dependency is not found.
|
75
|
+
|
76
|
+
To control that the main application actually supports a certain wagon, an application version may be defined
|
77
|
+
so wagons can define a requirement. The application version can be set in an initializer. Create it with:
|
78
|
+
|
79
|
+
rake wagon:app_version
|
80
|
+
|
81
|
+
Besides setting the version, this initializer will check all loaded wagons for their application requirement
|
82
|
+
and raise errors if one is not met. In `lib/[wagon_name]/wagon.rb` the requirement may be defined, e.g.:
|
83
|
+
|
84
|
+
app_requirement '>= 1.0'
|
85
|
+
|
86
|
+
The syntax follows the Ruby gem version and requirements.
|
87
|
+
|
88
|
+
## Seed Data
|
89
|
+
|
90
|
+
Wagons integrates [Seed Fu](https://github.com/mbleigh/seed-fu) for seed data. All seed data from the application
|
91
|
+
is also available in wagon tests, as long as no fixture files overwrite the corresponding tables.
|
92
|
+
|
93
|
+
Wagons may come with their own seed data as well. Simply put it into `db/fixtures[/environment]`. To allow for
|
94
|
+
an automatic removal of wagons, [Seed Fu-ndo](https://github.com/codez/seed-fu-ndo) is able to record
|
95
|
+
seed file instructions and destroy all entries that exist in the database. Just make sure that you only use
|
96
|
+
the `seed` and `seed_once` methods in these files, or the unseed may not work correctly.
|
97
|
+
|
98
|
+
## Beware
|
99
|
+
|
100
|
+
There are a few other things that work differently with wagons:
|
101
|
+
|
102
|
+
### Schema & Migrations
|
103
|
+
|
104
|
+
Wagons are extensions to your application that may vary between various installations. Wagon tables are added
|
105
|
+
and removed as wagons are installed or uninstalled. After you have added a wagon's gem to your production
|
106
|
+
`Wagonfile`, run `rake wagon:setup` to run the migrations and load the seed data. Before you remove them
|
107
|
+
from `Wagonfile`, run `rake wagon:remove WAGON=to_remove` to eliminate the artifacts from the database first.
|
108
|
+
|
109
|
+
In this way, the `schema.rb` file must only contain the tables of the application, not of all wagons.
|
110
|
+
When you have migrations for your main application and wagons loaded, the schema will not be dumped on
|
111
|
+
`db:migrate`. You need to either remove the wagons or reset the database before the schema may be dumped.
|
112
|
+
This is (currently) the cost for having arbitrary pluggable application extensions.
|
113
|
+
|
114
|
+
### Tests
|
115
|
+
|
116
|
+
Wagons use your application for tests. This is also true for your application's test database. To get the
|
117
|
+
correct setup, `app:db:test:prepare` is extended to run the migration of the current wagon and all its
|
118
|
+
dependencies, as well as their seed data. Once the database is set up, single tests may be run with
|
119
|
+
the usual `ruby -I test test/my_test.rb` command.
|
120
|
+
|
121
|
+
The `test_helper.rb` of the main application is included in all wagon tests. Any additions in
|
122
|
+
this file are available in wagon tests as well. The only thing wagons need to do is reseting the
|
123
|
+
fixture path to the wagon's test fixtures.
|
124
|
+
|
125
|
+
RSpec works fine with wagons as well. Simply put the heading lines found in `test_helper.rb` into your
|
126
|
+
`spec_helper.rb`.
|
127
|
+
|
128
|
+
### Gem Bundling
|
129
|
+
|
130
|
+
Bundler manages application dependencies, with a stress on application. Because wagons live
|
131
|
+
inside your application during development, the app's `Gemfile` is included in each wagon's `Gemfile`.
|
132
|
+
However, Bundler still keeps a separate `Gemfile.lock` for each wagon, so you have to make sure to keep
|
133
|
+
these up to date when you change your main application gems. The gem versions for the wagons should be
|
134
|
+
the same as for the application. `rake wagon:bundle:update` is here to help you exactly with that.
|
135
|
+
We recommend to NOT check in the Wagon's `Gemfile.lock` file into source control.
|
136
|
+
|
137
|
+
Unfortunately, adding wagon gems to the `Wagonfile` in production also breaks with Bundler's approach
|
138
|
+
of locking down application gems. Because of that, the `--deployment` option cannot be used
|
139
|
+
with wagons. If you install your gems from `vendor/cache` into `vendor/bundle` or so,
|
140
|
+
you still get most of the benefits of using Bundler, including the guarantee for the very same gem
|
141
|
+
versions as used in development.
|
142
|
+
|
143
|
+
Contributions to this or any other issues are very welcome.
|
data/Rakefile
CHANGED
@@ -30,24 +30,8 @@ Rake::TestTask.new(:test) do |test|
|
|
30
30
|
test.verbose = true
|
31
31
|
end
|
32
32
|
|
33
|
-
task :test => :
|
34
|
-
def in_dummy(command)
|
35
|
-
version = "RAILS_VERSION=\"#{ENV['RAILS_VERSION']}\" " if ENV['RAILS_VERSION']
|
36
|
-
Bundler.with_clean_env { sh "cd test/dummy && #{version}#{command}" }
|
37
|
-
end
|
38
|
-
|
33
|
+
task :test => :bundle do
|
39
34
|
begin
|
40
|
-
in_dummy 'rm -rf Gemfile.lock'
|
41
|
-
if ENV['ROOT_BUNDLE_PATH'] # used by travis-ci
|
42
|
-
in_dummy 'mkdir -p .bundle'
|
43
|
-
in_dummy 'echo "---\nBUNDLE_PATH: \"$ROOT_BUNDLE_PATH\"\n" > .bundle/config'
|
44
|
-
in_dummy 'cat .bundle/config'
|
45
|
-
in_dummy 'mkdir -p vendor/wagons/test_wagon/.bundle'
|
46
|
-
in_dummy 'echo -e "---\nBUNDLE_PATH: \"$ROOT_BUNDLE_PATH\"\n" > vendor/wagons/test_wagon/.bundle/config'
|
47
|
-
in_dummy 'mkdir -p vendor/wagons/superliner/.bundle'
|
48
|
-
in_dummy 'echo -e "---\nBUNDLE_PATH: \"$ROOT_BUNDLE_PATH\"\n" > vendor/wagons/superliner/.bundle/config'
|
49
|
-
end
|
50
|
-
in_dummy 'bundle'
|
51
35
|
in_dummy 'bundle exec rails g wagon test_wagon'
|
52
36
|
in_dummy 'bundle exec rake wagon:bundle:update'
|
53
37
|
in_dummy "bundle exec rake db:migrate test #{'-t' if Rake.application.options.trace}"
|
@@ -57,6 +41,20 @@ task :test => :set_rails_version do
|
|
57
41
|
end
|
58
42
|
end
|
59
43
|
|
44
|
+
task :bundle => :set_rails_version do
|
45
|
+
in_dummy 'rm -rf Gemfile.lock'
|
46
|
+
if ENV['ROOT_BUNDLE_PATH'] # used by ci
|
47
|
+
in_dummy 'mkdir -p .bundle'
|
48
|
+
in_dummy 'echo "---\nBUNDLE_PATH: \"$ROOT_BUNDLE_PATH\"\n" > .bundle/config'
|
49
|
+
in_dummy 'cat .bundle/config'
|
50
|
+
in_dummy 'mkdir -p vendor/wagons/test_wagon/.bundle'
|
51
|
+
in_dummy 'echo -e "---\nBUNDLE_PATH: \"$ROOT_BUNDLE_PATH\"\n" > vendor/wagons/test_wagon/.bundle/config'
|
52
|
+
in_dummy 'mkdir -p vendor/wagons/superliner/.bundle'
|
53
|
+
in_dummy 'echo -e "---\nBUNDLE_PATH: \"$ROOT_BUNDLE_PATH\"\n" > vendor/wagons/superliner/.bundle/config'
|
54
|
+
end
|
55
|
+
in_dummy 'bundle'
|
56
|
+
end
|
57
|
+
|
60
58
|
task :set_rails_version do
|
61
59
|
if ENV['BUNDLE_GEMFILE']
|
62
60
|
version = File.read(ENV['BUNDLE_GEMFILE'])[/gem\s*'rails',\s*'(.*)'/, 1]
|
@@ -65,3 +63,8 @@ task :set_rails_version do
|
|
65
63
|
end
|
66
64
|
|
67
65
|
task :default => :test
|
66
|
+
|
67
|
+
def in_dummy(command)
|
68
|
+
version = "RAILS_VERSION=\"#{ENV['RAILS_VERSION']}\" " if ENV['RAILS_VERSION']
|
69
|
+
Bundler.with_unbundled_env { sh "cd test/dummy && #{version}#{command}" }
|
70
|
+
end
|
data/lib/tasks/wagons.rake
CHANGED
@@ -123,7 +123,7 @@ eval(File.read(wagonfile)) if File.exist?(wagonfile)"
|
|
123
123
|
puts "\n*** #{w.wagon_name.upcase} ***" if wagons.size > 1
|
124
124
|
rel_dir = w.root.to_s.sub(Rails.root.to_s + File::SEPARATOR, '')
|
125
125
|
cmd = "cd #{rel_dir} && #{ENV['CMD']}"
|
126
|
-
Bundler.
|
126
|
+
Bundler.with_unbundled_env do
|
127
127
|
verbose(Rake.application.options.trace) { sh cmd }
|
128
128
|
end
|
129
129
|
end
|
@@ -143,14 +143,12 @@ eval(File.read(wagonfile)) if File.exist?(wagonfile)"
|
|
143
143
|
task :abort_if_pending_migrations => :environment do
|
144
144
|
paths = wagons.collect(&:migrations_paths).flatten
|
145
145
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
ActiveRecord::Migrator.new(:up, context.migrations, ActiveRecord::SchemaMigration).pending_migrations
|
153
|
-
end
|
146
|
+
context = ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration)
|
147
|
+
pending_migrations = ActiveRecord::Migrator.new(
|
148
|
+
:up,
|
149
|
+
context.migrations,
|
150
|
+
ActiveRecord::SchemaMigration
|
151
|
+
).pending_migrations
|
154
152
|
|
155
153
|
if pending_migrations.any?
|
156
154
|
puts "You have #{pending_migrations.size} pending migrations:"
|
@@ -188,12 +186,7 @@ namespace :db do
|
|
188
186
|
Rake::Task[:'db:_dump'].clear_actions
|
189
187
|
|
190
188
|
task :_dump do
|
191
|
-
context =
|
192
|
-
if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('6.0.0')
|
193
|
-
ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths)
|
194
|
-
else
|
195
|
-
ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::SchemaMigration)
|
196
|
-
end
|
189
|
+
context = ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::SchemaMigration)
|
197
190
|
migrated = Set.new(context.get_all_versions)
|
198
191
|
if migrated.size > context.migrations.size
|
199
192
|
puts "The database schema will not be dumped when there are loaded wagon migrations."
|
@@ -206,11 +199,15 @@ namespace :db do
|
|
206
199
|
end
|
207
200
|
|
208
201
|
task :_dump_rails do
|
209
|
-
|
202
|
+
schema_format =
|
203
|
+
Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('7.1.0') ?
|
204
|
+
ActiveRecord::Base.schema_format : ActiveRecord.schema_format
|
205
|
+
|
206
|
+
case schema_format
|
210
207
|
when :ruby then Rake::Task["db:schema:dump"].invoke
|
211
208
|
when :sql then Rake::Task["db:structure:dump"].invoke
|
212
209
|
else
|
213
|
-
raise "unknown schema format #{
|
210
|
+
raise "unknown schema format #{schema_format}"
|
214
211
|
end
|
215
212
|
Rake::Task[:'db:_dump_rails'].reenable
|
216
213
|
end
|
@@ -5,12 +5,12 @@ module ActiveRecord
|
|
5
5
|
# Extend maintain_test_schema! to include migrations of the current wagon to test
|
6
6
|
# or to make sure no wagon migrations are loaded when testing the main application.
|
7
7
|
def maintain_test_schema_with_wagons!
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
return unless maintain_test_schema?
|
9
|
+
|
10
|
+
# set migrations paths to core only, wagon migrations are loaded separately
|
11
|
+
Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
|
12
|
+
if app_needs_migration?
|
13
|
+
suppress_messages { load_wagon_schema! }
|
14
14
|
end
|
15
15
|
end
|
16
16
|
alias maintain_test_schema_without_wagons! maintain_test_schema!
|
@@ -19,11 +19,15 @@ module ActiveRecord
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def load_wagon_schema!
|
22
|
-
|
22
|
+
if rails_version_smaller_than('7.1.0')
|
23
|
+
Base.clear_all_connections!
|
24
|
+
else
|
25
|
+
Base.connection_handler.clear_all_connections!
|
26
|
+
end
|
23
27
|
|
24
28
|
# Contrary to the original rails approach (#load_schema_if_pending!),
|
25
29
|
# purge the database first to get rid of all wagon tables.
|
26
|
-
config = Base.configurations
|
30
|
+
config = Base.configurations.configs_for(env_name: 'test').first
|
27
31
|
Tasks::DatabaseTasks.purge(config)
|
28
32
|
|
29
33
|
Base.establish_connection(config)
|
@@ -34,7 +38,11 @@ module ActiveRecord
|
|
34
38
|
|
35
39
|
def load_app_schema(config)
|
36
40
|
Tasks::DatabaseTasks.load_schema(config)
|
37
|
-
|
41
|
+
if rails_version_smaller_than('7.1.0')
|
42
|
+
check_pending!
|
43
|
+
else
|
44
|
+
check_all_pending!
|
45
|
+
end
|
38
46
|
end
|
39
47
|
|
40
48
|
def app_needs_migration?
|
@@ -47,21 +55,41 @@ module ActiveRecord
|
|
47
55
|
end
|
48
56
|
|
49
57
|
def migration_versions_in_db
|
50
|
-
if
|
58
|
+
if schema_migration_table_exists?
|
51
59
|
migration_context.get_all_versions.to_set
|
52
60
|
else
|
53
61
|
[].to_set
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
65
|
+
def schema_migration_table_exists?
|
66
|
+
if rails_version_smaller_than('7.1.0')
|
67
|
+
Base.connection.table_exists?(SchemaMigration.table_name)
|
68
|
+
else
|
69
|
+
SchemaMigration.new(Base.connection).table_exists?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
57
73
|
def migration_context
|
58
|
-
if
|
74
|
+
if rails_version_smaller_than('7.1.0')
|
75
|
+
MigrationContext.new(Migrator.migrations_paths, SchemaMigration)
|
76
|
+
else
|
59
77
|
MigrationContext.new(Migrator.migrations_paths)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def maintain_test_schema?
|
82
|
+
if rails_version_smaller_than('7.0.0')
|
83
|
+
ActiveRecord::Base.maintain_test_schema
|
60
84
|
else
|
61
|
-
|
85
|
+
ActiveRecord.maintain_test_schema
|
62
86
|
end
|
63
87
|
end
|
64
88
|
|
89
|
+
def rails_version_smaller_than(version)
|
90
|
+
Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new(version)
|
91
|
+
end
|
92
|
+
|
65
93
|
end
|
66
94
|
end
|
67
95
|
end
|
@@ -4,7 +4,11 @@ module ActiveSupport #:nodoc:
|
|
4
4
|
def self.reset_fixture_path(path)
|
5
5
|
self.fixture_table_names = []
|
6
6
|
self.fixture_class_names = {}
|
7
|
-
|
7
|
+
if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('7.1.0')
|
8
|
+
self.fixture_path = path
|
9
|
+
else
|
10
|
+
self.fixture_paths = [path]
|
11
|
+
end
|
8
12
|
fixtures :all
|
9
13
|
end
|
10
14
|
end
|
data/lib/wagons/installer.rb
CHANGED
data/lib/wagons/version.rb
CHANGED
data/lib/wagons/wagon.rb
CHANGED
@@ -127,10 +127,10 @@ module Wagons
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def migration_context
|
130
|
-
if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('
|
131
|
-
ActiveRecord::MigrationContext.new(migrations_paths)
|
132
|
-
else
|
130
|
+
if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('7.1.0')
|
133
131
|
ActiveRecord::MigrationContext.new(migrations_paths, ActiveRecord::SchemaMigration)
|
132
|
+
else
|
133
|
+
ActiveRecord::MigrationContext.new(migrations_paths)
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
@@ -0,0 +1,167 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../..
|
3
|
+
specs:
|
4
|
+
wagons (0.6.1)
|
5
|
+
bundler (>= 1.1)
|
6
|
+
rails (>= 5.2)
|
7
|
+
seed-fu-ndo (>= 0.0.3)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
actioncable (6.1.7)
|
13
|
+
actionpack (= 6.1.7)
|
14
|
+
activesupport (= 6.1.7)
|
15
|
+
nio4r (~> 2.0)
|
16
|
+
websocket-driver (>= 0.6.1)
|
17
|
+
actionmailbox (6.1.7)
|
18
|
+
actionpack (= 6.1.7)
|
19
|
+
activejob (= 6.1.7)
|
20
|
+
activerecord (= 6.1.7)
|
21
|
+
activestorage (= 6.1.7)
|
22
|
+
activesupport (= 6.1.7)
|
23
|
+
mail (>= 2.7.1)
|
24
|
+
actionmailer (6.1.7)
|
25
|
+
actionpack (= 6.1.7)
|
26
|
+
actionview (= 6.1.7)
|
27
|
+
activejob (= 6.1.7)
|
28
|
+
activesupport (= 6.1.7)
|
29
|
+
mail (~> 2.5, >= 2.5.4)
|
30
|
+
rails-dom-testing (~> 2.0)
|
31
|
+
actionpack (6.1.7)
|
32
|
+
actionview (= 6.1.7)
|
33
|
+
activesupport (= 6.1.7)
|
34
|
+
rack (~> 2.0, >= 2.0.9)
|
35
|
+
rack-test (>= 0.6.3)
|
36
|
+
rails-dom-testing (~> 2.0)
|
37
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
38
|
+
actiontext (6.1.7)
|
39
|
+
actionpack (= 6.1.7)
|
40
|
+
activerecord (= 6.1.7)
|
41
|
+
activestorage (= 6.1.7)
|
42
|
+
activesupport (= 6.1.7)
|
43
|
+
nokogiri (>= 1.8.5)
|
44
|
+
actionview (6.1.7)
|
45
|
+
activesupport (= 6.1.7)
|
46
|
+
builder (~> 3.1)
|
47
|
+
erubi (~> 1.4)
|
48
|
+
rails-dom-testing (~> 2.0)
|
49
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
50
|
+
activejob (6.1.7)
|
51
|
+
activesupport (= 6.1.7)
|
52
|
+
globalid (>= 0.3.6)
|
53
|
+
activemodel (6.1.7)
|
54
|
+
activesupport (= 6.1.7)
|
55
|
+
activerecord (6.1.7)
|
56
|
+
activemodel (= 6.1.7)
|
57
|
+
activesupport (= 6.1.7)
|
58
|
+
activestorage (6.1.7)
|
59
|
+
actionpack (= 6.1.7)
|
60
|
+
activejob (= 6.1.7)
|
61
|
+
activerecord (= 6.1.7)
|
62
|
+
activesupport (= 6.1.7)
|
63
|
+
marcel (~> 1.0)
|
64
|
+
mini_mime (>= 1.1.0)
|
65
|
+
activesupport (6.1.7)
|
66
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
67
|
+
i18n (>= 1.6, < 2)
|
68
|
+
minitest (>= 5.1)
|
69
|
+
tzinfo (~> 2.0)
|
70
|
+
zeitwerk (~> 2.3)
|
71
|
+
builder (3.2.4)
|
72
|
+
concurrent-ruby (1.1.10)
|
73
|
+
crass (1.0.6)
|
74
|
+
erubi (1.11.0)
|
75
|
+
globalid (1.0.0)
|
76
|
+
activesupport (>= 5.0)
|
77
|
+
i18n (1.12.0)
|
78
|
+
concurrent-ruby (~> 1.0)
|
79
|
+
loofah (2.19.0)
|
80
|
+
crass (~> 1.0.2)
|
81
|
+
nokogiri (>= 1.5.9)
|
82
|
+
mail (2.7.1)
|
83
|
+
mini_mime (>= 0.1.1)
|
84
|
+
marcel (1.0.2)
|
85
|
+
method_source (1.0.0)
|
86
|
+
mini_mime (1.1.2)
|
87
|
+
minitest (5.16.3)
|
88
|
+
mocha (1.15.0)
|
89
|
+
net-protocol (0.1.3)
|
90
|
+
timeout
|
91
|
+
net-smtp (0.3.2)
|
92
|
+
net-protocol
|
93
|
+
nio4r (2.5.8)
|
94
|
+
nokogiri (1.13.8-x86_64-linux)
|
95
|
+
racc (~> 1.4)
|
96
|
+
open4 (1.3.4)
|
97
|
+
racc (1.6.0)
|
98
|
+
rack (2.2.4)
|
99
|
+
rack-test (2.0.2)
|
100
|
+
rack (>= 1.3)
|
101
|
+
rails (6.1.7)
|
102
|
+
actioncable (= 6.1.7)
|
103
|
+
actionmailbox (= 6.1.7)
|
104
|
+
actionmailer (= 6.1.7)
|
105
|
+
actionpack (= 6.1.7)
|
106
|
+
actiontext (= 6.1.7)
|
107
|
+
actionview (= 6.1.7)
|
108
|
+
activejob (= 6.1.7)
|
109
|
+
activemodel (= 6.1.7)
|
110
|
+
activerecord (= 6.1.7)
|
111
|
+
activestorage (= 6.1.7)
|
112
|
+
activesupport (= 6.1.7)
|
113
|
+
bundler (>= 1.15.0)
|
114
|
+
railties (= 6.1.7)
|
115
|
+
sprockets-rails (>= 2.0.0)
|
116
|
+
rails-controller-testing (1.0.5)
|
117
|
+
actionpack (>= 5.0.1.rc1)
|
118
|
+
actionview (>= 5.0.1.rc1)
|
119
|
+
activesupport (>= 5.0.1.rc1)
|
120
|
+
rails-dom-testing (2.0.3)
|
121
|
+
activesupport (>= 4.2.0)
|
122
|
+
nokogiri (>= 1.6)
|
123
|
+
rails-html-sanitizer (1.4.3)
|
124
|
+
loofah (~> 2.3)
|
125
|
+
railties (6.1.7)
|
126
|
+
actionpack (= 6.1.7)
|
127
|
+
activesupport (= 6.1.7)
|
128
|
+
method_source
|
129
|
+
rake (>= 12.2)
|
130
|
+
thor (~> 1.0)
|
131
|
+
rake (13.0.6)
|
132
|
+
seed-fu (2.3.9)
|
133
|
+
activerecord (>= 3.1)
|
134
|
+
activesupport (>= 3.1)
|
135
|
+
seed-fu-ndo (0.0.3)
|
136
|
+
seed-fu (>= 2.2.0)
|
137
|
+
sprockets (4.1.1)
|
138
|
+
concurrent-ruby (~> 1.0)
|
139
|
+
rack (> 1, < 3)
|
140
|
+
sprockets-rails (3.4.2)
|
141
|
+
actionpack (>= 5.2)
|
142
|
+
activesupport (>= 5.2)
|
143
|
+
sprockets (>= 3.0.0)
|
144
|
+
sqlite3 (1.5.3-x86_64-linux)
|
145
|
+
thor (1.2.1)
|
146
|
+
timeout (0.3.0)
|
147
|
+
tzinfo (2.0.5)
|
148
|
+
concurrent-ruby (~> 1.0)
|
149
|
+
websocket-driver (0.7.5)
|
150
|
+
websocket-extensions (>= 0.1.0)
|
151
|
+
websocket-extensions (0.1.5)
|
152
|
+
zeitwerk (2.6.1)
|
153
|
+
|
154
|
+
PLATFORMS
|
155
|
+
x86_64-linux
|
156
|
+
|
157
|
+
DEPENDENCIES
|
158
|
+
mocha
|
159
|
+
net-smtp
|
160
|
+
open4
|
161
|
+
rails (~> 6.1.0)
|
162
|
+
rails-controller-testing
|
163
|
+
sqlite3
|
164
|
+
wagons!
|
165
|
+
|
166
|
+
BUNDLED WITH
|
167
|
+
2.3.19
|
data/test/dummy/Gemfile
CHANGED