railsmdb 1.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|