active_json_schema 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cdfca17ff6cc30e98bba49122db2b8072a3bedf880486ce80574dde8e73d74ba
4
+ data.tar.gz: 6209512ebddb4a3903f1ad1762ad16a76a998ddc59a031d7a88a2aefc34ca137
5
+ SHA512:
6
+ metadata.gz: f3643c51ef453e218e320617d6521548903734e3c47efb0c22a2bd0fe2b167f07fe85356ee1c6fbe797e6d19cc2a13c38d7bae9675206d86dd769ccdfbfdc479
7
+ data.tar.gz: fb09e2a10dd66bd4431a2281c4637f8a552be34620726894b06c76a98be125519f058a64a20b4b1b845bf468eea89c8ebba52a60bea2d6a2ed46246e5346d0d1
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/standardrb/standard
3
+ ruby_version: 3.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ ## [Unreleased]
2
+
3
+ ### Added
4
+ - Comprehensive README with installation instructions, usage examples, and customization options
5
+ - Filled in gemspec with summary, description, and metadata
6
+ - Support for generating JSON Schema for ActiveRecord models
7
+ - Customizable schema generation with options for specific attributes and associations
8
+ - Ability to include nested associations in schema generation
9
+
10
+ ## [0.1.0] - 2024-10-08
11
+
12
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Kaleb Lape
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,134 @@
1
+ # ActiveJsonSchema
2
+
3
+ ActiveJsonSchema is a Ruby gem that extends ActiveRecord models to generate JSON Schema representations. It provides an easy way to create JSON Schema definitions for your ActiveRecord models, including support for associations.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem "active_json_schema"
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install active_json_schema
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Basic Usage
28
+
29
+ To use ActiveJsonSchema in your ActiveRecord models, include the `ActiveJsonSchema::ToJsonSchema` module:
30
+
31
+ ```ruby
32
+ class User < ActiveRecord::Base
33
+ include ActiveJsonSchema::ToJsonSchema
34
+
35
+ has_many :posts
36
+ end
37
+
38
+ class Post < ActiveRecord::Base
39
+ include ActiveJsonSchema::ToJsonSchema
40
+
41
+ belongs_to :user
42
+ end
43
+ ```
44
+
45
+ Now you can generate JSON Schema for your models:
46
+
47
+ ```ruby
48
+ user_schema = User.to_json_schema
49
+ puts user_schema
50
+ ```
51
+
52
+ This will output a JSON Schema representation of the User model, including all its attributes.
53
+
54
+ ### Customizing Schema Generation
55
+
56
+ You can customize the schema generation by passing options to the `to_json_schema` method:
57
+
58
+ ```ruby
59
+ # Generate schema for specific attributes only
60
+ user_schema = User.to_json_schema(only: %w[name email])
61
+
62
+ # Include associations in the schema
63
+ user_schema = User.to_json_schema(associations: %w[posts])
64
+
65
+ # Customize association options
66
+ user_schema = User.to_json_schema(associations: { posts: { only: %w[title content] } })
67
+
68
+ # Allow additional properties
69
+ user_schema = User.to_json_schema(additional_properties: true)
70
+ ```
71
+
72
+ ### Working with Associations
73
+
74
+ ActiveJsonSchema supports generating schemas for associated models:
75
+
76
+ ```ruby
77
+ class User < ActiveRecord::Base
78
+ include ActiveJsonSchema::ToJsonSchema
79
+
80
+ has_many :posts
81
+ end
82
+
83
+ user_schema = User.to_json_schema(associations: %w[posts])
84
+ ```
85
+
86
+ This will include a `posts_attributes` property in the User schema, referencing the Post schema definition.
87
+
88
+ ### Overriding Default Behavior
89
+
90
+ You can override the default `to_json_schema` method in your models for more control:
91
+
92
+ ```ruby
93
+ class Post < ActiveRecord::Base
94
+ include ActiveJsonSchema::ToJsonSchema
95
+
96
+ def self.to_json_schema(only: %w[title content], **)
97
+ super
98
+ end
99
+ end
100
+ ```
101
+
102
+ This example will always include only the 'title' and 'content' attributes in the Post schema unless specified otherwise.
103
+
104
+ ## Examples
105
+
106
+ Here are some more examples to illustrate the usage:
107
+
108
+ ```ruby
109
+ # Generate schema for User model with all attributes
110
+ User.to_json_schema
111
+
112
+ # Generate schema for User model with specific attributes and associations
113
+ User.to_json_schema(only: %w[name email], associations: %w[posts])
114
+
115
+ # Generate schema for Post model with customized association
116
+ Post.to_json_schema(associations: { user: { only: %w[name] } })
117
+
118
+ # Generate schema with nested associations
119
+ User.to_json_schema(associations: { posts: { associations: %w[comments] } })
120
+ ```
121
+
122
+ ## Development
123
+
124
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
125
+
126
+ To install this gem onto your local machine, run `bundle exec rake install`.
127
+
128
+ ## Contributing
129
+
130
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pingortle/active_json_schema. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](CODE_OF_CONDUCT.md).
131
+
132
+ ## License
133
+
134
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "standard/rake"
9
+
10
+ task default: %i[test standard]
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ConvertsToJsonSchemaWithRefs
4
+ class UnsupportedAssociationType < StandardError; end
5
+
6
+ def self.generate(model_class, only: nil, associations: {}, additional_properties: false)
7
+ new(model_class, only: only, associations: associations, additional_properties: additional_properties).generate
8
+ end
9
+
10
+ def initialize(model_class, only: nil, associations: [], additional_properties: false)
11
+ @model_class = model_class
12
+ @only = only
13
+ @associations = associations.is_a?(Array) ? associations.to_h { |a| [a, {}] } : associations
14
+ @additional_properties = additional_properties
15
+ @definitions = {}
16
+ end
17
+
18
+ def generate
19
+ schema = {
20
+ type: "object",
21
+ properties: properties_for(@model_class, @only, @associations),
22
+ required: required_properties(@model_class, @only),
23
+ additionalProperties: @additional_properties
24
+ }
25
+ schema[:definitions] = @definitions unless @definitions.empty?
26
+ schema
27
+ end
28
+
29
+ private
30
+
31
+ def properties_for(model_class, only, associations)
32
+ puts "properties_for(...)"
33
+ puts "model_class: #{model_class}"
34
+ puts "only: #{only}"
35
+ puts "associations: #{associations}"
36
+ puts
37
+
38
+ properties = {}
39
+
40
+ model_class.columns_hash.each do |column_name, column_info|
41
+ next unless only.nil? || only.include?(column_name)
42
+
43
+ properties[column_name] = column_to_json_property(column_info)
44
+ end
45
+
46
+ puts "associations.each do |association_name, options|"
47
+ associations.each do |association_name, options|
48
+ puts "association_name: #{association_name}"
49
+ association = model_class.reflect_on_association(association_name)
50
+ puts "association: #{association}"
51
+ next unless association
52
+
53
+ definition_name = association.klass.name.underscore
54
+ if options.empty?
55
+ klass = association.klass
56
+ unless klass.ancestors.include?(ActiveJsonSchema::ToJsonSchema)
57
+ raise UnsupportedAssociationType.new("Please include ActiveJsonSchema::ToJsonSchema in #{klass} or specify association options.")
58
+ end
59
+
60
+ nested_schema = klass.to_json_schema
61
+ @definitions.merge!(nested_schema[:definitions] || {})
62
+ @definitions[definition_name] ||= nested_schema.except(:definitions)
63
+ else
64
+ @definitions[definition_name] ||= generate_definition(association.klass, options)
65
+ end
66
+
67
+ property_name = "#{association_name}_attributes"
68
+ properties[property_name] = association_to_json_property(association, definition_name)
69
+ end
70
+
71
+ properties
72
+ end
73
+
74
+ def generate_definition(model_class, options)
75
+ puts "generate_definition(...)"
76
+ puts "model_class: #{model_class}"
77
+ puts "options: #{options}"
78
+ only = options[:only]
79
+ nested_associations = options[:associations] || {}
80
+
81
+ {
82
+ type: "object",
83
+ properties: properties_for(model_class, only, nested_associations),
84
+ required: required_properties(model_class, only)
85
+ }
86
+ end
87
+
88
+ def required_properties(model_class, only)
89
+ model_class.columns_hash.select do |column_name, column_info|
90
+ (only.nil? || only.include?(column_name)) && !column_info.null
91
+ end.keys
92
+ end
93
+
94
+ def column_to_json_property(column_info)
95
+ property = {type: sql_type_to_json_type(column_info.type)}
96
+
97
+ case column_info.type
98
+ when :string, :text
99
+ property[:maxLength] = column_info.limit if column_info.limit
100
+ when :integer, :bigint
101
+ property[:minimum] = 0 if column_info.sql_type.include?("unsigned")
102
+ when :decimal
103
+ property[:multipleOf] = 10**-column_info.scale if column_info.scale
104
+ end
105
+
106
+ property
107
+ end
108
+
109
+ def association_to_json_property(association, definition_name)
110
+ case association.macro
111
+ when :has_many, :has_and_belongs_to_many
112
+ {
113
+ type: "array",
114
+ items: {"$ref": "#/definitions/#{definition_name}"}
115
+ }
116
+ when :belongs_to, :has_one
117
+ {"$ref": "#/definitions/#{definition_name}"}
118
+ else
119
+ raise "Unsupported association type: #{association.macro}"
120
+ end
121
+ end
122
+
123
+ def sql_type_to_json_type(sql_type)
124
+ case sql_type
125
+ when :string, :text
126
+ "string"
127
+ when :integer, :bigint
128
+ "integer"
129
+ when :float, :decimal
130
+ "number"
131
+ when :boolean
132
+ "boolean"
133
+ when :date, :datetime, :time
134
+ "string"
135
+ else
136
+ "string"
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJsonSchema
4
+ module ToJsonSchema
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def to_json_schema(only: nil, associations: {}, additional_properties: false)
11
+ ConvertsToJsonSchemaWithRefs.generate(self, only: only, associations: associations, additional_properties: additional_properties)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJsonSchema
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "active_json_schema/version"
4
+
5
+ module ActiveJsonSchema
6
+ class Error < StandardError; end
7
+ require_relative "active_json_schema/converts_to_json_schema_with_refs"
8
+ require_relative "active_json_schema/to_json_schema"
9
+ end
@@ -0,0 +1,4 @@
1
+ module ActiveJsonSchema
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_json_schema
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kaleb Lape
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-10-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: ActiveJsonSchema extends ActiveRecord models to generate JSON Schema
14
+ representations, including support for associations.
15
+ email:
16
+ - kaleb.lape@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".standard.yml"
22
+ - CHANGELOG.md
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - lib/active_json_schema.rb
27
+ - lib/active_json_schema/converts_to_json_schema_with_refs.rb
28
+ - lib/active_json_schema/to_json_schema.rb
29
+ - lib/active_json_schema/version.rb
30
+ - sig/active_json_schema.rbs
31
+ homepage: https://github.com/RailsQuest/active_json_schema
32
+ licenses:
33
+ - MIT
34
+ metadata:
35
+ allowed_push_host: https://rubygems.org
36
+ homepage_uri: https://github.com/RailsQuest/active_json_schema
37
+ source_code_uri: https://github.com/RailsQuest/active_json_schema
38
+ changelog_uri: https://github.com/RailsQuest/active_json_schema/blob/main/CHANGELOG.md
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.5.20
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Generate JSON Schema representations for ActiveRecord models
58
+ test_files: []