databound 2.0.1 → 3.0.0

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: cba727e2ab9d8e8ae6f7493aad47e28cac352592
4
- data.tar.gz: d6791304413633e2abdaee1b737a77b1a9dfaea3
3
+ metadata.gz: c17ea9293869f528bb57b8f815ade20dfe629904
4
+ data.tar.gz: bff389e7ba5502edb650bede3fe7b78acda3a88e
5
5
  SHA512:
6
- metadata.gz: 63143f0d64ad79f6563425cd35b7a73a4e01d0c3b40b369476c34f77c52d54c64a2793f57b68f39970c8031f6706df4fdb038aacfd29ff3fbccc58cb6f0d008a
7
- data.tar.gz: b6cdeca9c47ab71d89368ed45f2c10ee2f3eb715f693b3255264083982d25d9415c9fe1ee3723ae4ef947a5fb1ca81ab0cc682314d7c0ad4d953deb8c15e60e0
6
+ metadata.gz: ac22d42e131278f67c5fa25dbcfeeb3f8e8300c1596d47ddf5493cb19daab2a9cc3cd05519ed5a8b780ba703db670bffaea15144ac66ab364d9807bf6553eeb4
7
+ data.tar.gz: 2c4d73542e0f1195e9e1ebc0aebeb6cd366c2f77b526e347d160225694b4c03b15b4882ef5cb21b4c799c70fed73122996217084725fe44bdce56eabfa26631a
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ![Databound](https://cloud.githubusercontent.com/assets/1877286/4743542/df89dcec-5a28-11e4-9114-6f383fe269cb.png)
8
8
 
9
- Exposes Ruby on Rails database to the Javascript side.
9
+ Provides Javascript a simple CRUD API to the Ruby on Rails backend.
10
10
 
11
11
  This repo is for Ruby on Rails backend part of Databound.
12
12
 
@@ -24,11 +24,11 @@ This repo is for Ruby on Rails backend part of Databound.
24
24
  });
25
25
 
26
26
  User.find(15).then(function(user) {
27
- print('User no. 15: ' + user.name);
27
+ alert('User no. 15: ' + user.name);
28
28
  });
29
29
 
30
30
  User.create({ name: 'Peter' }).then(function(user) {
31
- print('I am ' + user.name + ' from database');
31
+ alert('I am ' + user.name + ' from database');
32
32
  });
