apicasso 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5bb7e923ec8a2c1b6dd39fa43f73aa1be3ee06e8
4
- data.tar.gz: bb00637db4132d6657dd28522dd44ecb5c4aab66
3
+ metadata.gz: f4a2ce3d41ad82b4b1ac28fc6dfa0b6f8a756b55
4
+ data.tar.gz: 8d1d9d6f5aa7abae2406020e6445d1e3b1bb3932
5
5
  SHA512:
6
- metadata.gz: b40b4cd7847667e72ec02688ff615fd0c5478d00fb61428423c99e10a25b12c19f2ee6c1cfdad9bdb3b003e63e372f909448efcc42647a1bfd454075f139b27c
7
- data.tar.gz: 066b338bbb39d787213ad8d836ccaa24a72b8bf1934c86dc9ab1d468eada1450f7715b37908627b7ebd60c2feb7512568d85b0305e41e2b022e556c572d5e5eb
6
+ metadata.gz: 02332ef2f6cb186bfb2f94f88ad44d60341fb6fff892ffac77293474bd3089ba297b48b6934f6d89d1fd3d773ccc4f5b8f7754e597a58b83fee4fb06728e5ff3
7
+ data.tar.gz: 9a45a1ac48bb74da7bc40aa003a9faf0d0da486f89b9c9f66ca47732d25a80bfb0f6d74347e5eab1d25983c50f91eaa5330bcb9716c6dfb5a330ef4dced02444
data/README.md CHANGED
@@ -5,7 +5,7 @@ JSON API development can get boring and time consuming. If you think it through,
5
5
  **APIcasso** is intended to be used as a full-fledged CRUD JSON API or as a base controller to speed-up development.
6
6
  It is a route-based resource abstraction using API key scoping. This makes it possible to make CRUD-only applications just by creating functional Rails' models. It is a perfect candidate for legacy Rails projects that do not have an API. Access to your application's resources is managed by a `.scope` JSON object per API key. It uses that permission scope to restrict and extend access.
7
7
 
8
- ## Installation
8
+ # Installation
9
9
  Add this line to your application's `Gemfile`:
10
10
 
11
11
  ```ruby
@@ -18,8 +18,13 @@ $ rails g apicasso:install
18
18
  ```
19
19
  You will need to use a database with JSON fields support to use this gem.
20
20
 
21
- ## Usage
22
- After installing APIcasso into your application you can mount a full-fledged CRUD JSON API just by attaching into some route. Usually you will have it under a scoped route like `/api/v1` or a subdomain. You can do that by adding this into your `config/routes.rb`:
21
+ # Usage
22
+
23
+ **APIcasso** is meant to be used as an engine, which means you don't need to configure any route or controller to build a working CRUD API. Sometimes you also need some customized controller actions or even a specific logic to access some of your application's resources. In that case you will use `Apicasso::CrudController` class to easily build only your own logic around the API abstraction.
24
+
25
+ ## Mounting engine into `config/routes.rb`
26
+
27
+ After installing it, you can mount a full-fledged CRUD JSON API just by attaching into some route. Usually you will have it under a scoped route like `/api/v1` or a subdomain. You can do that by adding this into your `config/routes.rb`:
23
28
  ```ruby
24
29
  # To mount your APIcasso routes under the path scope `/api/v1`
25
30
  mount Apicasso::Engine, at: "/api/v1"
@@ -39,47 +44,116 @@ Your API will reflect very similarly a `resources :resource` statement with the
39
44
  options '/:resource/' # A schema dump for the required `:resource`
40
45
  options '/:resource/:id/:nested/' # A schema dump for the required `:nested` relation from one of your application's `:resource`
41
46
  ```
47
+
42
48
  This means all your application's models will be exposed as `:resource` and it's relations will be exposed as `:nested`. It will enable you to CRUD and get schema metadata from your records.
43
49
 
44
- > But this is permissive as hell! I do not want to expose my entire application like this, haven't you thought about security?
50
+ ## Authorization/Authentication
51
+
52
+ > But exposing my models to de internet is permissive as hell! Haven't you thought about security?
45
53
 
