wagons 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d06295f19bd1963830bd47006676c4b25eb2b1e7b30af0f8c2302996b129493
4
- data.tar.gz: d3c66601cc2869001432ae9877cbd03dfd6a68f9685aa47ab929a3b36023dcef
3
+ metadata.gz: 115a339a7bcdac6dcaa1421a9c10b721ccbe58274b02fd88913c9a0c6c012bc1
4
+ data.tar.gz: 8b75fa6188d5742edc1468d07b07ecc9b7c4464c4f42eb52f4a12bf30af24c4c
5
5
  SHA512:
6
- metadata.gz: bb293faaa5f7639c22dea5b78a98b202936ad6dd5fe6016c7215b81866861c9eb23a81a733e2dffc27ce09d1ebd7459f000a33dd73913e94633a4d0b96ad245a
7
- data.tar.gz: ac080f11d0a70f91755e510f365a9c36bfec28e2918fd167edf58524f40834c52b0fae01bcb8dd44b1e1bce8ca7abc50bd96e877220ffbd454b80a9e4aaac076
6
+ metadata.gz: bb5f39ce863e8540db973fcb4882b35e8e3734edc380e58df0b72ed9da53412081b94389782ac6dccb431b204f400470bb88aeabecea37644e49b78f8acd71e0
7
+ data.tar.gz: 1f6330feb1ceaf5bf001c126a95dd661432e4ac96cf170031e26db94da183a3955406adc0491d65ce480057c2137c58bdf5971e0608ed8e62d1c9bc856a1bdde
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2012 Pascal Zumkehr
1
+ Copyright 2012-2023 Pascal Zumkehr, Puzzle ITC
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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.
@@ -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
- pending_migrations =
147
- if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('6.0.0')
148
- context = ActiveRecord::MigrationContext.new(paths)
149
- ActiveRecord::Migrator.new(:up, context.migrations).pending_migrations
150
- else
151
- context = ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration)
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
- case ActiveRecord::Base.schema_format
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 #{ActiveRecord::Base.schema_format}"
210
+ raise "unknown schema format #{schema_format}"
214
211
  end
215
212
  Rake::Task[:'db:_dump_rails'].reenable
216
213
  end
@@ -19,16 +19,15 @@ module ActiveRecord
19
19
  private
20
20
 
21
21
  def load_wagon_schema!
22
- Base.clear_all_connections!
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 =
27
- if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('6.1.0')
28
- Base.configurations['test']
29
- else
30
- Base.configurations.configs_for(env_name: 'test').first
31
- end
30
+ config = Base.configurations.configs_for(env_name: 'test').first
32
31
  Tasks::DatabaseTasks.purge(config)
33
32
 
34
33
  Base.establish_connection(config)
@@ -39,7 +38,11 @@ module ActiveRecord
39
38
 
40
39
  def load_app_schema(config)
41
40
  Tasks::DatabaseTasks.load_schema(config)
42
- check_pending!
41
+ if rails_version_smaller_than('7.1.0')
42
+ check_pending!
43
+ else
44
+ check_all_pending!
45
+ end
43
46
  end
44
47
 
45
48
  def app_needs_migration?
@@ -52,29 +55,41 @@ module ActiveRecord
52
55
  end
53
56
 
54
57
  def migration_versions_in_db
55
- if Base.connection.table_exists?(SchemaMigration.table_name)
58
+ if schema_migration_table_exists?
56
59
  migration_context.get_all_versions.to_set
57
60
  else
58
61
  [].to_set
59
62
  end
60
63
  end
61
64
 
62
- def migration_context
63
- if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('6.0.0')
64
- MigrationContext.new(Migrator.migrations_paths)
65
+ def schema_migration_table_exists?
66
+ if rails_version_smaller_than('7.1.0')
67
+ Base.connection.table_exists?(SchemaMigration.table_name)
65
68
  else
69
+ SchemaMigration.new(Base.connection).table_exists?
70
+ end
71
+ end
72
+
73
+ def migration_context
74
+ if rails_version_smaller_than('7.1.0')
66
75
  MigrationContext.new(Migrator.migrations_paths, SchemaMigration)
76
+ else
77
+ MigrationContext.new(Migrator.migrations_paths)
67
78
  end
68
79
  end
69
80
 
70
81
  def maintain_test_schema?
71
- if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new('7.0.0')
82
+ if rails_version_smaller_than('7.0.0')
72
83
  ActiveRecord::Base.maintain_test_schema
73
84
  else
74
85
  ActiveRecord.maintain_test_schema
75
86
  end
76
87
  end
77
88
 
89
+ def rails_version_smaller_than(version)
90
+ Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new(version)
91
+ end
92
+
78
93
  end
79
94
  end
80
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
- self.fixture_path = path
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
@@ -1,3 +1,3 @@
1
1
  module Wagons
2
- VERSION = '0.7.0'
2
+ VERSION = '0.8.0'
3
3
  end
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('6.0.0')
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
 
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec :path => '../..'
4
4
 
5
- gem 'rails', '~> 6.0.0'
5
+ gem 'rails', '~> 7.0.0'
6
6
 
7
7
  group :test do
8
8
  gem 'mocha', :require => false
data/test/dummy/Gemfile CHANGED
@@ -6,7 +6,7 @@ gem 'wagons', :path => File.expand_path(__FILE__).split("test#{File::SEPARATOR}d
6
6
 
7
7
  group :development, :test do
8
8
  gem 'net-smtp'
9
- gem 'sqlite3'
9
+ gem 'sqlite3', '~> 1.4'
10
10
  end
11
11
 
12
12
  group :test do