33
33
  ```
34
34
 
data/databound.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Databound::VERSION
9
9
  spec.authors = ['Domas Bitvinskas']
10
10
  spec.email = ['domas.bitvinskas@me.com']
11
- spec.summary = %q{Databound exposes Ruby on Rails database to the Javascript side}
12
- spec.description = %q{Works with ActiveRecord and Mongoid out of the box}
13
- spec.homepage = 'https://github.com/Nedomas/databound'
11
+ spec.summary = %q{Provides Javascript a simple API to the Ruby on Rails CRUD}
12
+ spec.description = %q{It lets you use methods like create, update, destroy in the front-end while handling all the setup and providing basic security out of the box.}
13
+ spec.homepage = 'http://databound.me'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
data/lib/databound.rb CHANGED
@@ -2,13 +2,13 @@ require 'databound/extensions'
2
2
  require 'databound/version'
3
3
  require 'databound/data'
4
4
  require 'databound/manager'
5
- require 'databound/utils'
5
+ require 'databound/config'
6
+ require 'databound/controller'
6
7
  require 'databound/rails/routes'
7
8
 
8
9
  module Databound
9
10
  def self.included(base)
10
11
  base.send(:before_action, :init_crud, only: %i(where create update destroy))
11
- base.extend(ClassMethods)
12
12
  end
13
13
 
14
14
  def where
@@ -66,14 +66,6 @@ module Databound
66
66
  serializer.new(record).attributes[:id]
67
67
  end
68
68
 
69
- def model
70
- raise 'Override model method to specify a model to be used in CRUD'
71
- end
72
-
73
- def permitted_columns
74
- []
75
- end
76
-
77
69
  def init_crud
78
70
  @crud = Databound::Manager.new(self)
79
71
  end
@@ -81,23 +73,4 @@ module Databound
81
73
  def scoped_records
82
74
  @crud.find_scoped_records(only_extra_scopes: true)
83
75
  end
84
-
85
- module ClassMethods
86
- attr_reader :dsls
87
- attr_reader :stricts
88
- attr_reader :permit_update_destroy
89
-
90
- def dsl(name, value, strict: true, &block)
91
- @stricts ||= {}
92
- @stricts[name.to_s] = strict
93
-
94
- @dsls ||= {}
95
- @dsls[name.to_s] ||= {}
96
- @dsls[name.to_s][value.to_s] = block
97
- end
98
-
99
- def permit_update_destroy?(&block)
100
- @permit_update_destroy = block
101
- end
102
- end
103
76
  end
@@ -0,0 +1,38 @@
1
+ module Databound
2
+ class Config
3
+ def initialize(block, model)
4
+ @model = model
5
+ @permit = {}
6
+ instance_eval(&block)
7
+ end
8
+
9
+ def columns(*specified_columns)
10
+ @columns = specified_columns
11
+ end
12
+
13
+ def model(specified_model)
14
+ raise "Model '#{@model}' already specified" if @model
15
+
16
+ @model = specified_model
17
+ end
18
+
19
+ def permit(*methods, &block)
20
+ methods.each do |method|
21
+ @permit[method] = block
22
+ end
23
+ end
24
+
25
+ def dsl(name, value, strict: true, &block)
26
+ @stricts ||= {}
27
+ @stricts[name] = strict
28
+
29
+ @dsls ||= {}
30
+ @dsls[name] ||= {}
31
+ @dsls[name][value.to_s] = block
32
+ end
33
+
34
+ def read(name)
35
+ instance_variable_get("@#{name}")
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,63 @@
1
+ module Databound
2
+ class Controller
3
+ class << self
4
+ def add_application_controller_configs!
5
+ def ApplicationController.databound(model = nil, &block)
6
+ include Databound
7
+
8
+ send(:define_method, :databound_config) do
9
+ Databound::Config.new(block, model)
10
+ end
11
+ end
12
+ end
13
+
14
+ def find_or_create(name, resource, opts)
15
+ find(name) || create(name, resource, opts)
16
+ end
17
+
18
+ def create(name, resource, opts)
19
+ opts ||= {}
20
+ Object.const_set(as_constant_string(name), new(resource, opts))
21
+ end
22
+
23
+ def new(resource, opts)
24
+ model_name = opts.delete(:model) || fallback_model(resource)
25
+
26
+ result = Class.new(ApplicationController)
27
+ result.send(:databound) do
28
+ model model_name
29
+
30
+ opts.each do |key, value|
31
+ send(key, *value)
32
+ end
33
+ end
34
+
35
+ result
36
+ end
37
+
38
+ def fallback_model(resource)
39
+ resource.to_s.classify.underscore.to_sym
40
+ end
41
+
42
+ def exists?(path)
43
+ name_error = false
44
+
45
+ begin
46
+ as_constant_string(path).constantize
47
+ rescue NameError
48
+ name_error = true
49
+ end
50
+
51
+ !name_error
52
+ end
53
+
54
+ def find(path)
55
+ as_constant_string(path).constantize if exists?(path)
56
+ end
57
+
58
+ def as_constant_string(name)
59
+ "#{name.camelize}Controller"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,16 +1,16 @@
1
1
  module Databound
2
2
  class Data
3
- def initialize(controller, json)
3
+ def initialize(controller, json, model)
4
4
  return unless json
5
5
 
6
6
  @controller = controller
7
- @params = JSON.parse(json) if json.is_a?(String)
8
- @params = json if json.is_a?(Hash)
7
+ @json = json
9
8
  @data = interpolated_params
9
+ @model = model
10
10
  end
11
11
 
12
- def records(model)
13
- model.where(@data)
12
+ def records
13
+ @model.where(@data)
14
14
  end
15
15
 
16
16
  def to_h
@@ -19,21 +19,27 @@ module Databound
19
19
 
20
20
  private
21
21
 
22
+ def params
23
+ @params ||= JSON.parse(@json) if @json.is_a?(String)
24
+ @params ||= @json if @json.is_a?(Hash)
25
+ OpenStruct.new(@params)
26
+ end
27
+
22
28
  def interpolated_params
23
- @params.each_with_object({}) do |(key, val), obj|
29
+ params.to_h.each_with_object({}) do |(key, val), obj|
24
30
  check_strict!(key, val)
25
31
 
26
32
  block = dsl_block(key, val)
27
- obj[key] = block ? @controller.instance_exec(@params.to_options, &block) : val
33
+ obj[key] = block ? @controller.instance_exec(params, &block) : val
28
34
  end
29
35
  end
30
36
 
31
37
  def dsl_block(key, val)
32
- swallow_nil { dsl_key(key)[val] }
38
+ swallow_nil { dsl_key(key)[val.to_s] }
33
39
  end
34
40
 
35
41
  def dsl_key(key)
36
- swallow_nil { @controller.class.dsls[key] }
42
+ swallow_nil { @controller.databound_config.read(:dsls)[key] }
37
43
  end
38
44
 
39
45
  def check_strict!(key, val)
@@ -45,7 +51,7 @@ module Databound
45
51
  end
46
52
 
47
53
  def strict?(key)
48
- swallow_nil { @controller.class.stricts[key] }
54
+ swallow_nil { @controller.databound_config.read(:stricts)[key] }
49
55
  end
50
56
  end
51
57
  end
@@ -1,5 +1,3 @@
1
- # module Databound
2
- # end
3
1
  def swallow_nil
4
2
  yield
5
3
  rescue NoMethodError
@@ -3,67 +3,78 @@ module Databound
3
3
  class Manager
4
4
  def initialize(controller)
5
5
  @controller = controller
6
- @model = @controller.send(:model)
7
6
 
8
- @scope = Databound::Data.new(controller, scope_js)
9
- @data = Databound::Data.new(controller, data_js).to_h
7
+ @scope = Databound::Data.new(@controller, scope_js, model)
8
+ @data = Databound::Data.new(@controller, data_js, model)
10
9
 
11
10
  @extra_where_scopes = JSON.parse(extra_where_scopes_js).map do |extra_scope|
12
- Databound::Data.new(controller, extra_scope)
11
+ Databound::Data.new(@controller, extra_scope, model)
13
12
  end
14
13
  end
15
14
 
16
15
  def find_scoped_records(only_extra_scopes: false)
17
- records = []
18
- records << @scope.records(@model)
16
+ records = model.where(or_query(@scope, *@extra_where_scopes))
17
+ records = filter_by_params!(records) unless only_extra_scopes
19
18
 
20
- @extra_where_scopes.each do |extra_scope|
21
- records << extra_scope.records(@model)
22
- end
23
-
24
- if only_extra_scopes
25
- records.flatten
26
- else
27
- records.map { |record| record.where(@data) }.flatten
28
- end
19
+ check_permit!(:read, params, records)
20
+ records
29
21
  end
30
22
 
31
23
  def create_from_data
32
- check_params!
33
- @model.where(@scope.to_h).create(@data)
24
+ check_params!(:create)
25
+ record = model.new(params.to_h)
26
+ check_permit!(:create, params, record)
27
+
28
+ record.save
29
+ record
34
30
  end
35
31
 
36
32
  def update_from_data
37
- id = @data.delete('id')
33
+ attributes = params.to_h
34
+ id = attributes.delete(:id)
38
35
 
39
- check_params!
40
- record = @model.find(id)
41
- check_permit_update_destroy!(record)
42
- record.update(@data)
36
+ check_params!(:update)
37
+ record = model.find(id)
38
+ check_permit!(:update, params, record)
43
39
 
40
+ record.update(attributes)
44
41
  record
45
42
  end
46
43
 
47
44
  def destroy_from_data
48
- record = @model.find(@data['id'])
49
- check_permit_update_destroy!(record)
45
+ record = model.find(params.id)
46
+ check_permit!(:destroy, params, record)
50
47
  record.destroy
51
48
  end
52
49
 
53
50
  private
54
51
 
55
- def check_params!
56
- return if permitted_columns == :all
52
+ def or_query(*scopes)
53
+ nodes = scopes.map do |scope|
54
+ model.where(scope.to_h).where_values.reduce(:and)
55
+ end
56
+
57
+ nodes[1..-1].reduce(nodes.first) do |memo, node|
58
+ node.or(memo)
59
+ end
60
+ end
61
+
62
+ def check_params!(action)
63
+ @action = action
64
+ return if columns == :all
57
65
  return if unpermitted_columns.empty?
58
66
 
59
67
  raise NotPermittedError, "Request includes unpermitted columns: #{unpermitted_columns.join(', ')}"
60
68
  end
61
69
 
62
- def check_permit_update_destroy!(record)
63
- return unless permit_update_destroy_block
64
- return if permit_update_destroy_block.call(record)
70
+ def check_permit!(method, params, record = nil)
71
+ permit_checks = @controller.databound_config.read(:permit)
72
+ check = permit_checks[method]
73
+
74
+ return unless check
75
+ return if @controller.instance_exec(params, record, &check)
65
76
 
66
- raise NotPermittedError, 'Request for update or destroy not permitted'
77
+ raise NotPermittedError, "Request for #{method} not permitted"
67
78
  end
68
79
 
69
80
  def permit_update_destroy_block
@@ -71,29 +82,35 @@ module Databound
71
82
  end
72
83
 
73
84
  def unpermitted_columns
74
- requested = [@scope, @data].map(&:to_h).flat_map(&:keys)
75
- requested - permitted_columns.map(&:to_s)
85
+ params.to_h.keys - columns - allowed_action_columns
76
86
  end
77
87
 
78
- def permitted_columns
79
- columns = @controller.send(:permitted_columns)
88
+ def params
89
+ OpenStruct.new(@scope.to_h.merge(@data.to_h))
90
+ end
91
+
92
+ def allowed_action_columns
93
+ @action == :update ? [:id] : []
94
+ end
80
95
 
81
- case columns
82
- when :all
96
+ def columns
97
+ result = @controller.databound_config.read(:columns)
98
+
99
+ case result
100
+ when [:all]
83
101
  :all
84
- when :table_columns
102
+ when [:table_columns]
85
103
  table_columns
86
104
  else
87
- Array(columns)
105
+ Array(result)
88
106
  end
89
107
  end
90
108
 
91
109
  def table_columns
92
- # permit all by default
93
110
  if mongoid?
94
111
  model.fields.keys.map(&:to_sym)
95
112
  elsif activerecord?
96
- model.column_names
113
+ model.column_names.map(&:to_sym)
97
114
  else
98
115
  raise 'ORM not supported. Use ActiveRecord or Mongoid'
99
116
  end
@@ -108,7 +125,13 @@ module Databound
108
125
  end
109
126
 
110
127
  def model
111
- @controller.send(:model)
128
+ raise 'No model specified' unless model_name
129
+
130
+ model_name.to_s.camelize.constantize
131
+ end
132
+
133
+ def model_name
134
+ @controller.databound_config.read(:model)
112
135
  end
113
136
 
114
137
  def scope_js
@@ -122,5 +145,13 @@ module Databound
122
145
  def extra_where_scopes_js
123
146
  @controller.params[:extra_where_scopes] || '[]'
124
147
  end
148
+
149
+ def extra_scope_records
150
+ @extra_where_scopes.flat_map(&:records)
151
+ end
152
+
153
+ def filter_by_params!(records)
154
+ records.where(params.to_h)
155
+ end
125
156
  end
126
157
  end
@@ -3,15 +3,16 @@ class ActionDispatch::Routing::Mapper
3
3
  namespace = @scope[:path]
4
4
  namespace = namespace[1..-1] if namespace
5
5
  opts = resources.pop if resources.last.is_a?(Hash)
6
+ Databound::Controller.add_application_controller_configs!
6
7
 
7
8
  resources.each do |resource|
8
9
  Rails.application.routes.draw do
9
- controller = [namespace, resource].compact.join('/')
10
- Databound::Utils.create_controller_unless_exists(controller, resource, opts)
10
+ controller_name = [namespace, resource].compact.join('/')
11
+ Databound::Controller.find_or_create(controller_name, resource, opts)
11
12
 
12
13
  %i(where create update destroy).each do |name|
13
14
  path = [namespace, resource, name].compact.join('/')
14
- to = [controller, name].join('#')
15
+ to = [controller_name, name].join('#')
15
16
  post path => to
16
17
  end
17
18
  end
@@ -1,3 +1,3 @@
1
1
  module Databound
2
- VERSION = '2.0.1'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -1,6 +1,35 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe PermittedColumnsController, type: :controller do
3
+ describe PostsController, type: :controller do
4
+ describe 'via routes' do
5
+ it 'raise when param is not permitted' do
6
+ data = {
7
+ data: {
8
+ city: 'Barcelona',
9
+ },
10
+ scope: {},
11
+ }
12
+
13
+ expect { post(:create, javascriptize(data)) }.to raise_error(
14
+ Databound::NotPermittedError,
15
+ 'Request includes unpermitted columns: city',
16
+ )
17
+ end
18
+
19
+ it 'should create when param is permitted' do
20
+ data = {
21
+ data: {
22
+ title: 'Nikki',
23
+ },
24
+ scope: {},
25
+ }
26
+
27
+ expect { post(:create, javascriptize(data)) }.not_to raise_error
28
+ end
29
+ end
30
+ end
31
+
32
+ describe ColumnsController, type: :controller do
4
33
  describe '#create' do
5
34
  it 'raise when param is not permitted' do
6
35
  data = {
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe ProjectsController do
4
+ describe 'via routes' do
5
+ it 'should be able to specify model via routes' do
6
+ expect(ProjectsController.new.databound_config.read(:model)).to equal(:user)
7
+ end
8
+
9
+ it 'should be able to specify columns via routes' do
10
+ expect(ProjectsController.new.databound_config.read(:columns))
11
+ .to eql(%i(city user_id))
12
+ end
13
+ end
14
+ end
15
+
16
+ describe NoModelController, type: :controller do
17
+ describe 'raise error' do
18
+ it 'when model is not defined' do
19
+ expect { post(:create) }.to raise_error(RuntimeError)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe PermitController, type: :controller do
4
+ CURRENT_USER_ID = 1
5
+
6
+ before :each do
7
+ Project.create(city: 'LA', user_id: 5)
8
+ Project.create(city: 'LA', user_id: 1)
9
+ end
10
+
11
+ describe '#read' do
12
+ it 'raise when scope is not permitted' do
13
+ data = {
14
+ data: {
15
+ city: 'LA',
16
+ dont_permit: true,
17
+ },
18
+ scope: {},
19
+ }
20
+
21
+ expect { post(:where, javascriptize(data)) }.to raise_error(
22
+ Databound::NotPermittedError,
23
+ 'Request for read not permitted',
24
+ )
25
+ end
26
+
27
+ it 'should update when param is permitted' do
28
+ data = {
29
+ data: {
30
+ city: 'Barcelona',
31
+ user_id: 1,
32
+ },
33
+ scope: {},
34
+ }
35
+
36
+ expect { post(:where, javascriptize(data)) }.not_to raise_error
37
+ end
38
+ end
39
+
40
+ describe '#create' do
41
+ it 'raise when scope is not permitted' do
42
+ data = {
43
+ data: {
44
+ city: 'Barcelona',
45
+ user_id: 2,
46
+ },
47
+ scope: {},
48
+ }
49
+
50
+ expect { post(:create, javascriptize(data)) }.to raise_error(
51
+ Databound::NotPermittedError,
52
+ 'Request for create not permitted',
53
+ )
54
+ end
55
+
56
+ it 'should update when param is permitted' do
57
+ data = {
58
+ data: {
59
+ city: 'Barcelona',
60
+ user_id: 1,
61
+ },
62
+ scope: {},
63
+ }
64
+
65
+ expect { post(:create, javascriptize(data)) }.not_to raise_error
66
+ end
67
+ end
68
+
69
+ describe '#update' do
70
+ it 'raise when scope is not permitted' do
71
+ data = {
72
+ data: {
73
+ id: 1,
74
+ city: 'Barcelona',
75
+ },
76
+ scope: {},
77
+ }
78
+
79
+ expect { post(:update, javascriptize(data)) }.to raise_error(
80
+ Databound::NotPermittedError,
81
+ 'Request for update not permitted',
82
+ )
83
+ end
84
+
85
+ it 'should update when param is permitted' do
86
+ data = {
87
+ data: {
88
+ id: 2,
89
+ city: 'Barcelona',
90
+ },
91
+ scope: {},
92
+ }
93
+
94
+ expect { post(:update, javascriptize(data)) }.not_to raise_error
95
+ end
96
+ end
97
+
98
+ describe '#destroy' do
99
+ it 'raise when scope is not permitted' do
100
+ data = {
101
+ data: {
102
+ id: 1,
103
+ },
104
+ scope: {},
105
+ }
106
+
107
+ expect { post(:destroy, javascriptize(data)) }.to raise_error(
108
+ Databound::NotPermittedError,
109
+ 'Request for destroy not permitted',
110
+ )
111
+ end
112
+
113
+ it 'should destroy when param is permitted' do
114
+ data = {
115
+ data: {
116
+ id: 2,
117
+ },
118
+ scope: {},
119
+ }
120
+
121
+ expect { post(:destroy, javascriptize(data)) }.not_to raise_error
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,6 @@
1
+ class ColumnsController < ApplicationController
2
+ databound do
3
+ model :user
4
+ columns :name
5
+ end
6
+ end
@@ -1,21 +1,11 @@
1
1
  class DslController < ApplicationController
2
- include Databound
3
-
4
- private
5
-
6
- def model
7
- User
8
- end
9
-
10
- def permitted_columns
11
- %i(name city)
12
- end
13
-
14
- dsl(:city, :hottest) do
15
- 'Miami'
16
- end
17
-
18
- dsl(:city, :coldest) do |params|
19
- "Where #{params[:name]} lives"
2
+ databound do
3
+ model :user
4
+ columns :name, :city
5
+
6
+ dsl(:city, :hottest) { 'Miami' }
7
+ dsl(:city, :coldest) do |params|
8
+ "Where #{params.name} lives"
9
+ end
20
10
  end
21
11
  end
@@ -1,17 +1,8 @@
1
1
  class LooseDslController < ApplicationController
2
- include Databound
2
+ databound do
3
+ model :user
4
+ columns :name, :city
3
5
 
4
- private
5
-
6
- def permitted_columns
7
- %i(name city)
8
- end
9
-
10
- def model
11
- User
12
- end
13
-
14
- dsl(:city, :hottest, strict: false) do
15
- 'Miami'
6
+ dsl(:city, :hottest, strict: false) { 'Miami' }
16
7
  end
17
8
  end
@@ -1,3 +1,4 @@
1
1
  class NoModelController < ApplicationController
2
- include Databound
2
+ databound do
3
+ end
3
4
  end
@@ -0,0 +1,18 @@
1
+ class PermitController < ApplicationController
2
+ databound do
3
+ model :project
4
+ columns :name, :city, :user_id, :dont_permit
5
+
6
+ permit(:read) do |params, records|
7
+ !params.dont_permit
8
+ end
9
+
10
+ permit(:create) do |params|
11
+ params.user_id == CURRENT_USER_ID
12
+ end
13
+
14
+ permit(:update, :destroy) do |_, record|
15
+ record.user_id == CURRENT_USER_ID
16
+ end
17
+ end
18
+ end
@@ -1,13 +1,6 @@
1
1
  class UsersController < ApplicationController
2
- include Databound
3
-
4
- private
5
-
6
- def model
7
- User
8
- end
9
-
10
- def permitted_columns
11
- %i(name city)
2
+ databound do
3
+ model :user
4
+ columns :name, :city
12
5
  end
13
6
  end
@@ -1,10 +1,11 @@
1
1
  Rails.application.routes.draw do
2
2
  databound :users
3
3
  databound :no_model
4
- databound :permitted_columns
4
+ databound :columns
5
5
  databound :dsl
6
6
  databound :loose_dsl
7
- databound :messages, permitted_columns: :table_columns
8
- databound :permit_update_destroy
9
- databound :posts, permitted_columns: %i(title)
7
+ databound :messages, columns: :table_columns
8
+ databound :permit
9
+ databound :posts, columns: %i(title)
10
+ databound :projects, columns: %i(city user_id), model: :user
10
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: databound
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Domas Bitvinskas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-04 00:00:00.000000000 Z
11
+ date: 2015-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-rails
@@ -122,7 +122,8 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '10.0'
125
- description: Works with ActiveRecord and Mongoid out of the box
125
+ description: It lets you use methods like create, update, destroy in the front-end
126
+ while handling all the setup and providing basic security out of the box.
126
127
  email:
127
128
  - domas.bitvinskas@me.com
128
129
  executables: []
@@ -138,29 +139,30 @@ files:
138
139
  - config.ru
139
140
  - databound.gemspec
140
141
  - lib/databound.rb
142
+ - lib/databound/config.rb
143
+ - lib/databound/controller.rb
141
144
  - lib/databound/data.rb
142
145
  - lib/databound/extensions.rb
143
146
  - lib/databound/manager.rb
144
147
  - lib/databound/rails/routes.rb
145
- - lib/databound/utils.rb
146
148
  - lib/databound/version.rb
147
149
  - lib/generators/databound/install/install_generator.rb
148
150
  - lib/generators/databound/install/templates/application.js
149
151
  - lib/generators/databound/install/templates/databound-standalone.js
152
+ - spec/controllers/columns_controller_spec.rb
150
153
  - spec/controllers/databound_spec.rb
151
154
  - spec/controllers/dsl_controller_spec.rb
152
155
  - spec/controllers/loose_dsl_controller_spec.rb
153
- - spec/controllers/no_model_controller_spec.rb
156
+ - spec/controllers/model_controller_spec.rb
154
157
  - spec/controllers/on_the_fly_spec.rb
155
- - spec/controllers/permit_update_destroy_controller_spec.rb
156
- - spec/controllers/permitted_columns_controller_spec.rb
157
- - spec/controllers/permitted_routes_columns_controller_spec.rb
158
+ - spec/controllers/permit_controller_spec.rb
159
+ - spec/controllers/routes_opts_controller_spec.rb
158
160
  - spec/internal/app/controllers/application_controller.rb
161
+ - spec/internal/app/controllers/columns_controller.rb
159
162
  - spec/internal/app/controllers/dsl_controller.rb
160
163
  - spec/internal/app/controllers/loose_dsl_controller.rb
161
164
  - spec/internal/app/controllers/no_model_controller.rb
162
- - spec/internal/app/controllers/permit_update_destroy_controller.rb
163
- - spec/internal/app/controllers/permitted_columns_controller.rb
165
+ - spec/internal/app/controllers/permit_controller.rb
164
166
  - spec/internal/app/controllers/users_controller.rb
165
167
  - spec/internal/app/models/message.rb
166
168
  - spec/internal/app/models/post.rb
@@ -222,7 +224,7 @@ files:
222
224
  - spec/support/rails_test_app/public/robots.txt
223
225
  - spec/support/rails_test_app/vendor/assets/javascripts/.keep
224
226
  - spec/support/rails_test_app/vendor/assets/stylesheets/.keep
225
- homepage: https://github.com/Nedomas/databound
227
+ homepage: http://databound.me
226
228
  licenses:
227
229
  - MIT
228
230
  metadata: {}
@@ -245,22 +247,22 @@ rubyforge_project:
245
247
  rubygems_version: 2.2.2
246
248
  signing_key:
247
249
  specification_version: 4
248
- summary: Databound exposes Ruby on Rails database to the Javascript side
250
+ summary: Provides Javascript a simple API to the Ruby on Rails CRUD
249
251
  test_files:
252
+ - spec/controllers/columns_controller_spec.rb
250
253
  - spec/controllers/databound_spec.rb
251
254
  - spec/controllers/dsl_controller_spec.rb
252
255
  - spec/controllers/loose_dsl_controller_spec.rb
253
- - spec/controllers/no_model_controller_spec.rb
256
+ - spec/controllers/model_controller_spec.rb
254
257
  - spec/controllers/on_the_fly_spec.rb
255
- - spec/controllers/permit_update_destroy_controller_spec.rb
256
- - spec/controllers/permitted_columns_controller_spec.rb
257
- - spec/controllers/permitted_routes_columns_controller_spec.rb
258
+ - spec/controllers/permit_controller_spec.rb
259
+ - spec/controllers/routes_opts_controller_spec.rb
258
260
  - spec/internal/app/controllers/application_controller.rb
261
+ - spec/internal/app/controllers/columns_controller.rb
259
262
  - spec/internal/app/controllers/dsl_controller.rb
260
263
  - spec/internal/app/controllers/loose_dsl_controller.rb
261
264
  - spec/internal/app/controllers/no_model_controller.rb
262
- - spec/internal/app/controllers/permit_update_destroy_controller.rb
263
- - spec/internal/app/controllers/permitted_columns_controller.rb
265
+ - spec/internal/app/controllers/permit_controller.rb
264
266
  - spec/internal/app/controllers/users_controller.rb
265
267
  - spec/internal/app/models/message.rb
266
268
  - spec/internal/app/models/post.rb
@@ -1,36 +0,0 @@
1
- module Databound
2
- class Utils
3
- def self.create_controller_unless_exists(path, resource, opts)
4
- return if exists?(path)
5
- opts ||= {}
6
-
7
- controller = Class.new(ApplicationController)
8
- controller.send(:include, Databound)
9
- controller.send(:define_method, :model) do
10
- resource.to_s.classify.constantize
11
- end
12
-
13
- controller.send(:define_method, :permitted_columns) do
14
- opts.fetch(:permitted_columns) do
15
- raise 'Specify permitted_columns in routes or the controller'
16
- end
17
- end
18
-
19
- Object.const_set(controller_name(path), controller)
20
- end
21
-
22
- def self.exists?(path)
23
- begin
24
- controller_name(path).constantize
25
- rescue NameError
26
- return false
27
- end
28
-
29
- true
30
- end
31
-
32
- def self.controller_name(path)
33
- "#{path.camelize}Controller"
34
- end
35
- end
36
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe NoModelController, type: :controller do
4
- describe 'raise error' do
5
- it 'when model is not defined' do
6
- expect { post(:create) }.to raise_error(RuntimeError)
7
- end
8
- end
9
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe PermitUpdateDestroyController, type: :controller do
4
- CURRENT_USER_ID = 1
5
-
6
- before :each do
7
- Project.create(city: 'LA', user_id: 5)
8
- Project.create(city: 'LA', user_id: 1)
9
- end
10
-
11
- describe '#update' do
12
- it 'raise when scope is not permitted' do
13
- data = {
14
- data: {
15
- id: 1,
16
- city: 'Barcelona',
17
- },
18
- scope: {},
19
- }
20
-
21
- expect { post(:update, javascriptize(data)) }.to raise_error(
22
- Databound::NotPermittedError,
23
- 'Request for update or destroy not permitted',
24
- )
25
- end
26
-
27
- it 'should update when param is permitted' do
28
- data = {
29
- data: {
30
- id: 2,
31
- city: 'Barcelona',
32
- },
33
- scope: {},
34
- }
35
-
36
- expect { post(:update, javascriptize(data)) }.not_to raise_error
37
- end
38
- end
39
-
40
- describe '#destroy' do
41
- it 'raise when scope is not permitted' do
42
- data = {
43
- data: {
44
- id: 1,
45
- },
46
- scope: {},
47
- }
48
-
49
- expect { post(:destroy, javascriptize(data)) }.to raise_error(
50
- Databound::NotPermittedError,
51
- 'Request for update or destroy not permitted',
52
- )
53
- end
54
-
55
- it 'should destroy when param is permitted' do
56
- data = {
57
- data: {
58
- id: 2,
59
- },
60
- scope: {},
61
- }
62
-
63
- expect { post(:destroy, javascriptize(data)) }.not_to raise_error
64
- end
65
- end
66
- end
@@ -1,17 +0,0 @@
1
- class PermitUpdateDestroyController < ApplicationController
2
- include Databound
3
-
4
- private
5
-
6
- def permitted_columns
7
- %i(name city)
8
- end
9
-
10
- def model
11
- Project
12
- end
13
-
14
- permit_update_destroy? do |record|
15
- record.user_id == CURRENT_USER_ID
16
- end
17
- end
@@ -1,13 +0,0 @@
1
- class PermittedColumnsController < ApplicationController
2
- include Databound
3
-
4
- private
5
-
6
- def model
7
- User
8
- end
9
-
10
- def permitted_columns
11
- %i(name)
12
- end
13
- end