46
- *Sure!* The API is being exposed using authentication through `Authorization: Token` [HTTP header authentication](http://tools.ietf.org/html/draft-hammer-http-token-auth-01). The API key objects are manageable through the `Apicasso::Key` model, which gets setup at install. When a new key is created a `.token` is generated using an [Universally Unique Identifier(RFC 4122)](https://tools.ietf.org/html/rfc4122).
54
+ *Sure!* The **APIcasso** suite is exposing your application using authentication through `Authorization: Token` [HTTP header authentication](http://tools.ietf.org/html/draft-hammer-http-token-auth-01). The API key objects are manageable through the `Apicasso::Key` model, which gets setup at install. When a new key is created a `.token` is generated using an [Universally Unique Identifier(RFC 4122)](https://tools.ietf.org/html/rfc4122).
47
55
 
48
- Your API is then exposed based on each `Apicasso::Key.scope` definition
56
+ Each `Apicasso::Key` object has a token attribute, which is used to define the authorized access identification.
57
+
58
+ Your Models are then exposed based on each `Apicasso::Key.scope` definition, which is a way to configure how much of your application each key can access. I.E.:
49
59
  ```ruby
50
60
  Apicasso::Key.create(scope:
51
61
  { manage:
52
62
  [{ order: true }, { user: { account_id: 1 } }],
53
63
  read:
54
- [{ account: { id: 1 } }]
64
+ [{ account: { manager_id: 1 } }]
55
65
  })
56
66
  ```
57
- This translates directly into which parts of your application is exposed to each APIcasso keys.
67
+ > The key from this example will have full access to all orders and to users with `account_id == 1`. It will have also read-only access to accounts with `id == 1`.
58
68
 
59
- The key from this example will have full access to all orders and to users with `account_id == 1`. It will have also read-only access to accounts with `id == 1`.
69
+ A scope configured like this translates directly into which kind of access each key has on all of your application's models. This kind of authorization is why one of the dependencies for this gem is [CanCanCan](https://github.com/CanCanCommunity/cancancan), which abstracts the scope field into your API access control.
60
70
 
61
- This saves you the trouble of having to setup each and every controller for each model. And even if your application really need it, just make your controllers inherit from `Apicasso::CrudController` and extend it's functionalities. This authorization feature is why one of the dependencies for this gem is [CanCanCan](https://github.com/CanCanCommunity/cancancan), that abstracts the scope field into authorization for your application's resources.
71
+ You can have two kind of access control:
72
+ * `true` - This will mean the key will have the declared clearance on **ALL** of this model's records
73
+ * `Hash` - This will build a condition to what records this key have. A scope as `{ read: [{ account: { manager_id: 1 } }] }` will have read access into accounts with `manager_id == 1`
62
74
 
63
- The `crud#index` and `crud#nested_index` actions are already equipped with pagination, ordering and filtering.
75
+ This saves you the trouble of having to setup every controller for each model. And even if your application really needs it, just make your controllers inherit from `Apicasso::CrudController` will extend it's functionalities, enabling the use of `@object` and `@resource` variables to access what is being resquested.
64
76
 
65
- - You can pass `params[:sort]` with field names preffixed with `+` or `-` to configure custom ordering per request. I.E.: `?sort=+updated_at,-name`
66
- - You can pass `params[:q]` using [ransack's search matchers](https://github.com/activerecord-hackery/ransack#search-matchers) to build a search query. I.E.: `?q[full_name_start]=Picasso`
67
- - You can pass `params[:page]` and `params[:per_page]` to build pagination options. I.E.: `?page=2&per_page=12`
77
+ ## Features on index actions
68
78
 
69
- ## Contributing
70
- Bug reports and pull requests are welcome on GitHub at https://github.com/ErvalhouS/APIcasso. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant code of conduct](http://contributor-covenant.org/).
79
+ The index actions present in the gem are already equipped with pagination, ordering, grouping, fieldset selection and filtering. This will save you a lot of trouble, adding some best-practices conventions into your application's API.
71
80
 
72
- ## License
73
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
81
+ ### Sort
74
82
 
75
- ## Code of conduct
76
- Everyone interacting in the APIcasso project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ErvalhouS/APIcasso/blob/master/CODE_OF_CONDUCT.md).
83
+ You can sort a collection query by using a URL parameter with field names preffixed with `+` or `-` to configure custom ordering per request.
84
+
85
+ To order a collection with ascending `updated_at` and descending `name` you can add the `sort` parameter with those fields as options, indicating which kind of ordination you want to give to each one:
86
+ ```
87
+ ?sort=+updated_at,-name
88
+ ```
89
+
90
+ ### Filtering/Search
91
+
92
+ APIcasso has [ransack's search matchers](https://github.com/activerecord-hackery/ransack#search-matchers) on it's index actions. This means you can dynamically build search queries with any of your resource's fields, this will be done by using a `?q` parameter which groups all your filtering options on your requests. If you wanted to search all your records and return only the ones with `full_name` starting with `Picasso` your query would look something like this:
93
+ ```
94
+ ?q[full_name_start]=Picasso
95
+ ```
96
+ To build complex search queries you can chain many parameter options or check [ransack's wiki](https://github.com/activerecord-hackery/ransack/wiki/) on how to adapt this feature into your project's needs.
97
+
98
+ ### Pagination
99
+
100
+ Automatic pagination is done in index actions, with the adittion of some metadata to help on the data consumption. You can pass page and per page parameters to build pagination options into your needs. And on requests that you need unpaginated collections, just pass a lower than zero `per_page`. Example of a pagination query string:
101
+ ```
102
+ ?page=2&per_page=12
103
+ ```
104
+ Your colletion will be build inside a JSON along with some metadata about it. The response structure is:
105
+ ```
106
+ { entries: [{Record1}, {Record2}, {Record3} ... {Record12}],
107
+ total: 1234,
108
+ total_pages: 102,
109
+ last_page: false,
110
+ previous_page: localhost:3000/my_records?page=1&per_page=12,
111
+ next_page: localhost:3000/my_records?page=3&per_page=12,
112
+ out_of_bounds: false,
113
+ offset: 12 }
114
+ ```
115
+
116
+ ### Fieldset selecting
117
+
118
+ Sometimes your data can grow large in some tables and you need to consumed only a limited set of data on a given frontend application. To avoid large requests and filtering a lot of unused data with JS you can restrict which fields you need on your API's reponse. This is done adding a `?select` parameter. Just pass the field names you desire splitted by `,`
119
+ Let's say you are building a user list with their name, e-mails and phones, to get only those fields your URL query would look something like:
120
+ ```
121
+ ?select=name,email,phone
122
+ ```
123
+ This will change the response to filter out the unwanted attributes.
124
+
125
+ ### Grouping operations
126
+
127
+ If you need to make grouping calculations, like:
128
+ * Counting of all records, or by one **optional** field presence
129
+ * Maximum value of one field
130
+ * Minimum value of one field
131
+ * Average value of one field
132
+ * Value sum of one field
133
+
134
+ Grouping is done by the combination of 3 parameters
135
+ ```
136
+ ?group[by]=a_field&group[calculate]=count&group[fields]=another_field
137
+ ```
138
+ Each of those attributes on the `?group` parameter represent an option of the query being made.
139
+ - `group[by]` - Represents which field will be the key for the grouping behavior
140
+ - `group[calculate]` - Which calculation will be sent in the response. Options are: `count`, `maximum`, `minimum`, `average`, `sum`
141
+ - `group[fields]` - Represents which field will be the base for the response calculation.
142
+
143
+ # Contributing
144
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ErvalhouS/APIcasso. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant code of conduct](http://contributor-covenant.org/). To find good places to start contributing, try looking into our issue list and our Codeclimate profile, or if you want to participate actively on what the core team is working on checkout our todo list:
77
145
 
78
146
  ## TODO
79
147
 
80
148
  - Abstract a configurable CORS approach, maybe using middleware.
81
149
  - Add gem options like: Token rotation, Alternative authentication methods
82
- - Add latest features into README: fieldset selection, grouping responses, infinite collections, auto-documentation
150
+ - Add latest auto-documentation feature into README
83
151
  - Rate limiting
84
152
  - Testing suite
85
153
  - Travis CI
154
+
155
+ # Code of conduct
156
+ Everyone interacting in the APIcasso project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ErvalhouS/APIcasso/blob/master/CODE_OF_CONDUCT.md).
157
+
158
+ # License
159
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -147,7 +147,7 @@ module Apicasso
147
147
  # or a grouped count of attributes
148
148
  def index_json
149
149
  if params[:group].present?
150
- accessible_records.group(params[:group].split(',')).count
150
+ accessible_records.group(params[:group][:by].split(',')).send(params[:group][:calculate], params[:group][:fields])
151
151
  else
152
152
  collection_response
153
153
  end
@@ -170,7 +170,7 @@ module Apicasso
170
170
 
171
171
  # Returns the collection checking if it needs pagination
172
172
  def collection_response
173
- if params[:per_page].to_i == -1
173
+ if params[:per_page].to_i < 0
174
174
  built_unpaginated
175
175
  else
176
176
  built_paginated
@@ -1,3 +1,3 @@
1
1
  module Apicasso
2
- VERSION = '0.2.7'
2
+ VERSION = '0.2.8'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apicasso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fernando Bellincanta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-27 00:00:00.000000000 Z
11
+ date: 2018-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cancancan