Skip to content

Commit 1192640

Browse files
authored
Improve README and add documentation structure (#91)
## Summary - Improve README with comprehensive documentation explaining what the gem does - Add Related Projects and Compatibility sections - Add AGENTS.md for AI agent instructions - Create docs/ folder with progressive disclosure documentation ## Changes **README.md:** - Clear explanation of what the gem does and example output - Related Projects section linking to grape ecosystem - Compatibility table with version requirements - Usage examples (basic, custom descriptions, references) - Simplified Development/Contributing sections with links to docs **AGENTS.md:** - Minimal root file with essential commands and constraints - Links to detailed documentation **docs/:** - `architecture.md` - Component overview and data flow - `contributing.md` - PR requirements, CHANGELOG format - `documentation-options.md` - Full options table with examples - `testing.md` - Test patterns, shared contexts, issue specs Fixes #58
1 parent f5a0771 commit 1192640

7 files changed

Lines changed: 407 additions & 7 deletions

File tree

AGENTS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# grape-swagger-entity
2+
3+
Adapter for grape-swagger that parses Grape::Entity classes into OpenAPI schema definitions.
4+
5+
## Quick Reference
6+
7+
```bash
8+
bundle install # Install dependencies
9+
bundle exec rspec # Run tests
10+
bundle exec rubocop # Run linter
11+
bundle exec rubocop -a # Auto-fix linter issues
12+
```
13+
14+
## Key Constraints
15+
16+
- Ruby >= 3.0
17+
- All files must start with `# frozen_string_literal: true`
18+
- CHANGELOG.md entry required for every PR (danger enforces this)
19+
20+
## Documentation
21+
22+
- [Testing Patterns](docs/testing.md)
23+
- [Contributing Guidelines](docs/contributing.md)
24+
- [Architecture Overview](docs/architecture.md)

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#### Features
44

55
* Your contribution here.
6+
* [#91](https://github.com/ruby-grape/grape-swagger-entity/pull/91): Improve README and add documentation structure - [@numbata](https://github.com/numbata).
67

78
#### Fixes
89

README.md

Lines changed: 102 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,64 @@
66
## Table of Contents
77

88
- [What is grape-swagger-entity?](#what-is-grape-swagger-entity)
9+
- [What it does](#what-it-does)
10+
- [Example Output](#example-output)
11+
- [Related Projects](#related-projects)
12+
- [Compatibility](#compatibility)
913
- [Installation](#installation)
14+
- [Usage](#usage)
15+
- [Basic Entity](#basic-entity)
16+
- [Custom Model Description](#custom-model-description)
17+
- [Entity References](#entity-references)
18+
- [Documentation Options](#documentation-options)
1019
- [Development](#development)
1120
- [Contributing](#contributing)
1221
- [License](#license)
1322

14-
1523
## What is grape-swagger-entity?
1624

17-
A simple grape-swagger adapter to allow parse representers as response model
25+
This gem provides an adapter for [grape-swagger](https://github.com/ruby-grape/grape-swagger) that allows parsing [grape-entity](https://github.com/ruby-grape/grape-entity) classes to generate OpenAPI/Swagger model definitions automatically.
26+
27+
### What it does
28+
29+
- Generates `definitions` in your Swagger JSON from Grape::Entity exposures
30+
- Maps entity properties to OpenAPI schema properties with types and descriptions
31+
- Handles nested entities and entity references via `$ref`
32+
- Supports arrays, required fields, and documentation options
33+
34+
### Example Output
35+
36+
```json
37+
{
38+
"definitions": {
39+
"User": {
40+
"type": "object",
41+
"description": "User model",
42+
"properties": {
43+
"id": { "type": "integer", "description": "User ID" },
44+
"name": { "type": "string", "description": "Full name" }
45+
},
46+
"required": ["id", "name"]
47+
}
48+
}
49+
}
50+
```
51+
52+
## Related Projects
53+
54+
- [Grape](https://github.com/ruby-grape/grape)
55+
- [Grape Entity](https://github.com/ruby-grape/grape-entity)
56+
- [Grape Swagger](https://github.com/ruby-grape/grape-swagger)
57+
- [Grape Swagger Representable](https://github.com/ruby-grape/grape-swagger-representable)
58+
59+
## Compatibility
60+
61+
This gem is tested with the following versions:
62+
63+
| grape-swagger-entity | grape-swagger | grape-entity | grape |
64+
|---------------------|---------------|--------------|---------|
65+
| 0.7.x | >= 2.0.0 | >= 1.0.0 | >= 1.3 |
66+
| 0.6.x | >= 1.2.0 | >= 0.6.0 | >= 1.3 |
1867

1968
## Installation
2069

@@ -32,17 +81,63 @@ Or install it yourself as:
3281

3382
$ gem install grape-swagger-entity
3483

35-
## Development
84+
## Usage
85+
86+
### Basic Entity
87+
88+
Define your entities with `documentation` options to generate OpenAPI schema properties:
89+
90+
```ruby
91+
class UserEntity < Grape::Entity
92+
expose :id, documentation: { type: Integer, desc: 'User ID' }
93+
expose :name, documentation: { type: String, desc: 'Full name' }
94+
expose :email, documentation: { type: String, desc: 'Email address' }
95+
end
96+
```
97+
98+
### Custom Model Description
3699

37-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rspec` to run the tests. You can also run `bin/pry` for an interactive prompt that will allow you to experiment.
100+
Override the default "{ModelName} model" description by defining a `self.documentation` method. This feature is handled by [grape-swagger](https://github.com/ruby-grape/grape-swagger) (requires grape-swagger >= 2.2.0):
38101

39-
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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
102+
```ruby
103+
class UserEntity < Grape::Entity
104+
def self.documentation
105+
{ desc: 'Represents a user account with profile information' }
106+
end
107+
108+
expose :id, documentation: { type: Integer, desc: 'User ID' }
109+
expose :name, documentation: { type: String, desc: 'Full name' }
110+
end
111+
```
112+
113+
### Entity References
114+
115+
Use `using:` to reference other entities and `is_array:` for collections:
116+
117+
```ruby
118+
class OrderEntity < Grape::Entity
119+
expose :id, documentation: { type: Integer, desc: 'Order ID' }
120+
expose :user, using: UserEntity,
121+
documentation: { desc: 'The customer who placed this order' }
122+
expose :items, using: ItemEntity,
123+
documentation: { desc: 'Line items', is_array: true }
124+
end
125+
```
126+
127+
### Documentation Options
128+
129+
Common options: `type`, `desc`, `required`, `is_array`, `values`, `example`.
130+
131+
See [full documentation options](docs/documentation-options.md) for all available options including validation constraints.
132+
133+
## Development
134+
135+
See [testing documentation](docs/testing.md) for development setup and running tests.
40136

41137
## Contributing
42138

43-
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby-grape/grape-swagger-entity.
139+
See [contributing guidelines](docs/contributing.md).
44140

45141
## License
46142

47143
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
48-

docs/architecture.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Architecture Overview
2+
3+
## Purpose
4+
5+
This gem registers a model parser with grape-swagger that converts `Grape::Entity` classes into OpenAPI schema definitions.
6+
7+
## Core Components
8+
9+
```
10+
lib/grape-swagger/entity/
11+
├── parser.rb # Main parser - converts Entity to OpenAPI schema
12+
├── attribute_parser.rb # Parses individual exposure attributes
13+
├── helper.rb # Utility methods for model naming, discriminators
14+
└── version.rb # Gem version
15+
```
16+
17+
### Parser (`parser.rb`)
18+
19+
Entry point for entity parsing. Responsibilities:
20+
- Extract exposures from Grape::Entity
21+
- Handle nested entities and `using:` references
22+
- Process `merge: true` exposures
23+
- Handle inheritance with `allOf` and discriminators
24+
- Determine required fields
25+
26+
### AttributeParser (`attribute_parser.rb`)
27+
28+
Converts individual exposure options to OpenAPI property schema:
29+
- Maps Ruby types to OpenAPI types
30+
- Handles arrays (`is_array: true`)
31+
- Processes enums (`values:`)
32+
- Adds constraints (min/max, minLength/maxLength)
33+
34+
### Helper (`helper.rb`)
35+
36+
Utilities for:
37+
- Model name resolution (strips Entity/Entities suffix)
38+
- Discriminator detection for inheritance
39+
- Root exposure extraction
40+
41+
## Data Flow
42+
43+
```
44+
Grape::Entity class
45+
46+
47+
Parser.call
48+
49+
├── extract_params (get exposures)
50+
51+
├── parse_grape_entity_params
52+
│ │
53+
│ ├── AttributeParser (per exposure)
54+
│ │
55+
│ └── parse_nested (for nested blocks)
56+
57+
└── handle_discriminator (inheritance)
58+
59+
60+
[properties_hash, required_array]
61+
```
62+
63+
## Integration Point
64+
65+
Registered with grape-swagger in `lib/grape-swagger/entity.rb`:
66+
67+
```ruby
68+
GrapeSwagger.model_parsers.register(GrapeSwagger::Entity::Parser, Grape::Entity)
69+
```
70+
71+
grape-swagger calls `Parser.new(model, endpoint).call` when it encounters a `Grape::Entity` subclass.

docs/contributing.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Contributing Guidelines
2+
3+
## PR Requirements
4+
5+
Every PR must include:
6+
7+
1. **CHANGELOG.md entry** - Add under `### X.X.X (Next)` in the appropriate section:
8+
```markdown
9+
#### Fixes
10+
* [#123](https://github.com/ruby-grape/grape-swagger-entity/pull/123): Brief description - [@username](https://github.com/username).
11+
```
12+
13+
2. **Passing CI** - RuboCop + RSpec must pass
14+
15+
3. **Tests** - New functionality needs specs; bug fixes need regression tests
16+
17+
## CHANGELOG Format
18+
19+
```markdown
20+
### 0.7.1 (Next)
21+
22+
#### Features
23+
24+
* Your contribution here.
25+
26+
#### Fixes
27+
28+
* [#PR](URL): Description - [@author](URL).
29+
```
30+
31+
- Use `Features` for new functionality
32+
- Use `Fixes` for bug fixes and maintenance
33+
34+
## Commit Messages
35+
36+
Follow conventional style:
37+
- `Fix #123: description` for bug fixes
38+
- `Add feature description` for features
39+
- `Update dependency/docs` for maintenance
40+
41+
## Code Style
42+
43+
RuboCop enforces style. Key rules:
44+
- `frozen_string_literal: true` pragma required
45+
- Consistent hash indentation
46+
- No trailing whitespace
47+
48+
```bash
49+
bundle exec rubocop -a # Auto-fix most issues
50+
```
51+
52+
## Danger Checks
53+
54+
CI runs danger which enforces:
55+
- CHANGELOG entry present
56+
- Table of Contents in README is current
57+
- PR has description

docs/documentation-options.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Documentation Options
2+
3+
The `documentation` hash in entity exposures supports the following options:
4+
5+
## Type Options
6+
7+
| Option | Description | Example |
8+
|--------|-------------|---------|
9+
| `type` | OpenAPI data type | `String`, `Integer`, `Boolean`, `Float`, `Date`, `DateTime` |
10+
| `is_array` | Marks field as array type | `true` / `false` |
11+
12+
## Description Options
13+
14+
| Option | Description | Example |
15+
|--------|-------------|---------|
16+
| `desc` | Property description | `'User email address'` |
17+
| `example` | Example value for documentation | `'user@example.com'` |
18+
| `default` | Default value | `'pending'` |
19+
20+
## Validation Options
21+
22+
| Option | Description | Example |
23+
|--------|-------------|---------|
24+
| `required` | Whether field is required | `true` / `false` |
25+
| `values` | Enum values (array or proc) | `%w[pending active]` or `-> { Status.all }` |
26+
| `minimum` | Minimum value for numeric types | `0` |
27+
| `maximum` | Maximum value for numeric types | `100` |
28+
| `min_length` | Minimum length for strings | `1` |
29+
| `max_length` | Maximum length for strings | `255` |
30+
| `min_items` | Minimum items for arrays | `1` |
31+
| `max_items` | Maximum items for arrays | `10` |
32+
| `unique_items` | Array items must be unique | `true` |
33+
34+
## Display Options
35+
36+
| Option | Description | Example |
37+
|--------|-------------|---------|
38+
| `read_only` | Marks field as read-only | `true` |
39+
| `hidden` | Hide field from documentation | `true` |
40+
41+
## Examples
42+
43+
### Basic types
44+
45+
```ruby
46+
expose :id, documentation: { type: Integer, desc: 'Unique identifier' }
47+
expose :name, documentation: { type: String, desc: 'Full name', required: true }
48+
expose :active, documentation: { type: Boolean, default: true }
49+
```
50+
51+
### Enums
52+
53+
```ruby
54+
expose :status, documentation: {
55+
type: String,
56+
desc: 'Current status',
57+
values: %w[pending active suspended]
58+
}
59+
```
60+
61+
### Numeric constraints
62+
63+
```ruby
64+
expose :age, documentation: {
65+
type: Integer,
66+
minimum: 0,
67+
maximum: 150
68+
}
69+
```
70+
71+
### String constraints
72+
73+
```ruby
74+
expose :username, documentation: {
75+
type: String,
76+
min_length: 3,
77+
max_length: 20
78+
}
79+
```
80+
81+
### Arrays
82+
83+
```ruby
84+
expose :tags, documentation: {
85+
type: String,
86+
is_array: true,
87+
desc: 'Associated tags'
88+
}
89+
```

0 commit comments

Comments
 (0)