esquema 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +109 -0
- data/Rakefile +12 -0
- data/esquema.gemspec +38 -0
- data/lib/esquema/builder.rb +110 -0
- data/lib/esquema/configuration.rb +33 -0
- data/lib/esquema/model.rb +27 -0
- data/lib/esquema/property.rb +79 -0
- data/lib/esquema/schema_enhancer.rb +65 -0
- data/lib/esquema/type_caster.rb +41 -0
- data/lib/esquema/version.rb +5 -0
- data/lib/esquema.rb +8 -0
- data/lib/generators/esquema/install/install_generator.rb +15 -0
- data/lib/generators/esquema/install/templates/esquema_initializer.rb +22 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 558e39a6744da50805af73033bd229dcb5767ccd6eaf0709a24fbebb451f914a
|
4
|
+
data.tar.gz: a7579351072e9c130d815af4347280a82679b3e1160473b146458dc1e0367b24
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: daafedad9677ee070eec3b955e20fa3bdda4e6b58319672f17eb08cbafbf4c3074a1c9f4d759569c10e48d6d2165d7bf1a3720983babf369e88f2238b85d89d2
|
7
|
+
data.tar.gz: 732723cf1c653139c8dc255d91fc73eb792f583e2d0a839088a23af4c521a73301aa9ac99f875696a72cd6fe436e4842f36bd6783e7e28ebc6d4187bde4d00c6
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
|
4
|
+
Style/StringLiterals:
|
5
|
+
Enabled: true
|
6
|
+
EnforcedStyle: double_quotes
|
7
|
+
|
8
|
+
Style/StringLiteralsInInterpolation:
|
9
|
+
Enabled: true
|
10
|
+
EnforcedStyle: double_quotes
|
11
|
+
|
12
|
+
Layout/LineLength:
|
13
|
+
Max: 120
|
14
|
+
|
15
|
+
Metrics/BlockLength:
|
16
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.0
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Sergio Bayona
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Esquema
|
2
|
+
|
3
|
+
Esquema is a Ruby library for JSON Schema generation from ActiveRecord models.
|
4
|
+
|
5
|
+
Esquema was designed with the following assumptions:
|
6
|
+
|
7
|
+
- An ActiveRecord model represents a JSON object.
|
8
|
+
- The JSON object properties are a representation of the model's attributes.
|
9
|
+
- The JSON Schema property types are inferred from the model's attribute types.
|
10
|
+
- The model associations (has_many, belongs_to, etc.) are represented as subschemas in the JSON Schema.
|
11
|
+
- You can customize the generated schema by using the configuration file or the `enhance_schema` method.
|
12
|
+
|
13
|
+
Example Use:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
class User < ApplicationRecord
|
17
|
+
include Esquema::Model
|
18
|
+
|
19
|
+
# Assuming the User db table has the following columns:
|
20
|
+
# column :name, :string
|
21
|
+
# column :email, :string
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Calling `User.json_schema` will return the JSON Schema for the User model:
|
28
|
+
|
29
|
+
```json
|
30
|
+
{
|
31
|
+
"title": "User model",
|
32
|
+
"type": "object",
|
33
|
+
"properties": {
|
34
|
+
"id": {
|
35
|
+
"type": "integer"
|
36
|
+
},
|
37
|
+
"name": {
|
38
|
+
"type": "string"
|
39
|
+
},
|
40
|
+
"email": {
|
41
|
+
"type": "string"
|
42
|
+
}
|
43
|
+
},
|
44
|
+
"required:": [
|
45
|
+
"name",
|
46
|
+
"email"
|
47
|
+
]
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
## Installation
|
52
|
+
|
53
|
+
Install the gem and add to the application's Gemfile by executing:
|
54
|
+
|
55
|
+
$ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
56
|
+
|
57
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
58
|
+
|
59
|
+
$ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
60
|
+
|
61
|
+
|
62
|
+
Execute the following command to install the gem and generate the configuration file:
|
63
|
+
|
64
|
+
```bash
|
65
|
+
rails generate esquema:install
|
66
|
+
```
|
67
|
+
|
68
|
+
This will generate a configuration file at:
|
69
|
+
|
70
|
+
<rails_app>/config/initializer/esquema.rb
|
71
|
+
|
72
|
+
|
73
|
+
## Usage
|
74
|
+
|
75
|
+
Simply include the `Esquema::Model` module in your ActiveRecord model and call the `json_schema` method to generate the JSON Schema for the model.
|
76
|
+
|
77
|
+
There are multiple ways to customize the generated schema:
|
78
|
+
- You can exclude columns, foreign keys, and associations from the schema. See the <rails_project>/config/initializer/esquema.rb configuration for more details.
|
79
|
+
- For more complex customizations, you can use the `enhance_schema` method to modify the schema directly on the AR model. Here is an example:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
class User < ApplicationRecord
|
83
|
+
include Esquema::Model
|
84
|
+
|
85
|
+
enhance_schema do
|
86
|
+
model_description "A user of the system"
|
87
|
+
property :name, description: "The user's name", title: "Full Name"
|
88
|
+
property :group, enum: [1, 2, 3], default: 1, description: "The user's group"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
In the example above, the `enhance_schema` method is used to add a description to the model, change the title of the `name` property and add a description. It adds an enum, default value and a description to the `group` property.
|
94
|
+
|
95
|
+
|
96
|
+
## Development
|
97
|
+
|
98
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
99
|
+
|
100
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
101
|
+
|
102
|
+
## Contributing
|
103
|
+
|
104
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sergiobayona/esquema.
|
105
|
+
|
106
|
+
## License
|
107
|
+
|
108
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
109
|
+
|
data/Rakefile
ADDED
data/esquema.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/esquema/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "esquema"
|
7
|
+
spec.version = Esquema::VERSION
|
8
|
+
spec.authors = ["Sergio Bayona"]
|
9
|
+
spec.email = ["bayona.sergio@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Generate json-schema from ActiveRecord models."
|
12
|
+
spec.description = "Generate json-schema from ActiveRecord models."
|
13
|
+
spec.homepage = "https://esquema.co"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 2.6.0"
|
16
|
+
|
17
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
+
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
+
spec.metadata["source_code_uri"] = "https://github.com/sergiobayona/esquema"
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/sergiobayona/esquema/blob/main/CHANGELOG.md"
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(File.expand_path(f) == __FILE__) ||
|
28
|
+
f.start_with?(*%w[bin/ spec/ .git .github Gemfile])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
spec.bindir = "exe"
|
32
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
|
35
|
+
spec.add_dependency "rails", "~> 7.0"
|
36
|
+
spec.add_development_dependency "pry-byebug", ">= 3.10.1"
|
37
|
+
spec.add_development_dependency "rake", "~> 13.1"
|
38
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "property"
|
4
|
+
|
5
|
+
module Esquema
|
6
|
+
class Builder
|
7
|
+
attr_reader :model, :required_properties
|
8
|
+
|
9
|
+
def initialize(model)
|
10
|
+
raise ArgumentError, "Class is not an ActiveRecord model" unless model.ancestors.include? ActiveRecord::Base
|
11
|
+
|
12
|
+
@model = model
|
13
|
+
@properties = {}
|
14
|
+
@required_properties = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_schema
|
18
|
+
schema = {
|
19
|
+
title: build_title,
|
20
|
+
description: build_description,
|
21
|
+
type: "object",
|
22
|
+
properties: build_properties,
|
23
|
+
required: required_properties
|
24
|
+
}
|
25
|
+
|
26
|
+
schema.compact
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_properties
|
30
|
+
add_properties_from_columns
|
31
|
+
add_properties_from_has_many_associations
|
32
|
+
add_properties_from_has_one_associations
|
33
|
+
|
34
|
+
@properties
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_properties_from_columns
|
38
|
+
columns.each do |property|
|
39
|
+
next if property.name.end_with?("_id") && config.exclude_foreign_keys?
|
40
|
+
|
41
|
+
required_properties << property.name
|
42
|
+
options = enhancement_for(property.name)
|
43
|
+
@properties[property.name] ||= Property.new(property, options)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_properties_from_has_many_associations
|
48
|
+
has_many_associations.each do |association|
|
49
|
+
next if config.exclude_associations?
|
50
|
+
|
51
|
+
@properties[association.name] ||= Property.new(association)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_properties_from_has_one_associations
|
56
|
+
has_one_associations.each do |association|
|
57
|
+
next if config.exclude_associations?
|
58
|
+
|
59
|
+
klass = association.klass.name.constantize
|
60
|
+
@properties[association.name] ||= self.class.new(klass).build_schema
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def columns
|
65
|
+
model.columns.reject { |c| excluded_column?(c.name) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def enhancement_for(property_name)
|
69
|
+
schema_enhancements&.dig(:properties, property_name.to_sym) || {}
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_many_associations
|
73
|
+
model.reflect_on_all_associations(:has_many)
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_one_associations
|
77
|
+
model.reflect_on_all_associations(:has_one)
|
78
|
+
end
|
79
|
+
|
80
|
+
def excluded_column?(column_name)
|
81
|
+
raise ArgumentError, "Column name must be a string" unless column_name.is_a? String
|
82
|
+
|
83
|
+
config.excluded_columns.include?(column_name.to_sym)
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_title
|
87
|
+
schema_enhancements[:model_title].presence || model.name.demodulize.humanize
|
88
|
+
end
|
89
|
+
|
90
|
+
def build_description
|
91
|
+
schema_enhancements[:model_description].presence
|
92
|
+
end
|
93
|
+
|
94
|
+
def name
|
95
|
+
model.name
|
96
|
+
end
|
97
|
+
|
98
|
+
def schema_enhancements
|
99
|
+
if model.respond_to?(:schema_enhancements)
|
100
|
+
model.schema_enhancements
|
101
|
+
else
|
102
|
+
{}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def config
|
107
|
+
Esquema.configuration
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esquema
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :exclude_associations, :exclude_foreign_keys, :excluded_columns
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
reset
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset
|
12
|
+
@exclude_associations = false
|
13
|
+
@exclude_foreign_keys = true
|
14
|
+
@excluded_columns = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def exclude_foreign_keys?
|
18
|
+
exclude_foreign_keys
|
19
|
+
end
|
20
|
+
|
21
|
+
def exclude_associations?
|
22
|
+
exclude_associations
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.configuration
|
27
|
+
@configuration ||= Configuration.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.configure
|
31
|
+
yield(configuration)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require_relative "builder"
|
5
|
+
require_relative "schema_enhancer"
|
6
|
+
|
7
|
+
module Esquema
|
8
|
+
module Model
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
def self.json_schema
|
13
|
+
Esquema::Builder.new(self).build_schema.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.enhance_schema(&block)
|
17
|
+
schema_enhancements
|
18
|
+
enhancer = SchemaEnhancer.new(self, @schema_enhancements)
|
19
|
+
enhancer.instance_eval(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.schema_enhancements
|
23
|
+
@schema_enhancements ||= {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "type_caster"
|
4
|
+
module Esquema
|
5
|
+
class Property
|
6
|
+
DB_TO_JSON_TYPE_MAPPINGS = {
|
7
|
+
date: "date",
|
8
|
+
datetime: "date-time",
|
9
|
+
time: "time",
|
10
|
+
string: "string",
|
11
|
+
text: "string",
|
12
|
+
integer: "integer",
|
13
|
+
float: "number",
|
14
|
+
decimal: "number",
|
15
|
+
boolean: "boolean",
|
16
|
+
array: "array",
|
17
|
+
object: "object"
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
ATTRS = %i[type default title description item_type items enum].freeze
|
21
|
+
attr_accessor(*ATTRS)
|
22
|
+
attr_reader :property, :options
|
23
|
+
|
24
|
+
def initialize(property, options = {})
|
25
|
+
raise ArgumentError, "property must have a name" unless property.respond_to?(:name)
|
26
|
+
|
27
|
+
@property = property
|
28
|
+
@options = options
|
29
|
+
end
|
30
|
+
|
31
|
+
def as_json
|
32
|
+
ATTRS.each_with_object({}) do |property, hash|
|
33
|
+
value = send("build_#{property}")
|
34
|
+
next if value.nil? || (value.is_a?(String) && value.empty?)
|
35
|
+
|
36
|
+
hash[property] = value
|
37
|
+
end.compact
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_title
|
41
|
+
options[:title].presence || property.name.to_s.humanize
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_default
|
45
|
+
return unless property.respond_to?(:default)
|
46
|
+
|
47
|
+
default_value = property.default || options[:default].presence
|
48
|
+
|
49
|
+
@default = TypeCaster.cast(property.type, default_value) unless default_value.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
def build_type
|
53
|
+
return DB_TO_JSON_TYPE_MAPPINGS[:array] if property.try(:collection?)
|
54
|
+
|
55
|
+
@type = DB_TO_JSON_TYPE_MAPPINGS[property.type]
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_item_type
|
59
|
+
return unless property.respond_to?(:item_type)
|
60
|
+
|
61
|
+
@item_type = property.item_type if property.type == :array
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_description
|
65
|
+
options[:description]
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_items
|
69
|
+
return unless property.try(:collection?)
|
70
|
+
|
71
|
+
class_name = property.class_name.constantize
|
72
|
+
@items = Builder.new(class_name).build_schema
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_enum
|
76
|
+
options[:enum]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "date"
|
2
|
+
require "bigdecimal"
|
3
|
+
|
4
|
+
module Esquema
|
5
|
+
class SchemaEnhancer
|
6
|
+
VALID_OPTIONS = %i[title description maxLength minLength pattern maxItems minItems uniqueItems
|
7
|
+
maxProperties minProperties properties additionalProperties dependencies
|
8
|
+
enum format multipleOf maximum exclusiveMaximum minimum exclusiveMinimum
|
9
|
+
const allOf anyOf oneOf not default].freeze
|
10
|
+
|
11
|
+
TYPE_MAPPINGS = {
|
12
|
+
date: Date,
|
13
|
+
datetime: DateTime,
|
14
|
+
time: Time,
|
15
|
+
string: String,
|
16
|
+
text: String,
|
17
|
+
integer: Integer,
|
18
|
+
float: Float,
|
19
|
+
decimal: BigDecimal,
|
20
|
+
boolean: [TrueClass, FalseClass],
|
21
|
+
array: Array,
|
22
|
+
object: Object
|
23
|
+
}.freeze
|
24
|
+
attr_reader :model
|
25
|
+
|
26
|
+
def initialize(model, schema_enhancements)
|
27
|
+
@schema_enhancements = schema_enhancements
|
28
|
+
@model = model
|
29
|
+
end
|
30
|
+
|
31
|
+
def model_description(description)
|
32
|
+
@schema_enhancements[:model_description] = description
|
33
|
+
end
|
34
|
+
|
35
|
+
def model_title(title)
|
36
|
+
@schema_enhancements[:model_title] = title
|
37
|
+
end
|
38
|
+
|
39
|
+
def property(name, options = {})
|
40
|
+
db_type = model.type_for_attribute(name).type
|
41
|
+
klass_type = Array(TYPE_MAPPINGS[db_type])
|
42
|
+
|
43
|
+
validate_default_value(options[:default], klass_type, db_type)
|
44
|
+
validate_enum_values(options[:enum], klass_type, db_type)
|
45
|
+
|
46
|
+
options.assert_valid_keys(VALID_OPTIONS)
|
47
|
+
@schema_enhancements[:properties] ||= {}
|
48
|
+
@schema_enhancements[:properties][name] = options
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def validate_default_value(default_value, klass_type, db_type)
|
54
|
+
return unless default_value.present? && !klass_type.include?(default_value.class)
|
55
|
+
|
56
|
+
raise ArgumentError, "Default value must be of type #{db_type}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate_enum_values(enum_values, klass_type, db_type)
|
60
|
+
return unless enum_values.present? && !enum_values.all? { |value| klass_type.include?(value.class) }
|
61
|
+
|
62
|
+
raise ArgumentError, "Enum values must be of type #{db_type}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Esquema
|
4
|
+
module TypeCaster
|
5
|
+
def self.cast(type, value) # rubocop:disable Metrics/MethodLength
|
6
|
+
case type
|
7
|
+
when :string, :text
|
8
|
+
value.to_s
|
9
|
+
when :integer
|
10
|
+
begin
|
11
|
+
Integer(value)
|
12
|
+
rescue StandardError
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
when :float
|
16
|
+
begin
|
17
|
+
Float(value)
|
18
|
+
rescue StandardError
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
when :boolean
|
22
|
+
case value
|
23
|
+
when true, "true", "1", 1
|
24
|
+
true
|
25
|
+
when false, "false", "0", 0
|
26
|
+
false
|
27
|
+
else
|
28
|
+
nil # or handle as desired
|
29
|
+
end
|
30
|
+
when :array
|
31
|
+
Array(value)
|
32
|
+
when :object
|
33
|
+
value.is_a?(Hash) ? value : nil # or convert as desired
|
34
|
+
when :null
|
35
|
+
nil if value.nil?
|
36
|
+
else
|
37
|
+
raise ArgumentError, "Unsupported type: #{type}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/esquema.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module Esquema
|
6
|
+
module Generators
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
9
|
+
|
10
|
+
def copy_initializer_file
|
11
|
+
template "esquema_initializer.rb", "config/initializers/esquema.rb"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "esquema"
|
4
|
+
|
5
|
+
Esquema.configure do |config|
|
6
|
+
# Exclude Associations:
|
7
|
+
# Exclude associated models from the json-schema output.
|
8
|
+
# By default, all associated models are included.
|
9
|
+
config.exclude_associations = false
|
10
|
+
|
11
|
+
# Exclude Foreign Keys:
|
12
|
+
# Specify whether or not to exclude foreign keys from the json-schema output.
|
13
|
+
# By default, foreign keys are excluded.
|
14
|
+
# foreign keys are loosely defined as columns that end with "_id".
|
15
|
+
config.exclude_foreign_keys = true
|
16
|
+
|
17
|
+
# Excluded Columns:
|
18
|
+
# Specify the columns that you want to exclude from the json-schema output.
|
19
|
+
# These are columns common to all models, such as id, created_at, updated_at, etc.
|
20
|
+
# It's okay if not all models have these columns, they will be ignored.
|
21
|
+
config.excluded_columns = %i[id created_at updated_at deleted_at]
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: esquema
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergio Bayona
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.10.1
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.10.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.1'
|
55
|
+
description: Generate json-schema from ActiveRecord models.
|
56
|
+
email:
|
57
|
+
- bayona.sergio@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".rspec"
|
63
|
+
- ".rubocop.yml"
|
64
|
+
- ".ruby-version"
|
65
|
+
- CHANGELOG.md
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- esquema.gemspec
|
70
|
+
- lib/esquema.rb
|
71
|
+
- lib/esquema/builder.rb
|
72
|
+
- lib/esquema/configuration.rb
|
73
|
+
- lib/esquema/model.rb
|
74
|
+
- lib/esquema/property.rb
|
75
|
+
- lib/esquema/schema_enhancer.rb
|
76
|
+
- lib/esquema/type_caster.rb
|
77
|
+
- lib/esquema/version.rb
|
78
|
+
- lib/generators/esquema/install/install_generator.rb
|
79
|
+
- lib/generators/esquema/install/templates/esquema_initializer.rb
|
80
|
+
homepage: https://esquema.co
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata:
|
84
|
+
allowed_push_host: https://rubygems.org
|
85
|
+
homepage_uri: https://esquema.co
|
86
|
+
source_code_uri: https://github.com/sergiobayona/esquema
|
87
|
+
changelog_uri: https://github.com/sergiobayona/esquema/blob/main/CHANGELOG.md
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.6.0
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubygems_version: 3.5.3
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Generate json-schema from ActiveRecord models.
|
107
|
+
test_files: []
|