active_json_schema 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []