sanity-ruby 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: 0c4121d2a2289a431f6f938b61f275a3d06daebcf8821e02530cfe79b0c00979
4
+ data.tar.gz: 350cd01bf81655b2c46d60255055a47979b388803f5f83efbc1590e2bc908266
5
+ SHA512:
6
+ metadata.gz: 95e189e52382c065a9f70123f1fe789c8bdb81e62399e6da73e3f4a4ec30f07f3d8d95239774421aa786edfac4ed4cfd44b5edb093abc37b9a7064f844d666b2
7
+ data.tar.gz: 6b2d7c915b3350d01374ae53425b108b156f97c4633575a79e4094553756fe16a17038398096f5801fbe8cd866decb040f571ce5580026d02fd399a053d5ce3a
@@ -0,0 +1,29 @@
1
+ name: ci
2
+ on: push
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
9
+ ruby: [2.6, 2.7, "3.0"]
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+ - uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: ${{ matrix.ruby }}
15
+ bundler-cache: true
16
+ - run: bundle exec rake test
17
+
18
+ lint:
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby: [2.6]
23
+ steps:
24
+ - uses: actions/checkout@v2
25
+ - uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: ${{ matrix.ruby }}
28
+ bundler-cache: true
29
+ - run: bundle exec rake lint
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ Gemfile.lock
data/.standard.yml ADDED
@@ -0,0 +1,2 @@
1
+ parallel: true
2
+ format: progress
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sanity.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
8
+ gem "minitest-reporters", ">= 1.4"
9
+ gem "mocha", ">= 1.12"
10
+ gem "pry"
11
+
12
+ gem "guard"
13
+ gem "guard-minitest"
14
+ gem "yard"
15
+
16
+ gem "standard"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Drew Monroe
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,203 @@
1
+ # Sanity
2
+
3
+ ![](https://github.com/morning-brew/sanity-ruby/actions/workflows/ci.yml/badge.svg)
4
+ <a href="https://codeclimate.com/github/morning-brew/sanity-ruby/maintainability"><img src="https://api.codeclimate.com/v1/badges/1984ee6eb0bce46a2469/maintainability" /></a>
5
+
6
+ The Sanity Ruby library provides convenient access to the Sanity API from applications written in Ruby. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses when applicable.
7
+
8
+ The library also provides other features. For example:
9
+
10
+ - Easy configuration for fast setup and use.
11
+ - A pre-defined class to help make any PORO a "sanity resource"
12
+ - Extensibility in overriding the wrapper of your API response results
13
+ - A small DSL around GROQ queries
14
+
15
+ ## Contents
16
+
17
+ - [Getting Started](#getting-started)
18
+ - [Mutating](#mutating)
19
+ - [Querying](#querying)
20
+ - [Development](#development)
21
+ - [Contributing](#contributing)
22
+ - [License](#license)
23
+
24
+ ## Getting Started
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ ```ruby
29
+ gem 'sanity-ruby'
30
+ ```
31
+
32
+ To create a new document:
33
+
34
+ ```ruby
35
+ Sanity::Document.create(params: {_type: "user", first_name: "Carl", last_name: "Sagan"})
36
+ ```
37
+
38
+ To create a new asset:
39
+
40
+ ```ruby
41
+ # TODO
42
+ ```
43
+
44
+ To make any PORO a sanity resource:
45
+
46
+ ```ruby
47
+ class User < Sanity::Resource
48
+ attribute :_id, default: ""
49
+ attribute :_type: default: ""
50
+ mutatable only: %i(create delete)
51
+ queryable
52
+ end
53
+ ```
54
+
55
+ To create a new document in Sanity:
56
+
57
+ ```ruby
58
+ User.create(params: { first_name: "Carl", last_name: "Sagan" })
59
+ ```
60
+
61
+ or if you need to validate the object in your application first:
62
+
63
+ ```ruby
64
+ user = User.new(first_name: "Carl", last_name: "Sagan")
65
+ # your business logic here...
66
+ user.create
67
+ ```
68
+
69
+ To make any PORO act like a sanity resource:
70
+
71
+ ```ruby
72
+ class User
73
+ include Sanity::Mutatable
74
+ include Sanity::Queryable
75
+ queryable
76
+ mutatable
77
+ end
78
+ ```
79
+
80
+ ## Mutating
81
+
82
+ To [create a document](https://www.sanity.io/docs/http-mutations#c732f27330a4):
83
+
84
+ ```ruby
85
+ Sanity::Document.create(params: {_type: "user", first_name: "Carl", last_name: "Sagan"})
86
+ ```
87
+
88
+ To [create or replace a document](https://www.sanity.io/docs/http-mutations#95bb692d7fb0):
89
+
90
+ ```ruby
91
+ Sanity::Document.create_or_replace(params: { _id: "1234-321", _type: "user", first_name: "Carl", last_name: "Sagan"})
92
+ ```
93
+
94
+ To [create a document if it does not exist](https://www.sanity.io/docs/http-mutations#bd91661cae0c):
95
+
96
+ ```ruby
97
+ Sanity::Document.create_if_not_exists(params: { _id: "1234-321", _type: "user", first_name: "Carl", last_name: "Sagan"})
98
+ ```
99
+
100
+ To [delete a document](https://www.sanity.io/docs/http-mutations#40a9a879af9b):
101
+
102
+ ```ruby
103
+ Sanity::Document.delete(params: { _id: "1234-321"})
104
+ ```
105
+
106
+ To [patch a document](https://www.sanity.io/docs/http-mutations#2f480b2baca5):
107
+
108
+ ```ruby
109
+ Sanity::Document.patch(params: { _id: "1234-321", set: { first_name: "Carl" }})
110
+ ```
111
+
112
+ ## Querying
113
+
114
+ To [find document(s) by id](https://www.sanity.io/docs/http-doc):
115
+
116
+ ```ruby
117
+ Sanity::Document.find(_id: "1234-321")
118
+ ```
119
+
120
+ To find documents based on certain fields:
121
+
122
+ ```ruby
123
+ Sanity::Document.where(_id: "1234-321", slug: "foobar")
124
+ ```
125
+
126
+ [Where](https://www.sanity.io/docs/query-cheat-sheet#3949cadc7524)
127
+
128
+ _majority supported_
129
+
130
+ ```ruby
131
+ where: {
132
+ _id: "123", # _id == '123'
133
+ _id: {not: "123"} # _id != '123'
134
+ title: {match: "wo*"} # title match 'wo*'
135
+ popularity: {gt: 10}, # popularity > 10
136
+ popularity: {gt_eq: 10}, # popularity >= 10
137
+ popularity: {lt: 10}, # popularity < 10
138
+ popularity: {lt_eq: 10}, # popularity <= 10
139
+ _type: "movie", or: {_type: "cast"} # _type == 'movie' || _type == 'cast'
140
+ _type: "movie", and: {or: [{_type: "cast"}, {_type: "person"}]} # _type == 'movie' && (_type == 'cast' || _type == 'person')
141
+ _type: "movie", or: [{_type: "cast"}, {_type: "person"}] # _type == 'movie' || _type == 'cast' || _type == 'person'
142
+ }
143
+ ```
144
+
145
+ ```ruby
146
+ Sanity::Document.where(_type: "user", and: {or: {_id: "123", first_name: "Carl" }})
147
+ # Resulting GROQ:
148
+ # *[_type == 'user' && (_id == '123' || first_name == 'Carl')]
149
+ ```
150
+
151
+ [Order](https://www.sanity.io/docs/query-cheat-sheet#b5aec96cf56c)
152
+
153
+ _partially supported_
154
+
155
+ ```ruby
156
+ order: { createdAt: :desc, updatedAt: :asc }
157
+ # order(createdAt desc) | order(updatedAt asc)
158
+ ```
159
+
160
+ [Limit](https://www.sanity.io/docs/query-cheat-sheet#170b92d4caa2)
161
+
162
+ ```ruby
163
+ limit: 5, offset: 10
164
+ ```
165
+
166
+ ```ruby
167
+ Sanity::Document.where(_type: "user", limit: 5, offset: 2)
168
+ ```
169
+
170
+ [Select](https://www.sanity.io/docs/query-cheat-sheet#55d30f6804cc)
171
+
172
+ _partially supported_
173
+
174
+ ```ruby
175
+ select: [:_id, :slug, :title, :name]
176
+ ```
177
+
178
+ ```ruby
179
+ Sanity::Document.where(_type: "user", select: %i[first_name last_name])
180
+ ```
181
+
182
+ Should you need more advanced querying that isn't handled in this gem's DSL you can pass a raw groq query
183
+
184
+ [Query Cheat Sheet](https://www.sanity.io/docs/query-cheat-sheet)
185
+
186
+ ```ruby
187
+ Sanity::Document.where(groq: "*[_type=='movie']{title,poster{asset->{path,url}}}")
188
+ ```
189
+
190
+ ## Development
191
+
192
+ 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.
193
+
194
+ 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).
195
+
196
+ ## Contributing
197
+
198
+ Bug reports and pull requests are welcome on GitHub at https://github.com/morning-brew/sanity-ruby.
199
+
200
+
201
+ ## License
202
+
203
+ 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,24 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task default: :test
11
+
12
+ ##
13
+ # Github Actions always sets ENV["CI"] to true, so we can depend on it to prevent
14
+ # standardrb from running with the "--fix" flag.
15
+ #
16
+ # @see
17
+ # https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables
18
+ task :lint do
19
+ if ENV["CI"]
20
+ sh "bin/standardrb"
21
+ else
22
+ sh "bin/standardrb --fix"
23
+ end
24
+ end
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sanity"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bin/standardrb ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'standardrb' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("standard", "standardrb")
data/lib/sanity.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "sanity/refinements"
5
+
6
+ require "sanity/version"
7
+ require "sanity/configuration"
8
+
9
+ require "sanity/groqify"
10
+ require "sanity/http"
11
+
12
+ require "sanity/attributable"
13
+ require "sanity/mutatable"
14
+ require "sanity/queryable"
15
+
16
+ require "sanity/resource"
17
+ require "sanity/resources"
18
+
19
+ module Sanity
20
+ class Error < StandardError; end
21
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sanity
4
+ # Attributable is responsible for setting the appropriate attributes
5
+ # on an object in memory
6
+ #
7
+ # The attribute marco is used to define the available attributes and
8
+ # the default return value if applicable
9
+ #
10
+ # @example provides getter and setter methods for `_id` and sets the default value to an empty string
11
+ # attribute :_id, default: ""
12
+ #
13
+ module Attributable
14
+ class << self
15
+ def included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+ def attributes
22
+ @attributes ||= []
23
+ end
24
+
25
+ def default_attributes
26
+ @defaults ||= {}
27
+ end
28
+
29
+ private
30
+
31
+ def attribute(name, default: nil)
32
+ attributes << name
33
+ default_attributes.merge!("#{name}": default)
34
+ end
35
+ end
36
+
37
+ attr_reader :attributes
38
+
39
+ def initialize(**args)
40
+ self.class.default_attributes.merge(args).then do |attrs|
41
+ attrs.each do |key, val|
42
+ define_singleton_method("#{key}=") do |val|
43
+ args[key] = val
44
+ attributes[key] = val
45
+ end
46
+
47
+ define_singleton_method(key) { args[key] }
48
+ end
49
+
50
+ instance_variable_set("@attributes", attrs)
51
+ end
52
+ end
53
+
54
+ def inspect
55
+ attributes.keys.map { |key| "#{key}: #{attributes[key].inspect}" }.join(", ").then do |attrs|
56
+ attrs.empty? ? "#<#{_instance}>" : "#<#{_instance} #{attrs}>"
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def _instance
63
+ "#{self.class}:0x#{object_id}"
64
+ end
65
+ end
66
+ end