schema_dot_org 2.2.1 → 2.2.3
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +34 -22
- data/lib/schema_dot_org/aggregate_offer.rb +2 -5
- data/lib/schema_dot_org/college_or_university.rb +12 -0
- data/lib/schema_dot_org/contact_point.rb +0 -2
- data/lib/schema_dot_org/item_list.rb +0 -1
- data/lib/schema_dot_org/list_item.rb +9 -8
- data/lib/schema_dot_org/offer.rb +1 -3
- data/lib/schema_dot_org/organization.rb +7 -4
- data/lib/schema_dot_org/person.rb +7 -3
- data/lib/schema_dot_org/place.rb +1 -0
- data/lib/schema_dot_org/product.rb +1 -4
- data/lib/schema_dot_org/search_action.rb +1 -1
- data/lib/schema_dot_org/web_site.rb +1 -0
- data/lib/schema_dot_org.rb +122 -10
- data/schema_dot_org.gemspec +1 -1
- metadata +3 -3
- data/lib/schema_dot_org/schema_type.rb +0 -110
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e190c183425efbb7808c9e18f253cd377b91a4ce927d8f401f02158d6d704cf
|
4
|
+
data.tar.gz: 5e01217b962ed0ec450bda73923e2fbdff9ec4baeee2433c96cdc27c53e08bbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36a893438da0d2731fba7a14a5d2a04b4a406688b5be906c6080ad30b2bb42865553943451fcb25e22a737e2e5478ac95a72f8fadf6447f28791c8e0ff89d2d9
|
7
|
+
data.tar.gz: 2b1feab097655a4efd511838774f1f4c5224c0767cf78aa970f7feb7b57bd6e7a74bf7327aee2eecd2578d38aee68eb494c5ea5b6ff6131651c82c429f27cb70
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,22 +2,23 @@
|
|
2
2
|
|
3
3
|
# SchemaDotOrg
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
Easily create [Structured Data](https://developers.google.com/search/docs/guides/intro-structured-data) with **correct syntax and semantics**.
|
6
|
+
Good structured data [helps enhance a website's search result appearance](https://developers.google.com/search/docs/guides/enhance-site):
|
7
7
|
|
8
8
|
> Google Search works hard to understand the content of a page. You can help us by providing explicit clues about the meaning of a page . . .
|
9
9
|
|
10
10
|
## Usage
|
11
11
|
|
12
|
-
Let's say you have a Rails app.
|
12
|
+
Let's say you have a Rails app. First write plain-ruby code in a controller. Just instantiate
|
13
|
+
the structured data object you want in your web page:
|
13
14
|
|
14
15
|
```ruby
|
15
|
-
@
|
16
|
+
@my_org = Organization.new(
|
16
17
|
name: 'Public.Law',
|
17
18
|
founder: Person.new(name: 'Robb Shecter'),
|
18
19
|
founding_date: Date.new(2009, 3, 6),
|
19
20
|
founding_location: Place.new(address: 'Portland, OR'),
|
20
|
-
email: '
|
21
|
+
email: 'support@public.law',
|
21
22
|
telephone: '+1 123 456 7890',
|
22
23
|
url: 'https://www.public.law',
|
23
24
|
logo: 'https://www.public.law/favicon-196x196.png',
|
@@ -28,13 +29,13 @@ Let's say you have a Rails app. If you put this in a controller:
|
|
28
29
|
)
|
29
30
|
```
|
30
31
|
|
31
|
-
...and
|
32
|
+
...and then output it in a template:
|
32
33
|
|
33
34
|
```html
|
34
|
-
<%= @
|
35
|
+
<%= @my_org %>
|
35
36
|
```
|
36
37
|
|
37
|
-
...you'll get this in
|
38
|
+
...you'll get this perfectly formatted structured data in your HTML:
|
38
39
|
|
39
40
|
```html
|
40
41
|
<script type="application/ld+json">
|
@@ -42,7 +43,7 @@ Let's say you have a Rails app. If you put this in a controller:
|
|
42
43
|
"@context": "http://schema.org",
|
43
44
|
"@type": "Organization",
|
44
45
|
"name": "Public.Law",
|
45
|
-
"email": "
|
46
|
+
"email": "support@public.law",
|
46
47
|
"telephone": "+1 123 456 7890",
|
47
48
|
"url": "https://www.public.law",
|
48
49
|
"logo": "https://www.public.law/favicon-196x196.png",
|
@@ -63,14 +64,25 @@ Let's say you have a Rails app. If you put this in a controller:
|
|
63
64
|
</script>
|
64
65
|
```
|
65
66
|
|
66
|
-
|
67
|
+
### Principle: No silent failures
|
68
|
+
|
69
|
+
We coded the library this way because the data is embedded in the HTML - and it's a
|
70
|
+
pain in the butt to manually check for errors. In my case, I manage 500,000 unique
|
71
|
+
pages in my Rails app. There's _no way_ I could place error-free structured data in
|
72
|
+
them without automatic validation.
|
73
|
+
|
74
|
+
`SchemaDotOrg` will validate your Ruby code, and if it's correct, will generate Schema.org JSON-LD markup when `#to_s`
|
75
|
+
is called. If you, e.g., didn't add the correct attributes, you'll get a descriptive error message pointing
|
76
|
+
you to the problem.
|
67
77
|
|
68
|
-
|
69
|
-
|
70
|
-
|
78
|
+
Notice how the `foundingDate` is in the required ISO-8601 format. In the same way, the `foundingLocation` is a `Place`
|
79
|
+
which adds the proper `@type` attribute. All Ruby snake-case names have been converted to the Schema.org standard camel-case.
|
80
|
+
Etc., etc.
|
71
81
|
|
72
82
|
### You are prevented from creating invalid markup
|
73
83
|
|
84
|
+
If your page loads, you know your markup is good.
|
85
|
+
|
74
86
|
If you use the wrong type or try to set an unknown attribute, SchemaDotOrg will
|
75
87
|
refuse to create the incorrect JSON-LD. Instead, you'll get a message explaining
|
76
88
|
the problem:
|
@@ -86,15 +98,18 @@ Place.new(
|
|
86
98
|
# => NoMethodError: undefined method `author'
|
87
99
|
```
|
88
100
|
|
89
|
-
|
101
|
+
In my experience, I never get errors from the lib. I code it once, it works, and then
|
102
|
+
I move on to other things.
|
103
|
+
|
104
|
+
> This automatic validation comes from my [ValidatedObject gem](https://github.com/dogweather/validated_object), which in turn,
|
105
|
+
> is a thin wrapper around ActiveRecord::Validations. So there's nothing magical going on here.
|
90
106
|
|
91
107
|
## Supported Schema.org Types
|
92
108
|
|
93
109
|
AggregateOffer, ContactPoint, ItemList, ListItem, Offer, Organization, Person, Place,
|
94
110
|
Product, SearchAction, and WebSite.
|
95
111
|
|
96
|
-
Here are a few
|
97
|
-
all the available attributes.
|
112
|
+
Here are a few examples. [The source code for these is extremely easy to read.](https://github.com/dogweather/schema-dot-org/tree/master/lib/schema_dot_org) Check them out to see all the available attributes.
|
98
113
|
|
99
114
|
### WebSite
|
100
115
|
|
@@ -140,9 +155,6 @@ Organization.new(
|
|
140
155
|
)
|
141
156
|
```
|
142
157
|
|
143
|
-
### Person, Place, and SearchAction
|
144
|
-
|
145
|
-
These three aren't too useful on their own in web apps. They're used when creating a `WebSite` and `Organization`, as shown above.
|
146
158
|
|
147
159
|
## Installation
|
148
160
|
|
@@ -154,8 +166,8 @@ gem 'schema_dot_org'
|
|
154
166
|
|
155
167
|
## Development
|
156
168
|
|
157
|
-
The
|
158
|
-
easy to create and add to. For example, `Product`:
|
169
|
+
The coding is as DRY as I could possibly make it. I think it's really
|
170
|
+
easy to create and add to. For example, here's `Product`:
|
159
171
|
|
160
172
|
```ruby
|
161
173
|
class Product < SchemaType
|
@@ -179,4 +191,4 @@ Bug reports and pull requests are welcome on GitHub.
|
|
179
191
|
|
180
192
|
## License
|
181
193
|
|
182
|
-
|
194
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require 'schema_dot_org/offer'
|
6
|
-
|
7
|
-
# Model the Schema.org `Thing > Place`. See https://schema.org/Offer
|
3
|
+
#
|
4
|
+
# Model the Schema.org `Thing > Intangible > Offer > AggregateOffer`. See https://schema.org/Offer
|
8
5
|
#
|
9
6
|
module SchemaDotOrg
|
10
7
|
class AggregateOffer < SchemaType
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
#
|
5
|
+
# https://schema.org/CollegeOrUniversity
|
6
|
+
#
|
7
|
+
module SchemaDotOrg
|
8
|
+
class CollegeOrUniversity < SchemaType
|
9
|
+
validated_attr :name, type: String, presence: true
|
10
|
+
validated_attr :url, type: String, allow_nil: true
|
11
|
+
end
|
12
|
+
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'schema_dot_org'
|
4
|
-
require 'schema_dot_org/product'
|
5
3
|
|
4
|
+
require_relative 'product'
|
6
5
|
|
6
|
+
#
|
7
|
+
# Model the Schema.org `ItemListElement`. See https://schema.org/ItemListElement
|
8
|
+
#
|
7
9
|
module SchemaDotOrg
|
8
|
-
# Model the Schema.org `ItemListElement`. See https://schema.org/ItemListElement
|
9
10
|
class ListItem < SchemaType
|
10
|
-
validated_attr :image, type: String,
|
11
|
-
validated_attr :item, type: Product, allow_nil: true
|
12
|
-
validated_attr :name, type: String,
|
13
|
-
validated_attr :position, type: Integer,
|
14
|
-
validated_attr :url, type: String,
|
11
|
+
validated_attr :image, type: String, allow_nil: true
|
12
|
+
validated_attr :item, type: SchemaDotOrg::Product, allow_nil: true
|
13
|
+
validated_attr :name, type: String, allow_nil: true
|
14
|
+
validated_attr :position, type: Integer, presence: true
|
15
|
+
validated_attr :url, type: String, allow_nil: true
|
15
16
|
end
|
16
17
|
end
|
data/lib/schema_dot_org/offer.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'date'
|
4
|
-
require 'schema_dot_org'
|
5
3
|
|
6
4
|
#
|
7
|
-
# Model the Schema.org `Thing >
|
5
|
+
# Model the Schema.org `Thing > Intangible > Offer`. See https://schema.org/Offer
|
8
6
|
#
|
9
7
|
module SchemaDotOrg
|
10
8
|
class Offer < SchemaType
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'date'
|
4
|
-
require 'schema_dot_org'
|
5
|
-
require 'schema_dot_org/person'
|
6
|
-
require 'schema_dot_org/place'
|
7
|
-
require 'schema_dot_org/contact_point'
|
8
4
|
|
5
|
+
require_relative 'person'
|
6
|
+
require_relative 'place'
|
7
|
+
|
8
|
+
# Google allows `url` to be a string:
|
9
|
+
# https://developers.google.com/search/docs/appearance/structured-data/logo
|
9
10
|
|
10
11
|
module SchemaDotOrg
|
11
12
|
class Organization < SchemaType
|
@@ -14,9 +15,11 @@ module SchemaDotOrg
|
|
14
15
|
validated_attr :founder, type: SchemaDotOrg::Person, allow_nil: true
|
15
16
|
validated_attr :founding_date, type: Date, allow_nil: true
|
16
17
|
validated_attr :founding_location, type: SchemaDotOrg::Place, allow_nil: true
|
18
|
+
validated_attr :legal_name, type: String, allow_nil: true
|
17
19
|
validated_attr :logo, type: String
|
18
20
|
validated_attr :name, type: String
|
19
21
|
validated_attr :same_as, type: Array, allow_nil: true
|
22
|
+
validated_attr :slogan, type: String, allow_nil: true
|
20
23
|
validated_attr :telephone, type: String, allow_nil: true
|
21
24
|
validated_attr :url, type: String
|
22
25
|
end
|
@@ -1,12 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
|
3
4
|
#
|
4
5
|
# Model the Schema.org **Person**. See http://schema.org/Person
|
5
6
|
#
|
6
7
|
module SchemaDotOrg
|
7
8
|
class Person < SchemaType
|
8
|
-
validated_attr :
|
9
|
-
validated_attr :
|
10
|
-
validated_attr :
|
9
|
+
validated_attr :award, type: String, allow_nil: true
|
10
|
+
validated_attr :alumni_of, type: SchemaDotOrg::CollegeOrUniversity, allow_nil: true
|
11
|
+
validated_attr :honorific_suffix, type: String, allow_nil: true
|
12
|
+
validated_attr :name, type: String, presence: true
|
13
|
+
validated_attr :same_as, type: Array, allow_nil: true
|
14
|
+
validated_attr :url, type: String, allow_nil: true
|
11
15
|
end
|
12
16
|
end
|
data/lib/schema_dot_org/place.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'date'
|
4
|
-
require 'schema_dot_org'
|
5
|
-
require 'schema_dot_org/aggregate_offer'
|
6
3
|
|
7
4
|
#
|
8
|
-
# Model the Schema.org `Thing >
|
5
|
+
# Model the Schema.org `Thing > Product`. See https://schema.org/Product
|
9
6
|
#
|
10
7
|
module SchemaDotOrg
|
11
8
|
class Product < SchemaType
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# Model the Schema.org `Thing > SearchAction`. See http://schema.org/SearchAction
|
6
6
|
#
|
7
7
|
module SchemaDotOrg
|
8
|
-
class SearchAction < SchemaType
|
8
|
+
class SearchAction < SchemaDotOrg::SchemaType
|
9
9
|
validated_attr :query_input, type: String, presence: true
|
10
10
|
validated_attr :target, type: String, presence: true
|
11
11
|
end
|
data/lib/schema_dot_org.rb
CHANGED
@@ -1,16 +1,128 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
require 'json'
|
3
|
+
require 'validated_object'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Abstract base class for all the Schema.org types.
|
7
|
+
#
|
8
|
+
module SchemaDotOrg
|
9
|
+
class SchemaType < ValidatedObject::Base
|
10
|
+
ROOT_ATTR = { "@context" => "https://schema.org" }.freeze
|
11
|
+
UNQUALIFIED_CLASS_NAME_REGEX = /([^:]+)$/
|
12
|
+
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
json_string = to_json_ld(pretty: (!rails_production? && !ENV['SCHEMA_DOT_ORG_MINIFIED_JSON']))
|
16
|
+
|
17
|
+
# Mark as safe if we're in Rails
|
18
|
+
if json_string.respond_to?(:html_safe)
|
19
|
+
json_string.html_safe
|
20
|
+
else
|
21
|
+
json_string
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def to_json_ld(pretty: false)
|
27
|
+
"<script type=\"application/ld+json\">\n" + to_json(pretty: pretty, as_root: true) + "\n</script>"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def to_json(pretty: false, as_root: false)
|
32
|
+
structure = as_root ? ROOT_ATTR.merge(to_json_struct) : to_json_struct
|
33
|
+
|
34
|
+
if pretty
|
35
|
+
JSON.pretty_generate(structure)
|
36
|
+
else
|
37
|
+
structure.to_json
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# Use the class name to create the "@type" attribute.
|
43
|
+
# @return a hash structure representing json.
|
44
|
+
def to_json_struct
|
45
|
+
{ "@type" => un_namespaced_classname }.merge(_to_json_struct.reject { |_, v| v.blank? })
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def _to_json_struct
|
50
|
+
attrs_and_values
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
# @return the classname without the module namespace.
|
55
|
+
def un_namespaced_classname
|
56
|
+
self.class.name =~ UNQUALIFIED_CLASS_NAME_REGEX
|
57
|
+
Regexp.last_match(1)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def object_to_json_struct(object)
|
62
|
+
return nil unless object
|
63
|
+
object.to_json_struct
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def attrs_and_values
|
68
|
+
attrs.map do |attr|
|
69
|
+
# Clean up and andle the `query-input` attribute, which
|
70
|
+
# doesn't follow the normal camelCase convention.
|
71
|
+
attr_name = snake_case_to_lower_camel_case(attr.to_s.delete_prefix('@')).sub('queryInput', 'query-input')
|
72
|
+
attr_value = instance_variable_get(attr)
|
73
|
+
|
74
|
+
[attr_name, resolve_value(attr_value)]
|
75
|
+
end.to_h
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def resolve_value(value)
|
80
|
+
if value.is_a?(Array)
|
81
|
+
value.map { |v| resolve_value(v) }
|
82
|
+
|
83
|
+
elsif value.is_a?(Date)
|
84
|
+
value.to_s
|
85
|
+
|
86
|
+
elsif is_schema_type?(value)
|
87
|
+
value.to_json_struct
|
88
|
+
|
89
|
+
else
|
90
|
+
value
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def snake_case_to_lower_camel_case(snake_case)
|
96
|
+
snake_case.to_s.split('_').map.with_index { |s, i| i.zero? ? s : s.capitalize }.join
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def attrs
|
101
|
+
instance_variables.reject{ |v| [:@validation_context, :@errors].include?(v) }
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def is_schema_type?(object)
|
106
|
+
object.class.module_parent == SchemaDotOrg
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def rails_production?
|
111
|
+
defined?(Rails) && Rails.env.production?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
require 'schema_dot_org/aggregate_offer'
|
118
|
+
require 'schema_dot_org/college_or_university'
|
119
|
+
require 'schema_dot_org/contact_point'
|
7
120
|
require 'schema_dot_org/item_list'
|
8
121
|
require 'schema_dot_org/list_item'
|
122
|
+
require 'schema_dot_org/organization'
|
9
123
|
require 'schema_dot_org/person'
|
10
124
|
require 'schema_dot_org/place'
|
11
|
-
require 'schema_dot_org/
|
125
|
+
require 'schema_dot_org/product'
|
12
126
|
require 'schema_dot_org/offer'
|
13
|
-
require 'schema_dot_org/
|
14
|
-
|
15
|
-
module SchemaDotOrg
|
16
|
-
end
|
127
|
+
require 'schema_dot_org/search_action'
|
128
|
+
require 'schema_dot_org/web_site'
|
data/schema_dot_org.gemspec
CHANGED
@@ -7,7 +7,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.required_ruby_version = '>= 2.6'
|
9
9
|
spec.name = 'schema_dot_org'
|
10
|
-
spec.version = '2.2.
|
10
|
+
spec.version = '2.2.3'
|
11
11
|
spec.authors = ['Robb Shecter']
|
12
12
|
spec.email = ['robb@public.law']
|
13
13
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_dot_org
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robb Shecter
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: validated_object
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- bin/tapioca
|
88
88
|
- lib/schema_dot_org.rb
|
89
89
|
- lib/schema_dot_org/aggregate_offer.rb
|
90
|
+
- lib/schema_dot_org/college_or_university.rb
|
90
91
|
- lib/schema_dot_org/contact_point.rb
|
91
92
|
- lib/schema_dot_org/item_list.rb
|
92
93
|
- lib/schema_dot_org/list_item.rb
|
@@ -95,7 +96,6 @@ files:
|
|
95
96
|
- lib/schema_dot_org/person.rb
|
96
97
|
- lib/schema_dot_org/place.rb
|
97
98
|
- lib/schema_dot_org/product.rb
|
98
|
-
- lib/schema_dot_org/schema_type.rb
|
99
99
|
- lib/schema_dot_org/search_action.rb
|
100
100
|
- lib/schema_dot_org/web_site.rb
|
101
101
|
- schema_dot_org.gemspec
|
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'validated_object'
|
3
|
-
|
4
|
-
module SchemaDotOrg
|
5
|
-
class SchemaType < ValidatedObject::Base
|
6
|
-
ROOT_ATTR = { "@context" => "http://schema.org" }.freeze
|
7
|
-
UNQUALIFIED_CLASS_NAME_REGEX = /([^:]+)$/
|
8
|
-
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
json_string = to_json_ld(pretty: (!rails_production? && !ENV['SCHEMA_DOT_ORG_MINIFIED_JSON']))
|
12
|
-
|
13
|
-
# Mark as safe if we're in Rails
|
14
|
-
if json_string.respond_to?(:html_safe)
|
15
|
-
json_string.html_safe
|
16
|
-
else
|
17
|
-
json_string
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
def to_json_ld(pretty: false)
|
23
|
-
"<script type=\"application/ld+json\">\n" + to_json(pretty: pretty, as_root: true) + "\n</script>"
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
def to_json(pretty: false, as_root: false)
|
28
|
-
structure = as_root ? ROOT_ATTR.merge(to_json_struct) : to_json_struct
|
29
|
-
|
30
|
-
if pretty
|
31
|
-
JSON.pretty_generate(structure)
|
32
|
-
else
|
33
|
-
structure.to_json
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
# Use the class name to create the "@type" attribute.
|
39
|
-
# @return a hash structure representing json.
|
40
|
-
def to_json_struct
|
41
|
-
{ "@type" => un_namespaced_classname }.merge(_to_json_struct.reject { |_, v| v.blank? })
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
def _to_json_struct
|
46
|
-
attrs_and_values
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
# @return the classname without the module namespace.
|
51
|
-
def un_namespaced_classname
|
52
|
-
self.class.name =~ UNQUALIFIED_CLASS_NAME_REGEX
|
53
|
-
Regexp.last_match(1)
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def object_to_json_struct(object)
|
58
|
-
return nil unless object
|
59
|
-
object.to_json_struct
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
def attrs_and_values
|
64
|
-
attrs.map do |attr|
|
65
|
-
# Clean up and andle the `query-input` attribute, which
|
66
|
-
# doesn't follow the normal camelCase convention.
|
67
|
-
attr_name = snake_case_to_lower_camel_case(attr.to_s.delete_prefix('@')).sub('queryInput', 'query-input')
|
68
|
-
attr_value = instance_variable_get(attr)
|
69
|
-
|
70
|
-
[attr_name, resolve_value(attr_value)]
|
71
|
-
end.to_h
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
def resolve_value(value)
|
76
|
-
if value.is_a?(Array)
|
77
|
-
value.map { |v| resolve_value(v) }
|
78
|
-
|
79
|
-
elsif value.is_a?(Date)
|
80
|
-
value.to_s
|
81
|
-
|
82
|
-
elsif is_schema_type?(value)
|
83
|
-
value.to_json_struct
|
84
|
-
|
85
|
-
else
|
86
|
-
value
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
|
-
def snake_case_to_lower_camel_case(snake_case)
|
92
|
-
snake_case.to_s.split('_').map.with_index { |s, i| i.zero? ? s : s.capitalize }.join
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
def attrs
|
97
|
-
instance_variables.reject{ |v| [:@validation_context, :@errors].include?(v) }
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
def is_schema_type?(object)
|
102
|
-
object.class.module_parent == SchemaDotOrg
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
def rails_production?
|
107
|
-
defined?(Rails) && Rails.env.production?
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|