railsmdb 1.0.0.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/LICENSE +20 -0
- data/README.md +117 -0
- data/Rakefile +65 -0
- data/lib/railsmdb/cli.rb +16 -0
- data/lib/railsmdb/commands/dbconsole/dbconsole_command.rb +65 -0
- data/lib/railsmdb/commands/setup/setup_command.rb +20 -0
- data/lib/railsmdb/commands.rb +5 -0
- data/lib/railsmdb/crypt_shared/catalog.rb +123 -0
- data/lib/railsmdb/crypt_shared/listing.rb +71 -0
- data/lib/railsmdb/downloader.rb +55 -0
- data/lib/railsmdb/ext/rails/command/behavior.rb +55 -0
- data/lib/railsmdb/ext/rails/command.rb +21 -0
- data/lib/railsmdb/ext/rails/generators/rails/app/app_generator.rb +48 -0
- data/lib/railsmdb/ext/rails/generators.rb +21 -0
- data/lib/railsmdb/extractor.rb +94 -0
- data/lib/railsmdb/generators/mongoid/model/model_generator.rb +41 -0
- data/lib/railsmdb/generators/mongoid/model/templates/model.rb.tt +19 -0
- data/lib/railsmdb/generators/setup/concerns/setuppable.rb +545 -0
- data/lib/railsmdb/generators/setup/setup_generator.rb +123 -0
- data/lib/railsmdb/generators/setup/templates/README.md.tt +3 -0
- data/lib/railsmdb/generators/setup/templates/_bin/railsmdb.tt +3 -0
- data/lib/railsmdb/generators/setup/templates/_config/initializers/mongoid.rb.tt +26 -0
- data/lib/railsmdb/prioritizable.rb +97 -0
- data/lib/railsmdb/version.rb +12 -0
- data.tar.gz.sig +4 -0
- metadata +182 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3c5fc774da8b9ad81904fc662c1845ce3a54569183d019ac896aa67a3359a60e
|
4
|
+
data.tar.gz: f0e5879e0fea0e817ccc269d74050e6bbef2f60cfe75c7d58d3c6767d6af35c3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ac54e057125932ef589776d1e18f08cd221725c5660ce75207f8250c76bcf3f18f7e8b88ceec5483c60b2e7479ae4b5e069e8a01f5edbe36b5bc3af143793e3f
|
7
|
+
data.tar.gz: c68a7050639334ea019bd952784af540d03e57aa9600095b4b4273f2d6eff072250cb03e62fcef6d64f201739ea7eaaea6494f7fa2638fbebd88929fd9ea1dc4
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2023-Present MongoDB Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# Railsmdb for Mongoid
|
2
|
+
|
3
|
+
Railsmdb is a command-line utility for creating, updating, managing,
|
4
|
+
and maintaining Rails applications that use Mongoid and MongoDB for data storage. It is an extension of (and supports all other functionality of) the `rails` command from Ruby on Rails.
|
5
|
+
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
To install Railsmdb:
|
10
|
+
|
11
|
+
```
|
12
|
+
$ gem install railsmdb
|
13
|
+
```
|
14
|
+
|
15
|
+
This will install a new command, `railsmdb`.
|
16
|
+
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
The `railsmdb` command may be invoked exactly as you would invoke the `rails` command. For example, to create a new Rails app:
|
21
|
+
|
22
|
+
```
|
23
|
+
$ railsmdb new my_new_rails_app
|
24
|
+
```
|
25
|
+
|
26
|
+
This will create a new folder under the current directory called `my_new_rails_app`, and will populate it with all the scaffolding necessary to begin building your app.
|
27
|
+
|
28
|
+
Unlike the `rails` command, however, it will set up the necessary gems and configuration for you to begin your Rails app using the MongoDB database, with Mongoid as the Object-Document Mapper (ODM).
|
29
|
+
|
30
|
+
Also, in your new application, there will be a new script in the `bin` folder: `bin/railsmdb`. You'll see `bin/rails` in there as well, but it now links to `bin/railsmdb`.
|
31
|
+
|
32
|
+
By default, `railsmdb` will not include ActiveRecord in your new application. If you wish to use both Mongoid and ActiveRecord (to connect to MongoDB and a separate, relational database in the same application), you can pass `--no-skip-active-record`:
|
33
|
+
|
34
|
+
```
|
35
|
+
$ railsmdb new my_new_rails_app --no-skip-active-record
|
36
|
+
```
|
37
|
+
|
38
|
+
This will set up your application to use both Mongoid, and sqlite3 (by default). To start with a different relational database instead, you can pass the `--database` option:
|
39
|
+
|
40
|
+
```
|
41
|
+
$ railsmdb new my_new_rails_app --no-skip-active-record --database=mysql
|
42
|
+
```
|
43
|
+
|
44
|
+
To see a list of all available commands, simply type `railsmdb` without any arguments.
|
45
|
+
|
46
|
+
```
|
47
|
+
$ railsmdb
|
48
|
+
|
49
|
+
# alternatively:
|
50
|
+
$ railsmdb -h
|
51
|
+
```
|
52
|
+
|
53
|
+
|
54
|
+
### Setting up railsmdb and Mongoid in an established Rails app
|
55
|
+
|
56
|
+
If you want to add `railsmdb` to an existing (non-Mongoid) Rails app, and add Mongoid configuration as well, you can use `railsmdb setup`:
|
57
|
+
|
58
|
+
```
|
59
|
+
$ railsmdb setup
|
60
|
+
```
|
61
|
+
|
62
|
+
This must be run from the root directory of a Rails project. It will replace `bin/rails` with `bin/railsmdb`, add the `mongoid.yml` configuration file and the `mongoid.rb` initializer, and add the necessary gem entries to the `Gemfile`.
|
63
|
+
|
64
|
+
**Note:** it is recommended to run this command in a branch, so that you can easily experiment with the changes and roll them back if necessary.
|
65
|
+
|
66
|
+
|
67
|
+
### Generating Mongoid models
|
68
|
+
|
69
|
+
You can use `railsmdb` to generate stubs for new Mongoid models. From within a project:
|
70
|
+
|
71
|
+
```
|
72
|
+
$ bin/railsmdb generate model person
|
73
|
+
```
|
74
|
+
|
75
|
+
This will create a new model at `app/models/person.rb`:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
class Person
|
79
|
+
include Mongoid::Document
|
80
|
+
include Mongoid::Timestamp
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
You can specify the fields of the model as well:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
# bin/railsmdb generate model person name:string birth:date
|
88
|
+
|
89
|
+
class Person
|
90
|
+
include Mongoid::Document
|
91
|
+
include Mongoid::Timestamp
|
92
|
+
field :name, type: String
|
93
|
+
field :birth, type: Date
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
You can instruct the generator to make the new model a subclass of another, by passing the `--parent` option:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
# bin/railsmdb generate model student --parent=person
|
101
|
+
|
102
|
+
class Student < Person
|
103
|
+
include Mongoid::Timestamp
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
And if you need to store your models in a different collection than can be inferred from the model name, you can specify `--collection`:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
# bin/railsmdb generate model course --collection=classes
|
111
|
+
|
112
|
+
class Course
|
113
|
+
include Mongoid::Document
|
114
|
+
include Mongoid::Timestamp
|
115
|
+
store_in collection: 'classes'
|
116
|
+
end
|
117
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
4
|
+
|
5
|
+
require 'bundler'
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
require 'rubygems/package'
|
8
|
+
require 'rubygems/security'
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
|
11
|
+
require_relative './lib/railsmdb/version'
|
12
|
+
|
13
|
+
def signed_gem?(path_to_gem)
|
14
|
+
Gem::Package.new(path_to_gem, Gem::Security::HighSecurity).verify
|
15
|
+
true
|
16
|
+
rescue Gem::Security::Exception
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
21
|
+
t.rspec_opts = %w[ -I lib -I spec/support --format documentation ]
|
22
|
+
end
|
23
|
+
|
24
|
+
task default: %i[ spec ]
|
25
|
+
|
26
|
+
Rake::Task['release'].clear
|
27
|
+
|
28
|
+
desc 'Release railsmdb gem'
|
29
|
+
task release: %w[ release:require_private_key clobber build release:verify release:tag release:publish ]
|
30
|
+
|
31
|
+
namespace :release do
|
32
|
+
desc 'Requires the private key to be present'
|
33
|
+
task :require_private_key do
|
34
|
+
raise 'No private key present, cannot release' unless File.exist?('gem-private_key.pem')
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Verifies that all built gems in pkg/ are valid'
|
38
|
+
task :verify do
|
39
|
+
gems = Dir['pkg/*.gem']
|
40
|
+
if gems.empty?
|
41
|
+
puts 'There are no gems in pkg/ to verify'
|
42
|
+
else
|
43
|
+
gems.each do |gem|
|
44
|
+
if signed_gem?(gem)
|
45
|
+
puts "#{gem} is signed"
|
46
|
+
else
|
47
|
+
abort "#{gem} is not signed"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'Creates a new tag for the current version'
|
54
|
+
task :tag do
|
55
|
+
system "git tag -a v#{Railsmdb::Version::STRING} -m 'Tagging release: #{Railsmdb::Version::STRING}'"
|
56
|
+
system "git push upstream v#{Railsmdb::Version::STRING}"
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Publishes the most recently built gem'
|
60
|
+
task :publish do
|
61
|
+
system "gem push pkg/railsmdb-#{Railsmdb::Version::STRING}.gem"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# rubocop:enable Metrics/BlockLength
|
data/lib/railsmdb/cli.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/app_loader'
|
4
|
+
require 'railsmdb/ext/rails/command'
|
5
|
+
require 'railsmdb/ext/rails/generators/rails/app/app_generator'
|
6
|
+
|
7
|
+
# the EXECUTABLES constant might eventually be frozen, so we should do
|
8
|
+
# this the long, difficult way...
|
9
|
+
Rails::AppLoader.send :remove_const, :EXECUTABLES
|
10
|
+
Rails::AppLoader::EXECUTABLES = %w[ bin/railsmdb ].freeze
|
11
|
+
|
12
|
+
if ARGV.first == 'setup'
|
13
|
+
Rails::Command.invoke :setup, ARGV
|
14
|
+
else
|
15
|
+
require 'rails/cli'
|
16
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mongoid'
|
4
|
+
require 'rails/command/base'
|
5
|
+
require 'rails/command/environment_argument'
|
6
|
+
|
7
|
+
module Mongoid
|
8
|
+
module Command
|
9
|
+
# The implementation of the `dbconsole` command for Railsmdb.
|
10
|
+
class DbconsoleCommand < Rails::Command::Base
|
11
|
+
include Rails::Command::EnvironmentArgument
|
12
|
+
|
13
|
+
desc 'dbconsole', 'Start a console for MongoDB using the info in config/mongoid.yml'
|
14
|
+
def perform
|
15
|
+
require_application_and_environment!
|
16
|
+
exec_mongosh_with(Rails.env || 'default')
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Invokes mongosh using the config/mongoid.yml configuration for the
|
22
|
+
# current Rails environment. If no such configuration exists, it tries
|
23
|
+
# to fall back to the `default` configuration.
|
24
|
+
#
|
25
|
+
# @param [ String ] environment the named configuration to use.
|
26
|
+
def exec_mongosh_with(environment)
|
27
|
+
puts "Launching mongosh with #{environment} configuration."
|
28
|
+
config = find_configuration_for(environment)
|
29
|
+
|
30
|
+
command = ENV['MONGOSH_CMD'] || 'mongosh'
|
31
|
+
|
32
|
+
uri = config[:uri] || "mongodb://#{config[:hosts].first}/#{config[:database]}"
|
33
|
+
|
34
|
+
exec(command, uri)
|
35
|
+
rescue Errno::ENOENT
|
36
|
+
abort "mongosh is not installed, or is not in your PATH. Please see\n" \
|
37
|
+
"https://www.mongodb.com/docs/mongodb-shell for instructions on\n" \
|
38
|
+
'downloading and installing mongosh.'
|
39
|
+
end
|
40
|
+
|
41
|
+
# Looks for a Mongoid client configuration with the given name. If no
|
42
|
+
# such configuration exists, tries to load the `default` configuration.
|
43
|
+
# If that can't be found, it will abort executation.
|
44
|
+
#
|
45
|
+
# @param [ String ] environment the name of the configuration to load.
|
46
|
+
#
|
47
|
+
# @return [ Hash ] the named configuration
|
48
|
+
def find_configuration_for(environment)
|
49
|
+
config = Mongoid.clients[environment]
|
50
|
+
return config if config
|
51
|
+
|
52
|
+
warn "There is no #{environment} configuration defined in config/mongoid.yml."
|
53
|
+
|
54
|
+
config = Mongoid.clients[:default]
|
55
|
+
unless config
|
56
|
+
abort "There is no default configuration to fall back to.\n" \
|
57
|
+
'Please define a client in config/mongoid.yml.'
|
58
|
+
end
|
59
|
+
|
60
|
+
warn 'Using default configuration instead.'
|
61
|
+
config
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/command/base'
|
4
|
+
require 'railsmdb/generators/setup/setup_generator'
|
5
|
+
|
6
|
+
module Mongoid
|
7
|
+
module Command
|
8
|
+
# The implementation of the `setup` command for Railsmdb.
|
9
|
+
class SetupCommand < Rails::Command::Base
|
10
|
+
desc 'setup', 'Install railsmdb into an existing Rails app'
|
11
|
+
def perform(*args)
|
12
|
+
# remove the first argument, which will be `setup`, and pass
|
13
|
+
# the rest through to the generator
|
14
|
+
args.shift
|
15
|
+
|
16
|
+
Railsmdb::Generators::SetupGenerator.start(args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'railsmdb/crypt_shared/listing'
|
4
|
+
require 'os'
|
5
|
+
|
6
|
+
module Railsmdb
|
7
|
+
module CryptShared
|
8
|
+
# A utility method for querying a catalog listing.
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Catalog
|
12
|
+
class << self
|
13
|
+
# Return a Catalog instance representing the current listing.
|
14
|
+
#
|
15
|
+
# @return [ Catalog ] the current listing.
|
16
|
+
def current
|
17
|
+
new(Listing.fetch)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [ Hash ] the current listing
|
22
|
+
attr_reader :listing
|
23
|
+
|
24
|
+
# Create a new Catalog instance from the giving listing.
|
25
|
+
#
|
26
|
+
# @param [ Hash ] listing the data to query
|
27
|
+
def initialize(listing)
|
28
|
+
@listing = listing
|
29
|
+
end
|
30
|
+
|
31
|
+
# Queries the listing data using the given criteria, yielding the
|
32
|
+
# corresponding download data.
|
33
|
+
#
|
34
|
+
# @example Finding all production releases for M1 macs
|
35
|
+
# catalog.downloads(
|
36
|
+
# production_release: true,
|
37
|
+
# downloads: { arch: 'arm64', target: 'macos' }
|
38
|
+
# ) do |download|
|
39
|
+
# puts download['crypt_shared']['url']
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# @param [ Hash ] criteria the criteria hash
|
43
|
+
#
|
44
|
+
# @yield [ Hash ] each download record matching the criteria
|
45
|
+
def downloads(criteria = {})
|
46
|
+
download_criteria = criteria.delete(:downloads) || {}
|
47
|
+
|
48
|
+
listing['versions'].each do |version|
|
49
|
+
next unless hash_matches?(version, criteria)
|
50
|
+
|
51
|
+
version['downloads'].each do |download|
|
52
|
+
next unless hash_matches?(download, download_criteria)
|
53
|
+
|
54
|
+
yield download
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
# Queries the listing for all downloads that match the platform
|
62
|
+
# criteria for the current host.
|
63
|
+
#
|
64
|
+
# @param [ String ] which the download entry to return
|
65
|
+
#
|
66
|
+
# @return [ Array<String, String> ] a tuple of (url, sha256) for the
|
67
|
+
# requested download.
|
68
|
+
def optimal_download_url_for_this_host(which = 'crypt_shared')
|
69
|
+
downloads(production_release: true, downloads: download_criteria) do |dl|
|
70
|
+
return [ dl[which]['url'], dl[which]['sha256'] ]
|
71
|
+
end
|
72
|
+
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the download criteria (arch/target/edition) for the current
|
77
|
+
# host.
|
78
|
+
#
|
79
|
+
# @return [ Hash ] the download criteria
|
80
|
+
def download_criteria
|
81
|
+
{
|
82
|
+
arch: platform_arch,
|
83
|
+
target: platform_target,
|
84
|
+
edition: 'enterprise'
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# @return [ String ] the host CPU specification.
|
91
|
+
def platform_arch
|
92
|
+
OS.host_cpu
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [ String ] the normalized host operating system
|
96
|
+
def platform_target
|
97
|
+
if OS.windows? || OS::Underlying.windows?
|
98
|
+
'windows'
|
99
|
+
elsif OS.mac?
|
100
|
+
'macos'
|
101
|
+
elsif OS.linux?
|
102
|
+
# this will almost certainly need tweaking
|
103
|
+
release = OS.parse_os_release
|
104
|
+
id = release[:ID]
|
105
|
+
version = release[:VERSION_ID].gsub(/[^\d]/, '')
|
106
|
+
"#{id}#{version}"
|
107
|
+
else
|
108
|
+
warn 'cannot install the crypt_shared library for this platform'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Asks if the given hash satisfies all the given criteria.
|
113
|
+
#
|
114
|
+
# @param [ Hash ] hash the hash to query
|
115
|
+
# @param [ Hash ] criteria the criteria to use for the query
|
116
|
+
#
|
117
|
+
# @return [ true | false ] whether the hash meets the criteria or not.
|
118
|
+
def hash_matches?(hash, criteria)
|
119
|
+
criteria.all? { |key, value| hash[key.to_s] == value }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'tmpdir'
|
6
|
+
|
7
|
+
module Railsmdb
|
8
|
+
module CryptShared
|
9
|
+
# A utility class for fetching the JSON list of current MongoDB
|
10
|
+
# database offerings.
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
class Listing
|
14
|
+
# Convenience method for fetching and returning the current listing.
|
15
|
+
#
|
16
|
+
# @return [ Hash ] the parsed JSON contents of the listing
|
17
|
+
def self.fetch
|
18
|
+
new.listing
|
19
|
+
end
|
20
|
+
|
21
|
+
# Downloads and parses the listing, returning the result.
|
22
|
+
#
|
23
|
+
# @return [ Hash ] the parsed JSON contents of the listing
|
24
|
+
def listing
|
25
|
+
@listing ||= fetch_listing_json
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# the URI of the current.json catalog
|
31
|
+
CURRENT_URI = 'https://downloads.mongodb.org/current.json'
|
32
|
+
|
33
|
+
# where the JSON file should be cached
|
34
|
+
CURRENT_CACHE = File.join(Dir.tmpdir, '.current.json')
|
35
|
+
|
36
|
+
# how old the cache may be before it must be fetched again
|
37
|
+
CACHE_CUTOFF = 24 * 60 * 60 # seconds in 24 hours
|
38
|
+
|
39
|
+
# Fetches and parses the current catalog file, first checking the
|
40
|
+
# cache, and then if necessary fetching from the remote server.
|
41
|
+
#
|
42
|
+
# @return [ Hash ] the parsed JSON catalog file
|
43
|
+
def fetch_listing_json
|
44
|
+
fetch_listing_json_from_cache ||
|
45
|
+
fetch_listing_json_from_uri
|
46
|
+
end
|
47
|
+
|
48
|
+
# Looks at the cache for the requested catalog file. If it doesn't
|
49
|
+
# exist, or if it is too old, this returns nil.
|
50
|
+
#
|
51
|
+
# @return [ Hash | nil ] the parsed JSON catalog file, or nil if
|
52
|
+
# it needs to be fetched from the server
|
53
|
+
def fetch_listing_json_from_cache
|
54
|
+
return nil unless File.exist?(CURRENT_CACHE)
|
55
|
+
return nil unless File.mtime(CURRENT_CACHE) >= Time.now - CACHE_CUTOFF
|
56
|
+
|
57
|
+
JSON.load_file(CURRENT_CACHE)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Fetches the requested catalog file from the server. This will
|
61
|
+
# save the fetched file to the cache.
|
62
|
+
#
|
63
|
+
# @return [ Hash ] the parsed JSON catalog file
|
64
|
+
def fetch_listing_json_from_uri
|
65
|
+
uri = URI.parse(CURRENT_URI)
|
66
|
+
File.write(CURRENT_CACHE, uri.read)
|
67
|
+
fetch_listing_json_from_cache
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module Railsmdb
|
6
|
+
# A utility class for downloading a file from a given URL.
|
7
|
+
class Downloader
|
8
|
+
# @return [ String ] the url to download from
|
9
|
+
attr_reader :url
|
10
|
+
|
11
|
+
# @return [ String ] where the file should be saved to.
|
12
|
+
attr_reader :destination
|
13
|
+
|
14
|
+
# A helper method for fetching the file in a single call.
|
15
|
+
#
|
16
|
+
# @param [ String ] url the url to fetch from
|
17
|
+
# @param [ String ] destination the location to write to
|
18
|
+
# @param [ Proc ] callback a callback block that is invoked with the
|
19
|
+
# current total number of bytes read, as each chunk is read from the
|
20
|
+
# stream.
|
21
|
+
def self.fetch(url, destination, &callback)
|
22
|
+
new(url, destination).fetch(&callback)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a new Downloader object.
|
26
|
+
#
|
27
|
+
# @param [ String ] url the url to fetch from
|
28
|
+
# @param [ String ] destination the location to write to
|
29
|
+
def initialize(url, destination)
|
30
|
+
@url = url
|
31
|
+
@destination = destination
|
32
|
+
end
|
33
|
+
|
34
|
+
# Perform the fetch, pulling from the url and writing to the destination.
|
35
|
+
def fetch
|
36
|
+
File.open(destination, 'w:BINARY') do |io|
|
37
|
+
connection.get(url) do |req|
|
38
|
+
req.options.on_data = lambda do |chunk, total, _env|
|
39
|
+
yield total if block_given?
|
40
|
+
io << chunk
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# The underlying HTTP connection used to query the file.
|
51
|
+
def connection
|
52
|
+
@connection ||= Faraday.new(url: url, ssl: { verify: false, verify_hostname: false })
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/command/behavior'
|
4
|
+
|
5
|
+
module Railsmdb
|
6
|
+
# Extensions to the Rails::Command::Behavior module
|
7
|
+
module RailsCommandBehaviorExtension
|
8
|
+
module ClassMethods # :nodoc:
|
9
|
+
def self.included(mod)
|
10
|
+
mod.alias_method :rails_lookup, :lookup
|
11
|
+
mod.alias_method :lookup, :railsmdb_lookup
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# Railsmdb's version of `Command#lookup`, which makes
|
17
|
+
# sure any `rails:` namespace is preempted by a corresponding
|
18
|
+
# `railsmdb:` namespace.
|
19
|
+
#
|
20
|
+
# @param [ Array<String> ] namespaces the list of namespaces
|
21
|
+
# to look at
|
22
|
+
def railsmdb_lookup(namespaces)
|
23
|
+
rails_lookup(preempt_rails_namespace(namespaces))
|
24
|
+
end
|
25
|
+
|
26
|
+
# If a "rails:" namespace exists in the list,
|
27
|
+
# insert a new namespace before it with "rails:"
|
28
|
+
# replaced with "mongoid:"
|
29
|
+
#
|
30
|
+
# @param [ Array<String> ] namespaces the list of namespaces
|
31
|
+
# to consider
|
32
|
+
#
|
33
|
+
# @return [ Array<String> ] the (possibly modified) list of
|
34
|
+
# namespaces.
|
35
|
+
def preempt_rails_namespace(namespaces)
|
36
|
+
new_namespaces = []
|
37
|
+
|
38
|
+
namespaces.each do |ns|
|
39
|
+
if ns.match?(/\brails:/)
|
40
|
+
new_ns = ns.sub(/\brails:/, 'mongoid:')
|
41
|
+
new_namespaces.push(new_ns)
|
42
|
+
end
|
43
|
+
|
44
|
+
new_namespaces.push(ns)
|
45
|
+
end
|
46
|
+
|
47
|
+
# we need to replace the namespaces list in-place, so that the caller
|
48
|
+
# gets the updated namespaces.
|
49
|
+
namespaces.replace(new_namespaces)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
::Rails::Command::Behavior::ClassMethods.include ClassMethods
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/command'
|
4
|
+
require 'railsmdb/ext/rails/command/behavior'
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
module Command # :nodoc:
|
8
|
+
class << self
|
9
|
+
private
|
10
|
+
|
11
|
+
# Prepends the railsmdb commands lookup path to the existing rails
|
12
|
+
# lookup paths.
|
13
|
+
def railsmdb_lookup_paths
|
14
|
+
@railsmdb_lookup_paths ||= [ 'railsmdb/commands', *rails_lookup_paths ]
|
15
|
+
end
|
16
|
+
|
17
|
+
alias rails_lookup_paths lookup_paths
|
18
|
+
alias lookup_paths railsmdb_lookup_paths
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|