tupplur 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f2b8e48210120a1b238121391fc8552891670c81
4
+ data.tar.gz: 494017fd71c91f6fd6c936200df729a7adb201cd
5
+ SHA512:
6
+ metadata.gz: bf38291747032151dc4cf271d31b2fc560f123dc71b3b494006fb02d9a7fb3ff663b7d447a926ef4dddd9d9129dbdfc7f4f18b03c9d2d8735f11fdfd52dbd191
7
+ data.tar.gz: ed1ca103911a472313dfb7725c1dd54dc6d55165006a9ba3c71385b0b94051a05362d7eaacd471207ad37174d40fbe9ae1b86f0f81850ed66a0badb0b90b5a5f
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tupplur.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Robin Edman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,115 @@
1
+ # Tupplur
2
+
3
+ Tupplur extends your Mongoid 3.x models, allowing you to expose fields as readable
4
+ or writable from outside of your application. It includes a Rack REST adapter,
5
+ so that any Rack app can expose some or all of its' models as JSON easily
6
+ through a standard REST CRUD api.
7
+
8
+ This library is especially useful if you're building APIs for mobile or
9
+ Single Page Applications (maybe using Backbone, Spine, AngularJS or whichever
10
+ framework you prefer).
11
+
12
+ It's been designed to work well straight on top of Rack, or with lightweight
13
+ Rack-based frameworks such as Sinatra and Cuba. In fact, the REST adapter is
14
+ implemented as a Cuba application.
15
+
16
+ If you're using Rails you're probably better off with another solution at the
17
+ moment, since it might make more sense to use something that's more
18
+ integrated into the framework.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'tupplur'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install tupplur
33
+
34
+ If necessary in your application:
35
+ ```
36
+ require 'tupplur' # at the appropriate place.
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ Tupplur is divided into two parts: a model mixin and a Rack
42
+ application which acts like a REST endpoint.
43
+
44
+ ### REST endpoint Rack application
45
+ After Mongoid has been set up, mount the Rack app on a route of your choice.
46
+ The details of how you do this will depend on which framework you're using.
47
+ Each model gets its' own endpoint. So repeat this for all
48
+ models for which you want to provide a REST interface.
49
+
50
+ In Cuba:
51
+ ```ruby
52
+ on "/users" do
53
+ run Tupplur::RESTEndpoint.new(User)
54
+ end
55
+ ```
56
+
57
+ In Rack (in config.ru):
58
+ ```ruby
59
+ run Rack::URLMap.new("/" => YourApp.new,
60
+ "/users" => Tupplur::RESTEndpoint.new(User))
61
+ ```
62
+
63
+ If you're using Sinatra you might prefer the Rack method to mounting it
64
+ within Sinatra itself.
65
+
66
+ ### Model mixin
67
+ In your model:
68
+ ```ruby
69
+ class User
70
+ include Mongoid::Document
71
+ include Tupplur::ModelExtensions
72
+
73
+ # Define which operations you want to support.
74
+ rest_interface :create,
75
+ :read,
76
+ :update,
77
+ :delete
78
+
79
+ # Fields that are to be both readable and writable.
80
+ externally_accessible :name,
81
+ :email
82
+
83
+ # Read-only fields.
84
+ externally_readable :active
85
+
86
+ # Put your regular Mongoid model code here (or anywhere you want to as the ordering doesn't matter.)
87
+ field :name, type: String
88
+ field :email, type: String
89
+ field :password, type: String
90
+ field :active, type: Boolean, default: false
91
+ end
92
+ ```
93
+ This is where you define what parts of your model you want to
94
+ expose outside of your backend application. This is configured
95
+ in a similar manner to the way we choose to expose attributes on
96
+ objects in plain Ruby. There we use atr_reader and
97
+ attr_accessor. Tupplur includes the corresponding methods
98
+ externally_readable and externally_accessible.
99
+
100
+ You also define what REST operations a given model should
101
+ support using the rest_interface method. Just like externally_readable and
102
+ externally_writable it takes one or more symbols as arguments: :create, :read,
103
+ :update, :delete. The default is to not support any operation. You may
104
+ see this as whitelisting operations.
105
+
106
+ ### Examples
107
+ In the test directory you'll find an example app which uses the Cuba framework.
108
+
109
+ ## Contributing
110
+
111
+ 1. Fork it
112
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
113
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
114
+ 4. Push to the branch (`git push origin my-new-feature`)
115
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require "bundler/gem_tasks"
4
+
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = "test/*_test.rb"
8
+ end
@@ -0,0 +1,8 @@
1
+ require "tupplur/version"
2
+
3
+ require "tupplur/errors"
4
+ require "tupplur/model_extensions"
5
+ require "tupplur/rest_endpoint"
6
+
7
+ module Tupplur
8
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ module Tupplur
4
+ module Error
5
+ class RESTOperationNotAllowed < StandardError
6
+ def message
7
+ "The #{@operation} REST operation is not allowed."
8
+ end
9
+
10
+ def initialize(operation = 'unspecified')
11
+ @operation = operation
12
+ end
13
+ end
14
+
15
+ def self.log_exception(e)
16
+ puts "Exception: #{e}"
17
+ puts "Message: #{e.message}"
18
+ puts e.backtrace.join("\n")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: utf-8
2
+
3
+ require "active_support/all"
4
+
5
+ module Tupplur
6
+ module ModelExtensions
7
+ def self.included(base)
8
+ base.const_set(:EXTERNALLY_READABLE_FIELDS, ['_id'])
9
+ base.const_set(:EXTERNALLY_ACCESSIBLE_FIELDS, [])
10
+ base.const_set(:REST_INTERFACE, [])
11
+
12
+ base.send(:include, InstanceMethods)
13
+ base.send(:extend, ClassMethods)
14
+ end
15
+
16
+ module InstanceMethods
17
+ def as_external_document
18
+ doc = self.as_document
19
+
20
+ # note: id fix for client side libraries like Spine.js,
21
+ # who rely on an id attribute being present.
22
+ doc['id'] = doc['_id']
23
+
24
+ doc.slice(*readable_fields + ['id'])
25
+ end
26
+
27
+ def external_update!(document_as_hash)
28
+ allowed_fields = filter_accessible_fields(document_as_hash)
29
+ update_attributes!(allowed_fields)
30
+ end
31
+
32
+ # Does the model allow a certain REST operation?
33
+ # If no operation given: Does the model allow any REST operation at all?
34
+ def rest?(operation)
35
+ if operation
36
+ self.class.const_get(:REST_INTERFACE).include?(operation)
37
+ else
38
+ ! self.class.const_get(:REST_INTERFACE).empty?
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def filter_accessible_fields(hsh)
45
+ hsh.slice(*self.class.const_get(:EXTERNALLY_ACCESSIBLE_FIELDS).map(&:to_s))
46
+ end
47
+
48
+ def readable_fields
49
+ (self.class.const_get(:EXTERNALLY_ACCESSIBLE_FIELDS) + self.class.const_get(:EXTERNALLY_READABLE_FIELDS)).map(&:to_s)
50
+ end
51
+ end
52
+
53
+ module ClassMethods
54
+ # Does the model allow a certain REST operation?
55
+ # If no operation given: Does the model allow any REST operation at all?
56
+ def rest?(operation = nil)
57
+ if operation
58
+ const_get(:REST_INTERFACE).include?(operation)
59
+ else
60
+ ! const_get(:REST_INTERFACE).empty?
61
+ end
62
+ end
63
+
64
+ def rest_read(document_id = nil)
65
+ if document_id
66
+ rest_read_document(document_id)
67
+ else
68
+ rest_read_all
69
+ end
70
+ end
71
+
72
+ def rest_update(document_id, client_model)
73
+ raise Tupplur::Error::RESTOperationNotAllowed.new('update') unless rest?(:update)
74
+
75
+ find(document_id).external_update!(client_model)
76
+ end
77
+
78
+ def rest_delete(document_id)
79
+ raise Tupplur::Error::RESTOperationNotAllowed.new('delete') unless rest?(:delete)
80
+
81
+ find(document_id).delete
82
+ end
83
+
84
+ def rest_create(client_fields)
85
+ raise Tupplur::Error::RESTOperationNotAllowed.new('create') unless rest?(:create)
86
+
87
+ external_create!(client_fields)
88
+ end
89
+
90
+ def rest_read_document(document_id)
91
+ raise Tupplur::Error::RESTOperationNotAllowed.new('read') unless rest?(:read)
92
+
93
+ find(document_id).as_external_document
94
+ end
95
+
96
+ def rest_read_all
97
+ raise Tupplur::Error::RESTOperationNotAllowed.new('read') unless rest?(:read)
98
+
99
+ all.map { |m| m.as_external_document }
100
+ end
101
+
102
+ def external_create!(fields)
103
+ allowed_fields = filter_accessible_fields(fields)
104
+ create!(allowed_fields)
105
+ end
106
+
107
+ private
108
+
109
+ # Externally accessible fields and embedded documents.
110
+ def externally_accessible(*fields)
111
+ const_get(:EXTERNALLY_ACCESSIBLE_FIELDS).push(*fields)
112
+ end
113
+
114
+ # Externally readable fields and embedded documents.
115
+ def externally_readable(*fields)
116
+ const_get(:EXTERNALLY_READABLE_FIELDS).push(*fields)
117
+ end
118
+
119
+ # Used to define allowed REST operations (e.g. :read, :create, :update, :delete).
120
+ # Example usage:
121
+ # class MyModel
122
+ # include Mongoid::Document
123
+ # include Tupplur::ModelExtensions
124
+ #
125
+ # rest_interface :read, :update, :delete
126
+ #
127
+ def rest_interface(*operations)
128
+ const_get(:REST_INTERFACE).push(*operations)
129
+ end
130
+
131
+
132
+ def filter_accessible_fields(hsh)
133
+ hsh.slice(*const_get(:EXTERNALLY_ACCESSIBLE_FIELDS).map(&:to_s))
134
+ end
135
+
136
+ def readable_fields
137
+ (const_get(:EXTERNALLY_ACCESSIBLE_FIELDS) + const_get(:EXTERNALLY_READABLE_FIELDS)).map(&:to_s)
138
+ end
139
+
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+
3
+ require 'cuba'
4
+
5
+ module Tupplur
6
+ class RESTEndpoint < Cuba
7
+ attr_reader :model
8
+
9
+ def initialize(model)
10
+ @model = model
11
+ super() do
12
+ on ":id" do |document_id|
13
+ # REST read document
14
+ on get do
15
+ begin
16
+ send_json(@model.rest_read(document_id))
17
+ rescue Tupplur::Error::RESTOperationNotAllowed => e
18
+ res.status = 401
19
+ end
20
+ end
21
+
22
+ # REST update document
23
+ on put, param('data') do |client_model|
24
+ begin
25
+ send_json(@model.rest_update(document_id, client_model))
26
+ rescue Tupplur::Error::RESTOperationNotAllowed => e
27
+ res.status = 401
28
+ end
29
+ end
30
+
31
+ # REST delete document
32
+ on delete do
33
+ begin
34
+ send_json(@model.rest_delete(document_id))
35
+ rescue Tupplur::Error::RESTOperationNotAllowed => e
36
+ res.status = 401
37
+ end
38
+ end
39
+ end
40
+
41
+ # REST read whole collection
42
+ on get do
43
+ begin
44
+ send_json(@model.rest_read)
45
+ rescue Tupplur::Error::RESTOperationNotAllowed => e
46
+ res.status = 401
47
+ end
48
+ end
49
+
50
+ # REST create document
51
+ on post, param('data') do |client_fields|
52
+ begin
53
+ @model.rest_create(client_fields)
54
+ rescue Tupplur::Error::RESTOperationNotAllowed => e
55
+ res.status = 401
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def self.define
62
+ raise NotImplementedError, "Use .new and run the app instead."
63
+ end
64
+
65
+ private
66
+
67
+ def send_json(document)
68
+ res['Content-Type'] = 'application/json; charset=utf-8'
69
+ res.write(document.to_json)
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module Tupplur
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,126 @@
1
+ require_relative "test_helper"
2
+ require_relative "../lib/tupplur"
3
+
4
+ module RESTEndPointTest
5
+ class Base < TupplurTestCase
6
+ def tabula_rasa
7
+ User.delete_all
8
+ Secret.delete_all
9
+ end
10
+
11
+ def setup
12
+ tabula_rasa
13
+
14
+ User.create!(name: "Adam",
15
+ email: "adam@example.com",
16
+ password: "verysecurepassword")
17
+ User.create!(name: "Brenda",
18
+ email: "brenda@example.com",
19
+ password: "verysecurepassword")
20
+
21
+ Secret.create!(message: "Super secret info.")
22
+ end
23
+
24
+ def teardown
25
+ tabula_rasa
26
+ end
27
+ end
28
+
29
+ class GetTest < Base
30
+ test "get all documents returns only readable and accessible attributes" do
31
+ get "/users"
32
+
33
+ expected_response = [{name: "Adam", email: "adam@example.com", active: false},
34
+ {name: "Brenda", email: "brenda@example.com", active: false}]
35
+ response = ActiveSupport::JSON.decode(last_response.body).map(&:symbolize_keys!)
36
+
37
+ assert_equal(expected_response, response.map { |m| m.except(:_id, :id) })
38
+ end
39
+
40
+ test "get document with id returns only readable and accessible attributes" do
41
+ brenda_id = User.find_by(name: "Brenda")._id
42
+ get "/users/#{brenda_id}"
43
+
44
+ expected_response = {name: "Brenda", email: "brenda@example.com", active: false}
45
+ response = ActiveSupport::JSON.decode(last_response.body).symbolize_keys!
46
+
47
+ assert_equal(expected_response, response.except(:_id, :id))
48
+ end
49
+
50
+ test "cannot get resource that does not allow it" do
51
+ get "/secrets"
52
+
53
+ assert_equal(401, last_response.status)
54
+ end
55
+ end
56
+
57
+ class UpdateTest < Base
58
+ test "update accessible attribute" do
59
+ user = User.find_by(name: "Brenda")
60
+ put "/users/#{user._id}", {data: {name: "Brian"}}
61
+ user.reload
62
+
63
+ assert_equal("Brian", user.name)
64
+ end
65
+
66
+ test "cannot update readonly attribute" do
67
+ user = User.last
68
+ put "/users/#{user._id}", {data: {active: true}}
69
+ user.reload
70
+
71
+ refute(user.active)
72
+ end
73
+
74
+ test "cannot update internal attribute" do
75
+ user = User.last
76
+ put "users/#{user._id}", {data: {password: "anotherpassword"}}
77
+ user.reload
78
+
79
+ assert_equal("verysecurepassword", user.password)
80
+ end
81
+
82
+ test "cannot update resource that does not allow it" do
83
+ secret = Secret.first
84
+ put "secrets/#{secret._id}", {data: {message: "I say"}}
85
+ secret.reload
86
+
87
+ assert_equal("Super secret info.", secret.message)
88
+ end
89
+ end
90
+
91
+ class DeleteTest < Base
92
+ test "delete resource" do
93
+ user_id = User.first._id
94
+ delete "/users/#{user_id}"
95
+
96
+ refute(User.find(user_id))
97
+ end
98
+
99
+ test "cannot delete resource that does not allow it" do
100
+ secret_id = Secret.first._id
101
+ delete "/secrets/#{secret_id}"
102
+
103
+ assert(Secret.find(secret_id))
104
+ end
105
+ end
106
+
107
+ class CreateTest < Base
108
+ test "create resource" do
109
+ post "/users", {data: {name: "Charles", email: "charles@example.com"}}
110
+
111
+ assert(User.find_by(name: "Charles"))
112
+ end
113
+
114
+ test "cannot set readable attributes" do
115
+ post "/users", {data: {name: "Roger", active: true}}
116
+
117
+ refute(User.find_by(name: "Roger").active)
118
+ end
119
+
120
+ test "cannot create resource that does not allow it" do
121
+ post "/secrets", {data: {message: "Hey"}}
122
+
123
+ refute(Secret.find_by(message: "Hey"))
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,20 @@
1
+ require "mongoid"
2
+ require_relative "helpers"
3
+
4
+ cd_to_here
5
+ Mongoid.load!("./mongoid.yml")
6
+
7
+ require_relative "../../lib/tupplur"
8
+ require_relative "models/user"
9
+ require_relative "models/secret"
10
+
11
+ Cuba.define do
12
+ on "users" do
13
+ run Tupplur::RESTEndpoint.new(User)
14
+ end
15
+
16
+ on "secrets" do
17
+ run Tupplur::RESTEndpoint.new(Secret)
18
+ end
19
+ end
20
+
@@ -0,0 +1,4 @@
1
+ #encoding: utf-8
2
+ require './app'
3
+
4
+ run Cuba
@@ -0,0 +1,4 @@
1
+ def cd_to_here
2
+ root_directory = File.expand_path(File.dirname(__FILE__))
3
+ Dir.chdir(root_directory)
4
+ end
@@ -0,0 +1,7 @@
1
+ class Secret
2
+ include Mongoid::Document
3
+ include Tupplur::ModelExtensions
4
+
5
+ field :message, type: String
6
+ end
7
+
@@ -0,0 +1,20 @@
1
+ class User
2
+ include Mongoid::Document
3
+ include Tupplur::ModelExtensions
4
+
5
+ rest_interface :create,
6
+ :read,
7
+ :update,
8
+ :delete
9
+
10
+ externally_accessible :name,
11
+ :email
12
+
13
+ externally_readable :active
14
+
15
+ field :name, type: String
16
+ field :email, type: String
17
+ field :password, type: String
18
+ field :active, type: Boolean, default: false
19
+ end
20
+
@@ -0,0 +1,20 @@
1
+ # Tell Mongoid which environment this configuration is for.
2
+ development:
3
+ # This starts the session configuration settings. You may have as
4
+ # many sessions as you like, but you must have at least 1 named
5
+ # 'default'.
6
+ sessions:
7
+ # Define the default session.
8
+ default:
9
+ # A session can have any number of hosts. Usually 1 for a single
10
+ # server setup, and at least 3 for a replica set. Hosts must be
11
+ # an array of host:port pairs. This session is single server.
12
+ hosts:
13
+ - 127.0.0.1:27017
14
+ # Define the default database name.
15
+ database: tupplurtest
16
+ # Set username and password if you need to.
17
+ # username: user
18
+ # password: password
19
+ options:
20
+ raise_not_found_error: false
@@ -0,0 +1,14 @@
1
+ require "turn/autorun"
2
+ require "active_support/all"
3
+ require "rack/test"
4
+ require_relative "test_app/app"
5
+
6
+ Turn.config.natural = true
7
+
8
+ class TupplurTestCase < ActiveSupport::TestCase
9
+ include Rack::Test::Methods
10
+
11
+ def app
12
+ Cuba
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ #lib = File.expand_path('../lib', __FILE__)
3
+ #$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ # require 'tupplur/version'
5
+ require File.expand_path('../lib/tupplur/version', __FILE__)
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "tupplur"
9
+ spec.version = Tupplur::VERSION
10
+ spec.authors = ["Robin Edman"]
11
+ spec.email = ["robin.edman@gmail.com"]
12
+ spec.description = %q{Tupplur extends Mongoid, allowing fields to be exposed as readable or writable from outside of your application.}
13
+ spec.summary = spec.description
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "turn", "~> 0.9"
25
+ spec.add_development_dependency "activesupport", "~> 3.0"
26
+ spec.add_development_dependency "rack-test", "~> 0.6.2"
27
+ spec.add_development_dependency "virtus", "~> 1.0"
28
+ spec.add_development_dependency "mongoid", "~> 3.0"
29
+
30
+ spec.add_runtime_dependency "cuba", "~>3.1.0"
31
+ # Mongoid is an implicitly assumed dependency. So is ActiveSupport.
32
+ # We don't specify those versions since we don't want to risk conflicts with
33
+ # Mongoid.
34
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tupplur
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robin Edman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: turn
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '0.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack-test
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.6.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.6.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: virtus
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mongoid
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '3.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '3.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: cuba
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 3.1.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 3.1.0
125
+ description: Tupplur extends Mongoid, allowing fields to be exposed as readable or
126
+ writable from outside of your application.
127
+ email:
128
+ - robin.edman@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - Gemfile
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - lib/tupplur.rb
139
+ - lib/tupplur/errors.rb
140
+ - lib/tupplur/model_extensions.rb
141
+ - lib/tupplur/rest_endpoint.rb
142
+ - lib/tupplur/version.rb
143
+ - test/rest_endpoint_test.rb
144
+ - test/test_app/app.rb
145
+ - test/test_app/config.ru
146
+ - test/test_app/helpers.rb
147
+ - test/test_app/models/secret.rb
148
+ - test/test_app/models/user.rb
149
+ - test/test_app/mongoid.yml
150
+ - test/test_helper.rb
151
+ - tupplur.gemspec
152
+ homepage: ''
153
+ licenses:
154
+ - MIT
155
+ metadata: {}
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - '>='
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubyforge_project:
172
+ rubygems_version: 2.0.3
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Tupplur extends Mongoid, allowing fields to be exposed as readable or writable
176
+ from outside of your application.
177
+ test_files:
178
+ - test/rest_endpoint_test.rb
179
+ - test/test_app/app.rb
180
+ - test/test_app/config.ru
181
+ - test/test_app/helpers.rb
182
+ - test/test_app/models/secret.rb
183
+ - test/test_app/models/user.rb
184
+ - test/test_app/mongoid.yml
185
+ - test/test_helper.rb