natural_resource 0.1.2.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +39 -0
- data/Rakefile +23 -0
- data/lib/generators/natural/install/USAGE +9 -0
- data/lib/generators/natural/install/install_generator.rb +9 -0
- data/lib/generators/natural/install/templates/application_policy.rb +24 -0
- data/lib/generators/natural/resource/USAGE +17 -0
- data/lib/generators/natural/resource/resource_generator.rb +29 -0
- data/lib/generators/natural.rb +3 -0
- data/lib/generators/rspec/policy_generator.rb +11 -0
- data/lib/generators/rspec/templates/policy_spec.rb +28 -0
- data/lib/natural_resource/controller.rb +93 -0
- data/lib/natural_resource/core_ext.rb +5 -0
- data/lib/natural_resource/policy.rb +95 -0
- data/lib/natural_resource/policy_preconditions.rb +22 -0
- data/lib/natural_resource/railtie.rb +7 -0
- data/lib/natural_resource/version.rb +3 -0
- data/lib/natural_resource.rb +9 -0
- data/lib/tasks/natural_resource_tasks.rake +4 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 471019cc52094c5009a4aca80d8a7410f92194f9
|
4
|
+
data.tar.gz: dffd007f8763759da6b7449f7f527f49b32dac6f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 14f3e5cf9c857ee1a5dd91e0720924533fa91ff92b97715d22419901555d6833e9953b8174f2f4dc45648113c53973e82ddb17a5fe26755f134688f18ee2f1f0
|
7
|
+
data.tar.gz: 2ec45e30ef95b9699defecf3b5014bcf04d8ccd3ccba095ef9aaeb41ea2ef6fa26332a54d285dace3aa14f43cd2be8108279c603933a2f3a457900036919ddae
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Natural Resource
|
2
|
+
|
3
|
+
<img src="http://www.terracoding.com/assets/images/natural-resource.png" alt="Logo" height="200px"/>
|
4
|
+
|
5
|
+
Natural Resource is a small but opinionated framework built ontop of some of our favourite gems. It is designed to speed up CRUD related activities whilst still maintaining sensible standards (e.g. Admin Panel, expandable principles for an API). It utilises [Pundit](https://github.com/elabs/pundit) for authorisation and [Ransack](https://github.com/activerecord-hackery/ransack) for searching and filtering.
|
6
|
+
|
7
|
+
Sponsored by [Terracoding](http://terracoding.com)
|
8
|
+
|
9
|
+
# Getting Started
|
10
|
+
|
11
|
+
Simply install the gem
|
12
|
+
|
13
|
+
``` ruby
|
14
|
+
gem 'natural_resource'
|
15
|
+
```
|
16
|
+
Setup the Base Policy:
|
17
|
+
``` sh
|
18
|
+
rails g natural:install
|
19
|
+
```
|
20
|
+
|
21
|
+
Then generate controllers/policies as required:
|
22
|
+
|
23
|
+
``` sh
|
24
|
+
rails g natural:resource controller_name optional_model_name
|
25
|
+
```
|
26
|
+
|
27
|
+
The overall codebase for NaturalResource is very small and the bulk of the functionality can be found in `lib/natural_resource/controller.rb`, it's all relatively simple ruby code designed to be expanded on top for any custom functionality. To understand how Pundit works I suggest visiting their repository and going through the basics.
|
28
|
+
|
29
|
+
# Contributing
|
30
|
+
|
31
|
+
All contributions are welcome, simply fork the project and make a Pull Request upstream.
|
32
|
+
|
33
|
+
# Testing
|
34
|
+
|
35
|
+
Simply run the `rspec` test suite from the `spec/dummy` folder.
|
36
|
+
|
37
|
+
# License
|
38
|
+
|
39
|
+
Licensed under the MIT license, see the separate MIT-LICENSE.txt file.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'NaturalResource'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class ApplicationPolicy < NaturalResource::Policy
|
2
|
+
class Scope < Scope
|
3
|
+
# It is recommended to use per-role scopes for Users # simply extend the
|
4
|
+
# resolve method with conditions for each "role" and the name of the scope
|
5
|
+
# they should call.
|
6
|
+
def resolve
|
7
|
+
if !user.is_a? User
|
8
|
+
anon_user_scope
|
9
|
+
else
|
10
|
+
standard_user_scope
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def standard_user_scope
|
15
|
+
scope
|
16
|
+
# scope.where(user: user) # e.g. only show resources that belong to that user
|
17
|
+
end
|
18
|
+
|
19
|
+
def anon_user_scope
|
20
|
+
scope
|
21
|
+
# scope.public # e.g. only display public data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Description:
|
2
|
+
Generator to generate a natural_resource controller and it's dependencies.
|
3
|
+
Can be called via controller_name and with or without the model (inferred without).
|
4
|
+
|
5
|
+
Example:
|
6
|
+
rails generate natural:resource controller_name policy_model_name
|
7
|
+
|
8
|
+
This will create:
|
9
|
+
app/controllers/#{controller_name}.rb
|
10
|
+
app/policies/#{model_name}_policy.rb
|
11
|
+
|
12
|
+
rails generate natural:resource controller_name
|
13
|
+
|
14
|
+
This will create:
|
15
|
+
app/controllers/#{controller_name}.rb
|
16
|
+
app/policies/#{controller_name.singularize}_policy.rb
|
17
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'pundit'
|
2
|
+
require 'rails/generators'
|
3
|
+
|
4
|
+
class Natural::ResourceGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
argument :model_name, type: :string, default: ''
|
7
|
+
|
8
|
+
def generate_dependencies
|
9
|
+
@model_name = name if @model_name.blank?
|
10
|
+
invoke 'pundit:policy', [@model_name.singularize]
|
11
|
+
invoke 'controller', [name.pluralize]
|
12
|
+
|
13
|
+
c_sentinel = '< ApplicationController'
|
14
|
+
|
15
|
+
# Add resource reference to generated controller
|
16
|
+
in_root do
|
17
|
+
gsub_file "app/controllers/#{name.pluralize}_controller.rb", /(#{Regexp.escape(c_sentinel)})/mi do |match|
|
18
|
+
"#{match}\n resource :#{@model_name.pluralize.downcase}\n\n def resource_params\n params.require(:#{@model_name.singularize}).permit()\n end\n"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add note to generated Pundit policy
|
23
|
+
in_root do
|
24
|
+
gsub_file "app/policies/#{@model_name.singularize}_policy.rb", /(def resolve\n\s+scope\n\s+end)/mi do |match|
|
25
|
+
'# See ApplicationPolicy.rb to see how a scope is defined and used'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Generators
|
3
|
+
class PolicyGenerator < ::Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
|
5
|
+
|
6
|
+
def create_policy_spec
|
7
|
+
template 'policy_spec.rb', File.join('spec/policies', class_path, "#{file_name}_policy_spec.rb")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require '<%= File.exists?('spec/rails_helper.rb') ? 'rails_helper' : 'spec_helper' %>'
|
2
|
+
|
3
|
+
describe <%= class_name %>Policy do
|
4
|
+
let(:model) { } # <%= class_name %>.new
|
5
|
+
subject { described_class.new(user, model) }
|
6
|
+
|
7
|
+
context 'when a standard user' do
|
8
|
+
let(:user) { User.new }
|
9
|
+
|
10
|
+
# it { is_expected.to permit_auth(:action) }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when an anon user' do
|
14
|
+
let(:user) { User.new }
|
15
|
+
|
16
|
+
# it { is_expected.to_not permit_auth(:action) }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe <%= class_name %>Policy::Scope do
|
20
|
+
context 'when a standard user' do
|
21
|
+
let(:user) { } # User.new
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when a anon user' do
|
25
|
+
let(:user) { nil }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'action_controller'
|
3
|
+
require 'pundit'
|
4
|
+
require 'ransack'
|
5
|
+
require 'will_paginate'
|
6
|
+
|
7
|
+
module NaturalResource
|
8
|
+
module Controller
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
include Pundit
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
def resource(resource_name)
|
14
|
+
after_action :verify_authorized, except: :index
|
15
|
+
after_action :verify_policy_scoped
|
16
|
+
|
17
|
+
helper_method :current_context, :query, :resource_class, :resource, :resources
|
18
|
+
|
19
|
+
rescue_from ActiveRecord::RecordInvalid, with: :handle_invalid_create_or_update
|
20
|
+
|
21
|
+
# GET /:controller_name/new
|
22
|
+
define_method :new do; end
|
23
|
+
|
24
|
+
# GET /:controller_name/edit
|
25
|
+
define_method :edit do; end
|
26
|
+
|
27
|
+
# GET /:controller_name
|
28
|
+
define_method :index do; end
|
29
|
+
|
30
|
+
# POST /:controller_name
|
31
|
+
define_method :create do
|
32
|
+
resource.update! resource_params
|
33
|
+
redirect_to success_path, {notice: "#{resource} was created."}
|
34
|
+
end
|
35
|
+
|
36
|
+
# PUT /:controller_name/:id
|
37
|
+
define_method :update do
|
38
|
+
resource.tap { |r| r.update! resource_params }.touch
|
39
|
+
redirect_to success_path, {notice: "#{resource} was updated."}
|
40
|
+
end
|
41
|
+
|
42
|
+
# DELETE /:controller_name/:id
|
43
|
+
define_method :destroy do
|
44
|
+
resource.destroy
|
45
|
+
redirect_to success_path, {notice: "#{resource} was deleted."}
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
define_method :current_context do; end
|
51
|
+
|
52
|
+
# Resource allocation methods
|
53
|
+
define_method :query do
|
54
|
+
@query ||= policy_scope(resource_scope).ransack(params[:q])
|
55
|
+
end
|
56
|
+
|
57
|
+
define_method :resource_class do
|
58
|
+
resource_name.to_s.singularize.camelcase.constantize
|
59
|
+
end
|
60
|
+
|
61
|
+
define_method :resource do
|
62
|
+
@resource ||= if ['new', 'create'].include?(action_name)
|
63
|
+
policy_scope(resource_scope).new
|
64
|
+
else
|
65
|
+
policy_scope(resource_scope).find(params[:id])
|
66
|
+
end.tap(&method(:authorize))
|
67
|
+
end
|
68
|
+
|
69
|
+
define_method :resources do
|
70
|
+
@resources ||= query.result.paginate(page: params[:page])
|
71
|
+
end
|
72
|
+
|
73
|
+
define_method :resource_scope do
|
74
|
+
resource_class
|
75
|
+
end
|
76
|
+
|
77
|
+
define_method :success_path do
|
78
|
+
url_for(action: :index)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def handle_invalid_create_or_update
|
84
|
+
case action_name
|
85
|
+
when 'create' then render :new
|
86
|
+
when 'update' then render :edit
|
87
|
+
else raise NotImplementedError
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
ActionController::Base.send :include, NaturalResource::Controller
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'natural_resource/policy_preconditions'
|
3
|
+
|
4
|
+
# Starting block for ApplicationPolicy, set up for easy overriding
|
5
|
+
module NaturalResource
|
6
|
+
class Policy
|
7
|
+
include NaturalResource::PolicyPreconditions
|
8
|
+
attr_reader :user, :record
|
9
|
+
|
10
|
+
def initialize(user, record)
|
11
|
+
@user = user
|
12
|
+
@record = record
|
13
|
+
@errors = Hash.new { |h,k| h[k]= Set.new([]) }
|
14
|
+
@failure_status = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_status
|
18
|
+
@failure_status.presence || :unauthorized
|
19
|
+
end
|
20
|
+
|
21
|
+
def errors
|
22
|
+
if @errors.keys.empty?
|
23
|
+
{user: ['does not have permission to perform this action']}
|
24
|
+
else
|
25
|
+
@errors
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def index?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def show?
|
34
|
+
scope.where(id: record.id).exists?
|
35
|
+
end
|
36
|
+
|
37
|
+
def create?
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def new?
|
42
|
+
create?
|
43
|
+
end
|
44
|
+
|
45
|
+
def update?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
def edit?
|
50
|
+
update?
|
51
|
+
end
|
52
|
+
|
53
|
+
def destroy?
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
57
|
+
def own_record?
|
58
|
+
user && record.user == user
|
59
|
+
end
|
60
|
+
|
61
|
+
def anon?
|
62
|
+
user.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
def scope
|
66
|
+
Pundit.policy_scope!(user, record.class)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Base Scope class to infer/scope what a user should see
|
70
|
+
class Scope
|
71
|
+
attr_reader :user, :scope
|
72
|
+
|
73
|
+
def initialize(user, scope)
|
74
|
+
@user = user
|
75
|
+
@scope = scope
|
76
|
+
end
|
77
|
+
|
78
|
+
def resolve
|
79
|
+
if !user.is_a?(User)
|
80
|
+
anon_user_scope
|
81
|
+
else
|
82
|
+
standard_user_scope
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def standard_user_scope
|
87
|
+
raise NotImplementedError, [self.class.name, __method__].join('#')
|
88
|
+
end
|
89
|
+
|
90
|
+
def anon_user_scope
|
91
|
+
raise NotImplementedError, [self.class.name, __method__].join('#')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Encapsulation/Separation of precondition logic for Pundit policies
|
2
|
+
module NaturalResource::PolicyPreconditions
|
3
|
+
private
|
4
|
+
|
5
|
+
def precondition(record, precondition=nil, identifier: nil, message: nil)
|
6
|
+
precondition_met = if block_given?
|
7
|
+
yield
|
8
|
+
else
|
9
|
+
record.public_send(precondition)
|
10
|
+
end
|
11
|
+
|
12
|
+
identifier ||= record.class.to_s.underscore
|
13
|
+
message ||= "is not #{precondition.to_s.gsub(/\?*$/, '')}"
|
14
|
+
|
15
|
+
unless precondition_met
|
16
|
+
@failure_status ||= :precondition_failed
|
17
|
+
@errors[identifier] << message
|
18
|
+
end
|
19
|
+
|
20
|
+
precondition_met
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'natural_resource/version'
|
2
|
+
require 'natural_resource/controller'
|
3
|
+
require 'natural_resource/policy'
|
4
|
+
require 'generators/natural'
|
5
|
+
require 'generators/natural/resource/resource_generator'
|
6
|
+
require 'generators/natural/install/install_generator'
|
7
|
+
|
8
|
+
module NaturalResource
|
9
|
+
end
|
metadata
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: natural_resource
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert White
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pundit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ransack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: will_paginate
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :runtime
|
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: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.3'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.4'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.4'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: haml-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- robert@terracoding.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- README.md
|
119
|
+
- Rakefile
|
120
|
+
- lib/generators/natural.rb
|
121
|
+
- lib/generators/natural/install/USAGE
|
122
|
+
- lib/generators/natural/install/install_generator.rb
|
123
|
+
- lib/generators/natural/install/templates/application_policy.rb
|
124
|
+
- lib/generators/natural/resource/USAGE
|
125
|
+
- lib/generators/natural/resource/resource_generator.rb
|
126
|
+
- lib/generators/rspec/policy_generator.rb
|
127
|
+
- lib/generators/rspec/templates/policy_spec.rb
|
128
|
+
- lib/natural_resource.rb
|
129
|
+
- lib/natural_resource/controller.rb
|
130
|
+
- lib/natural_resource/core_ext.rb
|
131
|
+
- lib/natural_resource/policy.rb
|
132
|
+
- lib/natural_resource/policy_preconditions.rb
|
133
|
+
- lib/natural_resource/railtie.rb
|
134
|
+
- lib/natural_resource/version.rb
|
135
|
+
- lib/tasks/natural_resource_tasks.rake
|
136
|
+
homepage: http://www.github.com/haar/natural_resource
|
137
|
+
licenses:
|
138
|
+
- MIT
|
139
|
+
metadata: {}
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 1.3.1
|
154
|
+
requirements: []
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 2.4.5.1
|
157
|
+
signing_key:
|
158
|
+
specification_version: 4
|
159
|
+
summary: Small Rails Framework to speed up CRUD controllers
|
160
|
+
test_files: []
|