mwpastore / sinja Goto Github PK
View Code? Open in Web Editor NEWRESTful, {json:api}-compliant web services in Sinatra
Home Page: http://sinja-rb.org
License: MIT License
RESTful, {json:api}-compliant web services in Sinatra
Home Page: http://sinja-rb.org
License: MIT License
I have an error trying to do has_many:
ERROR - NoMethodError - undefined method `nullif' for Server::ApiV3:Class:
/home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-2.0.0/lib/sinatra/base.rb:1624:in `block in compile!'
/home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-2.0.0/lib/sinatra/base.rb:1624:in `block in compile!': undefined method `nullif' for Server::ApiV3:Class (NoMethodError)
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-2.0.0/lib/sinatra/base.rb:1624:in `each_pair'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-2.0.0/lib/sinatra/base.rb:1624:in `compile!'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-2.0.0/lib/sinatra/base.rb:1601:in `route'
from /vagrant/lib/sinja.rb:381:in `route'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-2.0.0/lib/sinatra/base.rb:1394:in `patch'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:338:in `prefixed'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:229:in `block (2 levels) in prefixed'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:338:in `prefixed'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:229:in `block (2 levels) in prefixed'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinja-1.2.5/lib/sinja/relationship_routes/has_many.rb:33:in `registered'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:244:in `block in register'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:242:in `each'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:242:in `register'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinja-1.2.5/lib/sinja/resource.rb:109:in `block (3 levels) in <module:Resource>'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:200:in `class_eval'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:200:in `block in new'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:190:in `initialize'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:190:in `new'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:190:in `new'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:220:in `namespace'
from /home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinja-1.2.5/lib/sinja/resource.rb:92:in `block (2 levels) in <module:Resource>'
It's just an simple:
has_many :programmes do
fetch do
resource.programmes
end
end
At least add a README to show how to start and use it!
and/or move them to their own gem
Hi bro, I think your development ability is very strong. I think you can develop some self-built solos and release them. Let us learn. By the way, you can also filter out the black mining pools outside. We will actively support you
Hi,
Sinja has a really slow require time in padrino:
8881.54 padrino
10214.73 dry-types
10736.37 grape
22786.43 sinja
Not sure why though.
Guidelines:
sinja-sequel.gemspec
lib/sinja-sequel.rb
lib/sinja/sequel.rb
lib/sinja/sequel/
lib/sinatra/jsonapi/sequel.rb
core.rb
to provide the basic configuration and helpers for the library in question:
conflict_exceptions
not_found_exceptions
validation_exceptions
validation_formatter
transaction
filter
sort
finalize
validate!
pagination.rb
(and its hook in core.rb
):
page_using
page
helpers.rb
that will ease the pain of writing action helpers, if any.resource
, has_many
, and has_one
, if possible.README.md
to reflect your work and document best practices.Hi @mwpastore,
I have an issue trying to load sinja with Padrino.
The error is:
ERROR - NoMethodError - undefined method `+' for #<Mustermann::Regular:"\\/channels(?![^\\/])">:
/home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:332:in `prefixed_path'
/home/vagrant/.rvm/gems/ruby-2.4.1/gems/sinatra-contrib-2.0.0/lib/sinatra/namespace.rb:332:in `prefixed_path': undefined method `+' for #<Mustermann::Regular:"\\/channels(?![^\\/])"> (NoMethodError)
Basically the sub app loded is
require 'sinja'
require 'sinja/sequel/core'
module Server
class ApiV3 < Padrino::Application
#register Padrino::Mailer
#register Padrino::Helpers
register Sinja
#enable :sessions
#prerequisites << Padrino.root('api_v3', 'controller', '*.rb')
resource :channel do
index do
Channel.all
end
# ..
end
end
end
Hi!
I realize this might be far-fetched since the gem has not been updated in a long time, but is there any possibility that support for Ruby 3.x will be implemented?
Ruby 3 introduces breaking changes related to keyword arguments and I suspect this causes errors with Sinja. Declaring a resource
causes an ArgumentError
in Ruby 3.0.1. For instance, this program:
require 'sinatra/base'
require 'sinatra/jsonapi'
require 'jsonapi-serializers'
class App < Sinatra::Base
register Sinatra::JSONAPI
resource :foos do
end
end
App.run!
yields:
.../.rvm/gems/ruby-3.0.1/gems/sinatra-2.1.0/lib/sinatra/base.rb:1650:in `route': wrong number of arguments (given 4, expected 2..3) (ArgumentError)
from .../.rvm/gems/ruby-3.0.1/gems/sinja-1.3.0/lib/sinja.rb:386:in `route'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-2.1.0/lib/sinatra/base.rb:1443:in `options'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:341:in `prefixed'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:234:in `block (2 levels) in prefixed'
from .../.rvm/gems/ruby-3.0.1/gems/sinja-1.3.0/lib/sinja/resource_routes.rb:12:in `registered'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:249:in `block in register'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:247:in `each'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:247:in `register'
from .../.rvm/gems/ruby-3.0.1/gems/sinja-1.3.0/lib/sinja/resource.rb:28:in `registered'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:249:in `block in register'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:247:in `each'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:247:in `register'
from .../.rvm/gems/ruby-3.0.1/gems/sinja-1.3.0/lib/sinja.rb:356:in `block in resource'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:199:in `class_eval'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:199:in `block in new'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:189:in `initialize'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:189:in `new'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:189:in `new'
from .../.rvm/gems/ruby-3.0.1/gems/sinatra-contrib-2.1.0/lib/sinatra/namespace.rb:219:in `namespace'
from .../.rvm/gems/ruby-3.0.1/gems/sinja-1.3.0/lib/sinja.rb:333:in `resource'
from sinja_demo.rb:8:in `<class:App>'
from sinja_demo.rb:5:in `<main>'
whereas it works fine when using Ruby 2.7.x.
I think Sinja looks really nice and it would definitely suit my needs, so fingers crossed this will be considered :)
Thanks!
The issue seems to be that all my attempts to create new resources via the JSON API using sinja seem to not work. It is entirely possible that I'm doing something wrong, but I can't find it looking through both the README and demo app.
I created a repo with the most essential components of my app captured:
https://github.com/jgnagy/test-api
Notice the /keys endpoint supports both show
and create
. The show works fine, per this curl command:
curl -i -H 'Accept: application/vnd.api+json' http://localhost:9292/keys/1
Which yields something like:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
Last-Modified: Mon, 13 Feb 2017 21:04:00 GMT
Content-Length: 260
Server: WEBrick/1.3.1 (Ruby/2.3.1/2016-04-26)
Date: Mon, 13 Feb 2017 21:04:00 GMT
Connection: Keep-Alive
{
"data": {
"type": "keys",
"id": "1",
"attributes": {
"name": "A Key",
"created-at": "2017-02-13 13:04:00 -0800"
},
"links": {
"self": "/keys/1"
}
},
"jsonapi": {
"version": "1.0"
},
"included": [
]
}
However, attempting to create a new resource via this curl command:
curl -i -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' --data '{"data":{"type":"keys", "attributes":{"name":"foo"}}}' http://localhost:9292/keys
Returns the following:
HTTP/1.1 400 Bad Request
Content-Type: application/vnd.api+json
Content-Length: 199
Server: WEBrick/1.3.1 (Ruby/2.3.1/2016-04-26)
Date: Mon, 13 Feb 2017 21:04:02 GMT
Connection: Keep-Alive
{
"errors": [
{
"id": "0d741b83-7a52-499a-8365-c278cd161e3a",
"title": "Bad Request Error",
"detail": "Malformed {json:api} request payload",
"status": "400"
}
]
}
I'm uncertain why this isn't working, and I've tried making additional Sinatra apps just passing "normal" JSON around and that works fine. When I involve sinja, it seems unhappy and I can't see why.
I'm using ruby 2.3.1 (about to upgrade ruby and see if that helps) via RVM on macOS.
I appreciate the help!
Enhance the resource
, has_one
, and has_many
keywords to take an options hash, which may include a custom route name to be used when drawing namespaces. (See also #9.)
Let's revisit this when jeremyevans/sequel#1275 is updated.
Hi @mwpastore,
Sorry about all the issue tickets, this is merely a question about filters.
I want to be able to do ?filter[date]=2017-09-24&filter[otherfilter][]=1&filter[otherfilter][]=2
But i'm not sure how to do it. There is both show_many and index with filters. show_many doesn't seem to do (filter_by: [:date, :otherfilter]).
What is the correct way of handling it in Sinja? The docs are quite small on the filters part.
Sinja is jumping through too many hoops to play nicely with Sinatra's built-in error-handling in conjunction with sideloading and UDFs. Let's:
:raise_errors
call
pass through middleware?Other notes:
I'm using Falcon as http server for sinatra app that uses sinja for json:api.
I've encountered a problem that my request.body is always malformed json.
After digging in I've found that Falcon uses Protocol::HTTP1::Body::Fixed
as body class which is not rewindable. method #content?
reads first 2 bytes to check if request has body. after that #deserialize_request_body
always retrieves part of content, because in this case env['rack.input']
is an instance of Falcon::Adapters::Input
which silently ignores rewind, because it's underlying body Protocol::HTTP1::Body::Fixed
does not respond to it. I want to leave this issue here - maybe someone will looking solution for same problem.
I think it worth for PR - we can use #empty?
on body if it responds to #empty?
.
my bugfix is following
module SinjaPatch
def content?
return request.body.size > 0 if request.body.respond_to?(:size)
return !request.body.empty? if request.body.respond_to?(:empty?)
request.body.rewind
request.body.read(1)
end
end
module FalconAdaptersInputPatch
def empty?
@body.respond_to?(:empty?) ? @body.empty? : @body.size
end
end
Falcon::Adapters::Input.include FalconAdaptersInputPatch
# must be added after `register Sinatra::JSONAPI` performed.
MyApp.prepend SinjaPatch
HEAD
requests for method discovery and CORSset :jsonapi_serializer_options, :meta => {}
)
Post[id], :include=>:author
)create
/update
graft
/merge
to take a :passthru
option that can be :create
, :update
, or both?env
?action_roles
, action_conflicts
, and relationships
on the registering app's settings (class) is kind of janky. Can we do a better job of hiding this storage from the registering app? It's still on settings but now at least it's tucked into a Config object.ACTIONS
into a method? It's just clumsy and weird. Well, that's a little better.
show
for update, destroy, and relationships is somewhat misguided. I can see a situation where a user has access to e.g. delete something without being able to view it. Maybe we need to abstract out a "finder" helper (or unrestricted action helper) that is used by show, update, etc.?I'm trying to add a custom route (similar to get '/top10'
in your README) and I only get 404s trying to access it. Using pry and inspecting the App::routes on the Sinatra application, I can see the route listed as:
[#<Mustermann::Concat:(regular:"\\/organizations(?![^\\/])" + sinatra:"/mine")>, [#<UnboundMethod: Authify::API::Services::API#`block in registered' condition>], #<Proc:0x007fc26c3ab048@/Users/jgnagy/.rvm/gems/ruby-2.3.1/gems/sinatra-2.0.0.beta2/lib/sinatra/base.rb:1643>]
The goal with the above is to add a custom route @ /organizations/mine
on an otherwise normal {json:api} resource /organizations
.
I've modified my simplified test-api to duplicate the issue: https://github.com/jgnagy/test-api/blob/master/lib/test/api.rb
In the test-api app above, the custom route should be /testkeys/foo
, but hitting that with:
curl -i -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' http://localhost:9292/testkeys/foo
yields:
HTTP/1.1 404 Not Found
Content-Type: application/vnd.api+json
X-Cascade: pass
Content-Length: 141
Server: WEBrick/1.3.1 (Ruby/2.3.1/2016-04-26)
Date: Wed, 15 Feb 2017 15:43:49 GMT
Connection: Keep-Alive
{
"errors": [
{
"id": "bbf08504-d69f-44d5-bb94-b3d84d5e4911",
"title": "Not Found Error",
"status": "404"
}
]
}
I added a vanilla /bar
namespace and tested a /baz
route and that works as expected:
curl -i -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' http://localhost:9292/bar/baz
returning:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
Content-Length: 519
Server: WEBrick/1.3.1 (Ruby/2.3.1/2016-04-26)
Date: Wed, 15 Feb 2017 15:34:47 GMT
Connection: Keep-Alive
{
"data": [
{
"type": "testkeys",
"id": "11",
"attributes": {
"name": "A Key",
"created-at": "2017-02-15 07:34:47 -0800"
},
"links": {
"self": "/testkeys/11"
}
},
{
"type": "testkeys",
"id": "12",
"attributes": {
"name": "A Key",
"created-at": "2017-02-15 07:34:47 -0800"
},
"links": {
"self": "/testkeys/12"
}
}
],
"jsonapi": {
"version": "1.0"
},
"included": [
]
}
I admit that I might be doing something wrong, but I have more-or-less copied and pasted from the README for this test app.
Enhance the resource
, has_one
, and has_many
keywords to track routing keywords (and any custom route names, see also #8) in a global structure, e.g. _sinja.route_config
, which we can then interrogate (along with _sinja.resource_config
) to generate Swagger/RAML/WADL, etc. in combination with some configurables and/or on-disk template(s).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.