trestle 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/trestle/_confirmation.js +23 -0
- data/app/assets/javascripts/trestle/_datepicker.js +22 -0
- data/app/assets/javascripts/trestle/_errors.js +11 -0
- data/app/assets/javascripts/trestle/_form.js +6 -0
- data/app/assets/javascripts/trestle/_gallery.js +27 -0
- data/app/assets/javascripts/trestle/_select.js +11 -0
- data/app/assets/javascripts/trestle/_sidebar.js +52 -0
- data/app/assets/javascripts/trestle/_table.js +21 -0
- data/app/assets/javascripts/trestle/_tabs.js +13 -0
- data/app/assets/javascripts/trestle/_tooltips.js +3 -0
- data/app/assets/javascripts/trestle/admin.js +23 -0
- data/app/assets/javascripts/trestle/custom.js +4 -0
- data/app/assets/stylesheets/trestle/components/_table.scss +6 -0
- data/app/helpers/trestle/form_helper.rb +1 -1
- data/app/helpers/trestle/format_helper.rb +48 -0
- data/app/helpers/trestle/url_helper.rb +2 -8
- data/app/views/layouts/trestle/admin.html.erb +3 -3
- data/app/views/trestle/admin/index.html.erb +1 -1
- data/app/views/trestle/dashboard/index.html.erb +2 -2
- data/app/views/trestle/resource/_form.html.erb +1 -1
- data/app/views/trestle/resource/edit.html.erb +2 -2
- data/app/views/trestle/resource/index.html.erb +1 -1
- data/app/views/trestle/resource/new.html.erb +1 -1
- data/app/views/trestle/resource/show.html.erb +2 -2
- data/app/views/trestle/shared/_sidebar.html.erb +4 -2
- data/bower.json +1 -1
- data/config/locales/en.yml +16 -2
- data/lib/generators/trestle/install/install_generator.rb +3 -3
- data/lib/generators/trestle/install/templates/custom.js +7 -0
- data/lib/generators/trestle/install/templates/trestle.rb.erb +3 -2
- data/lib/trestle/adapters.rb +7 -64
- data/lib/trestle/adapters/active_record_adapter.rb +46 -20
- data/lib/trestle/adapters/adapter.rb +176 -0
- data/lib/trestle/adapters/sequel_adapter.rb +85 -0
- data/lib/trestle/admin.rb +1 -1
- data/lib/trestle/attribute.rb +14 -37
- data/lib/trestle/breadcrumb.rb +6 -0
- data/lib/trestle/configuration.rb +1 -1
- data/lib/trestle/form/automatic.rb +29 -21
- data/lib/trestle/form/builder.rb +4 -0
- data/lib/trestle/form/field.rb +2 -2
- data/lib/trestle/form/fields/check_box.rb +1 -1
- data/lib/trestle/form/fields/collection_select.rb +1 -1
- data/lib/trestle/form/fields/date_select.rb +1 -1
- data/lib/trestle/form/fields/datetime_select.rb +1 -1
- data/lib/trestle/form/fields/grouped_collection_select.rb +1 -1
- data/lib/trestle/form/fields/select.rb +2 -2
- data/lib/trestle/form/fields/tag_select.rb +1 -2
- data/lib/trestle/form/fields/time_select.rb +1 -1
- data/lib/trestle/form/fields/time_zone_select.rb +1 -1
- data/lib/trestle/resource.rb +11 -7
- data/lib/trestle/resource/builder.rb +2 -1
- data/lib/trestle/resource/controller.rb +61 -17
- data/lib/trestle/scope.rb +1 -1
- data/lib/trestle/table/automatic.rb +5 -11
- data/lib/trestle/table/builder.rb +1 -0
- data/lib/trestle/table/column.rb +24 -43
- data/lib/trestle/version.rb +1 -1
- data/trestle.gemspec +3 -4
- data/vendor/assets/bower_components/trestle/flatpickr/dist/flatpickr.css +51 -26
- data/vendor/assets/bower_components/trestle/flatpickr/dist/flatpickr.js +349 -299
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ar.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/bg.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/bn.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/cat.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/cs.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/cy.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/da.js +6 -6
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/de.js +10 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/eo.js +11 -11
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/es.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/et.js +11 -11
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/fa.js +6 -6
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/fi.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/fr.js +11 -11
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/gr.js +13 -13
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/he.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/hi.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/hr.js +6 -6
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/hu.js +10 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/id.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/index.js +97 -0
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/it.js +10 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ja.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ko.js +6 -6
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/lt.js +10 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/lv.js +6 -6
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/mk.js +8 -8
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ms.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/my.js +7 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/nl.js +11 -11
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/no.js +11 -11
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/pa.js +5 -5
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/pl.js +6 -6
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/pt.js +6 -8
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ro.js +7 -9
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ru.js +6 -8
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/si.js +5 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sk.js +8 -8
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sl.js +8 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sq.js +5 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sr.js +9 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sv.js +8 -10
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/th.js +10 -11
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/tr.js +6 -8
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/uk.js +6 -7
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/vn.js +6 -8
- data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/zh.js +9 -11
- metadata +24 -34
- data/app/assets/javascripts/trestle/_confirmation.js.coffee +0 -18
- data/app/assets/javascripts/trestle/_datepicker.js.coffee +0 -18
- data/app/assets/javascripts/trestle/_errors.js.coffee +0 -8
- data/app/assets/javascripts/trestle/_form.js.coffee +0 -4
- data/app/assets/javascripts/trestle/_gallery.js.coffee +0 -21
- data/app/assets/javascripts/trestle/_select.js.coffee +0 -7
- data/app/assets/javascripts/trestle/_sidebar.js.coffee +0 -45
- data/app/assets/javascripts/trestle/_table.js.coffee +0 -16
- data/app/assets/javascripts/trestle/_tabs.js.coffee +0 -9
- data/app/assets/javascripts/trestle/_tooltips.js.coffee +0 -2
- data/app/assets/javascripts/trestle/admin.js.coffee +0 -22
- data/app/assets/javascripts/trestle/custom.js.coffee +0 -4
- data/lib/generators/trestle/install/templates/custom.js.coffee +0 -7
data/bower.json
CHANGED
data/config/locales/en.yml
CHANGED
|
@@ -28,6 +28,12 @@ en:
|
|
|
28
28
|
more_pages:
|
|
29
29
|
display_entries: "Displaying %{entry_name} <strong>%{first} - %{last}</strong> of <b>%{total}</b>"
|
|
30
30
|
|
|
31
|
+
onboarding:
|
|
32
|
+
welcome: Welcome to Trestle
|
|
33
|
+
no_admins: To begin, please create an admin within <code>app/admin</code>.
|
|
34
|
+
no_template: To customize this template, please create <code>%{path}</code>.
|
|
35
|
+
no_form: Please define a form block or create a <code>_form.html</code> partial.
|
|
36
|
+
|
|
31
37
|
admin:
|
|
32
38
|
titles:
|
|
33
39
|
index: Listing %{pluralized_model_name}
|
|
@@ -44,10 +50,18 @@ en:
|
|
|
44
50
|
headers:
|
|
45
51
|
id: ID
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
form:
|
|
54
|
+
select:
|
|
55
|
+
prompt: "- Select %{attribute_name} -"
|
|
49
56
|
|
|
50
57
|
confirmation:
|
|
51
58
|
title: Are you sure?
|
|
52
59
|
delete: Delete
|
|
53
60
|
cancel: Cancel
|
|
61
|
+
|
|
62
|
+
ui:
|
|
63
|
+
toggle_navigation: Toggle navigation
|
|
64
|
+
toggle_sidebar: Toggle sidebar
|
|
65
|
+
|
|
66
|
+
format:
|
|
67
|
+
blank: None
|
|
@@ -10,10 +10,10 @@ module Trestle
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def create_assets
|
|
13
|
-
template "_variables.scss",
|
|
14
|
-
template "_custom.scss",
|
|
13
|
+
template "_variables.scss", "app/assets/stylesheets/trestle/_variables.scss"
|
|
14
|
+
template "_custom.scss", "app/assets/stylesheets/trestle/_custom.scss"
|
|
15
15
|
|
|
16
|
-
template "custom.js
|
|
16
|
+
template "custom.js", "app/assets/javascripts/trestle/custom.js"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def create_directory
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This file may be used for providing additional customizations to the Trestle
|
|
2
|
+
// admin. It will be automatically included within all admin pages.
|
|
3
|
+
//
|
|
4
|
+
// For organizational purposes, you may wish to define your customizations
|
|
5
|
+
// within individual partials and `require` them here.
|
|
6
|
+
//
|
|
7
|
+
// e.g. //= require "trestle/custom/my_custom_js"
|
|
@@ -70,7 +70,7 @@ Trestle.configure do |config|
|
|
|
70
70
|
# config.around_action do |controller, block|
|
|
71
71
|
# Rails.logger.debug("Around action (before)")
|
|
72
72
|
# block.call
|
|
73
|
-
# Rails.logger.debug("Around
|
|
73
|
+
# Rails.logger.debug("Around action (after)")
|
|
74
74
|
# end
|
|
75
75
|
|
|
76
76
|
# Specify a custom hook to be injected into the admin.
|
|
@@ -93,7 +93,8 @@ Trestle.configure do |config|
|
|
|
93
93
|
# See the documentation on Trestle::Adapters::Adapter for details on
|
|
94
94
|
# the adapter methods that can be customized.
|
|
95
95
|
#
|
|
96
|
-
# config.default_adapter.
|
|
96
|
+
# config.default_adapter = Trestle::Adapters.compose(Trestle::Adapters::SequelAdapter)
|
|
97
|
+
# config.default_adapter.include MyAdapterExtensions
|
|
97
98
|
|
|
98
99
|
# Register a form field type to be made available to the Trestle form builder.
|
|
99
100
|
# Field types should conform to the following method definition:
|
data/lib/trestle/adapters.rb
CHANGED
|
@@ -2,73 +2,16 @@ module Trestle
|
|
|
2
2
|
module Adapters
|
|
3
3
|
extend ActiveSupport::Autoload
|
|
4
4
|
|
|
5
|
+
autoload :Adapter
|
|
6
|
+
|
|
5
7
|
autoload :ActiveRecordAdapter
|
|
6
8
|
autoload :DraperAdapter
|
|
9
|
+
autoload :SequelAdapter
|
|
7
10
|
|
|
8
|
-
class
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@admin = admin
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def collection(params={})
|
|
16
|
-
raise NotImplementedError
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def find_instance(params)
|
|
20
|
-
raise NotImplementedError
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def build_instance(params={})
|
|
24
|
-
raise NotImplementedError
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def update_instance(instance, params)
|
|
28
|
-
raise NotImplementedError
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def save_instance(instance)
|
|
32
|
-
raise NotImplementedError
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def delete_instance(instance)
|
|
36
|
-
raise NotImplementedError
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def decorate_collection(collection)
|
|
40
|
-
collection
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def merge_scopes(scope, other)
|
|
44
|
-
raise NotImplementedError
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def sort(collection, params)
|
|
48
|
-
raise NotImplementedError
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def paginate(collection, params)
|
|
52
|
-
raise NotImplementedError
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def count(collection)
|
|
56
|
-
raise NotImplementedError
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def permitted_params(params)
|
|
60
|
-
params.require(admin.admin_name.singularize).permit!
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def default_attributes
|
|
64
|
-
raise NotImplementedError
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Creates a new Adapter class with the given modules mixed in
|
|
68
|
-
def self.compose(*modules)
|
|
69
|
-
Class.new(self) do
|
|
70
|
-
modules.each { |mod| include(mod) }
|
|
71
|
-
end
|
|
11
|
+
# Creates a new Adapter class with the given modules mixed in
|
|
12
|
+
def self.compose(*modules)
|
|
13
|
+
Class.new(Adapter) do
|
|
14
|
+
modules.each { |mod| include(mod) }
|
|
72
15
|
end
|
|
73
16
|
end
|
|
74
17
|
end
|
|
@@ -2,19 +2,19 @@ module Trestle
|
|
|
2
2
|
module Adapters
|
|
3
3
|
module ActiveRecordAdapter
|
|
4
4
|
def collection(params={})
|
|
5
|
-
|
|
5
|
+
model.all
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def find_instance(params)
|
|
9
|
-
|
|
9
|
+
model.find(params[:id])
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def build_instance(params={})
|
|
13
|
-
|
|
12
|
+
def build_instance(attrs={}, params={})
|
|
13
|
+
model.new(attrs)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def update_instance(instance, params)
|
|
17
|
-
instance.assign_attributes(
|
|
16
|
+
def update_instance(instance, attrs, params={})
|
|
17
|
+
instance.assign_attributes(attrs)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def save_instance(instance)
|
|
@@ -25,10 +25,6 @@ module Trestle
|
|
|
25
25
|
instance.destroy
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def to_param(instance)
|
|
29
|
-
instance
|
|
30
|
-
end
|
|
31
|
-
|
|
32
28
|
def unscope(scope)
|
|
33
29
|
scope.unscoped
|
|
34
30
|
end
|
|
@@ -37,27 +33,57 @@ module Trestle
|
|
|
37
33
|
scope.merge(other)
|
|
38
34
|
end
|
|
39
35
|
|
|
36
|
+
def count(collection)
|
|
37
|
+
collection.count
|
|
38
|
+
end
|
|
39
|
+
|
|
40
40
|
def sort(collection, field, order)
|
|
41
41
|
collection.reorder(field => order)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
collection.page(params[:page])
|
|
44
|
+
def human_attribute_name(attribute, options={})
|
|
45
|
+
model.human_attribute_name(attribute, options)
|
|
47
46
|
end
|
|
48
47
|
|
|
49
|
-
def
|
|
50
|
-
|
|
48
|
+
def default_table_attributes
|
|
49
|
+
default_attributes.reject do |attribute|
|
|
50
|
+
inheritance_column?(attribute) || counter_cache_column?(attribute)
|
|
51
|
+
end
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
def default_form_attributes
|
|
55
|
+
default_attributes.reject do |attribute|
|
|
56
|
+
primary_key?(attribute) || inheritance_column?(attribute) || counter_cache_column?(attribute)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
protected
|
|
53
61
|
def default_attributes
|
|
54
|
-
|
|
55
|
-
if column.name.end_with?("_id") && (
|
|
56
|
-
Attribute::Association.new(
|
|
62
|
+
model.columns.map do |column|
|
|
63
|
+
if column.name.end_with?("_id") && (name = column.name.sub(/_id$/, '')) && (reflection = model.reflections[name])
|
|
64
|
+
Attribute::Association.new(column.name, class: -> { reflection.klass }, name: name, polymorphic: reflection.polymorphic?, type_column: reflection.foreign_type)
|
|
65
|
+
elsif column.name.end_with?("_type") && (name = column.name.sub(/_type$/, '')) && (reflection = model.reflections[name])
|
|
66
|
+
# Ignore type columns for polymorphic associations
|
|
57
67
|
else
|
|
58
|
-
Attribute.new(
|
|
68
|
+
Attribute.new(column.name, column.type, array_column?(column) ? { array: true } : {})
|
|
59
69
|
end
|
|
60
|
-
end
|
|
70
|
+
end.compact
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def primary_key?(attribute)
|
|
74
|
+
attribute.name.to_s == model.primary_key
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def inheritance_column?(attribute)
|
|
78
|
+
attribute.name.to_s == model.inheritance_column
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def counter_cache_column?(attribute)
|
|
82
|
+
attribute.name.to_s.end_with?("_count")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def array_column?(column)
|
|
86
|
+
column.respond_to?(:array?) && column.array?
|
|
61
87
|
end
|
|
62
88
|
end
|
|
63
89
|
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
module Trestle
|
|
2
|
+
module Adapters
|
|
3
|
+
class Adapter
|
|
4
|
+
attr_reader :admin
|
|
5
|
+
delegate :model, to: :admin
|
|
6
|
+
|
|
7
|
+
def initialize(admin)
|
|
8
|
+
@admin = admin
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Loads the initial collection for use by the index action.
|
|
12
|
+
#
|
|
13
|
+
# params - Unfiltered params hash from the controller
|
|
14
|
+
#
|
|
15
|
+
# Returns a scope object that can be chained with other methods (e.g. sort, paginate, count, etc).
|
|
16
|
+
def collection(params={})
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Finds (and returns) an individual instance for use by the show, edit, update, destroy actions.
|
|
21
|
+
#
|
|
22
|
+
# params - Unfiltered params hash from the controller
|
|
23
|
+
def find_instance(params)
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Builds (and returns) a new instance for new/create actions.
|
|
28
|
+
#
|
|
29
|
+
# attrs - Permitted attributes to set on the new instance
|
|
30
|
+
# params - Unfiltered params hash from the controller
|
|
31
|
+
def build_instance(attrs={}, params={})
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Updates (but does not save) a given resource's attributes.
|
|
36
|
+
#
|
|
37
|
+
# instance - The instance to update
|
|
38
|
+
# attrs - Permitted attributes to update on the instance
|
|
39
|
+
# params - Unfiltered params hash from the controller
|
|
40
|
+
#
|
|
41
|
+
# The return value is ignored.
|
|
42
|
+
def update_instance(instance, attrs, params={})
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Saves an instance (used by the create and update actions).
|
|
47
|
+
#
|
|
48
|
+
# instance - The instance to save
|
|
49
|
+
#
|
|
50
|
+
# Returns a boolean indicating the success/fail status of the save.
|
|
51
|
+
def save_instance(instance)
|
|
52
|
+
raise NotImplementedError
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Deletes an instance (used by the destroy action).
|
|
56
|
+
#
|
|
57
|
+
# instance - The instance to delete
|
|
58
|
+
#
|
|
59
|
+
# Returns a boolean indicating the success/fail status of the deletion.
|
|
60
|
+
def delete_instance(instance)
|
|
61
|
+
raise NotImplementedError
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Decorates a collection for rendering by the index view.
|
|
65
|
+
# Decorating is the final step in preparing the collection for the view.
|
|
66
|
+
#
|
|
67
|
+
# collection - The collection to decorate
|
|
68
|
+
#
|
|
69
|
+
# Returns an enumerable collection of instances.
|
|
70
|
+
def decorate_collection(collection)
|
|
71
|
+
collection
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Converts an instance to a URL parameter. The result of this method is passed to the #find_instance
|
|
75
|
+
# adapter method as params[:id]. It is recommended to simply use the instance's #id, as other potential options
|
|
76
|
+
# such as a permalink/slug could potentially be changed during editing.
|
|
77
|
+
#
|
|
78
|
+
# instance - The instance to convert
|
|
79
|
+
#
|
|
80
|
+
# Returns the URL representation of the instance.
|
|
81
|
+
def to_param(instance)
|
|
82
|
+
instance.id
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Unscopes a collection so that it can be merged with other scopes without duplication or interference.
|
|
86
|
+
#
|
|
87
|
+
# scope - The scope to unscope
|
|
88
|
+
#
|
|
89
|
+
# Returns a scope object.
|
|
90
|
+
def unscope(scope)
|
|
91
|
+
scope
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Merges scopes together for Trestle scope application and counting.
|
|
95
|
+
#
|
|
96
|
+
# scope - The first scope
|
|
97
|
+
# other - The second scope
|
|
98
|
+
#
|
|
99
|
+
# Returns a scope object representing the combination of the two given scopes.
|
|
100
|
+
def merge_scopes(scope, other)
|
|
101
|
+
raise NotImplementedError
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Counts the number of objects in a collection for use by scope links.
|
|
105
|
+
#
|
|
106
|
+
# collection - The collection to count
|
|
107
|
+
#
|
|
108
|
+
# Returns the total number (integer) of objects in the collection.
|
|
109
|
+
def count(collection)
|
|
110
|
+
raise NotImplementedError
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Sorts the collection by the given field and order.
|
|
114
|
+
# This method is called when an explicit sort column for the given field is not defined.
|
|
115
|
+
#
|
|
116
|
+
# collection - The collection to sort
|
|
117
|
+
# field - The field to sort by
|
|
118
|
+
# order - Symbol (:asc or :desc) representing the sort order (ascending or descending)
|
|
119
|
+
#
|
|
120
|
+
# Returns a scope object
|
|
121
|
+
def sort(collection, field, order)
|
|
122
|
+
raise NotImplementedError
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Paginates a collection for use by the index action.
|
|
126
|
+
#
|
|
127
|
+
# collection - The collection to paginate
|
|
128
|
+
# params - Unfiltered params hash from the controller:
|
|
129
|
+
# :page - current page number
|
|
130
|
+
#
|
|
131
|
+
# Returns a Kaminari-compatible scope corresponding to a single page.
|
|
132
|
+
def paginate(collection, params)
|
|
133
|
+
collection = Kaminari.paginate_array(collection.to_a) unless collection.respond_to?(:page)
|
|
134
|
+
collection.page(params[:page])
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Filters the submitted form parameters and returns a whitelisted attributes 'hash'
|
|
138
|
+
# that can be set or updated on a model instance.
|
|
139
|
+
#
|
|
140
|
+
# IMPORTANT: By default, all params are permitted, which assumes a trusted administrator. If this is not the
|
|
141
|
+
# case, a `params` block should be individually declared for each admin with the set of permitted parameters.
|
|
142
|
+
#
|
|
143
|
+
# params - Unfiltered params hash from the controller
|
|
144
|
+
#
|
|
145
|
+
# Returns the permitted set of parameters as a ActionController::Parameters object.
|
|
146
|
+
def permitted_params(params)
|
|
147
|
+
params.require(admin.admin_name.singularize).permit!
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Produces a human-readable name for a given attribute, applying I18n where appropriate.
|
|
151
|
+
# See ActiveModel::Translation for an implementation of this method.
|
|
152
|
+
#
|
|
153
|
+
# attribute - Attribute name (Symbol)
|
|
154
|
+
# options - Hash of options [not currently used]
|
|
155
|
+
#
|
|
156
|
+
# Returns the human-readable name of the given attribute as a String.
|
|
157
|
+
def human_attribute_name(attribute, options={})
|
|
158
|
+
attribute.to_s.titleize
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Generates a list of attributes that should be rendered by the index (table) view.
|
|
162
|
+
#
|
|
163
|
+
# Returns an Array of Trestle::Attribute and/or Trestle::Attribute::Association objects.
|
|
164
|
+
def default_table_attributes
|
|
165
|
+
raise NotImplementedError
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Generates a list of attributes that should be rendered by the new/show/edit (form) views.
|
|
169
|
+
#
|
|
170
|
+
# Returns an Array of Trestle::Attribute and/or Trestle::Attribute::Association objects.
|
|
171
|
+
def default_form_attributes
|
|
172
|
+
raise NotImplementedError
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "sequel"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
$stderr.puts "You don't have sequel installed in your application. Please add it to your Gemfile and run bundle install"
|
|
5
|
+
raise
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
Sequel::Model.plugin :active_model
|
|
9
|
+
|
|
10
|
+
module Trestle
|
|
11
|
+
module Adapters
|
|
12
|
+
module SequelAdapter
|
|
13
|
+
def collection(params={})
|
|
14
|
+
model.dataset
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find_instance(params)
|
|
18
|
+
model[params[:id]]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def build_instance(attrs={}, params={})
|
|
22
|
+
model.new(attrs)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def update_instance(instance, attrs, params={})
|
|
26
|
+
instance.set(attrs)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def save_instance(instance)
|
|
30
|
+
instance.save
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def delete_instance(instance)
|
|
34
|
+
instance.destroy
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def unscope(scope)
|
|
38
|
+
scope.unfiltered
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def merge_scopes(scope, other)
|
|
42
|
+
scope.intersect(other)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def count(collection)
|
|
46
|
+
collection.count
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def sort(collection, field, order)
|
|
50
|
+
collection.order(Sequel.send(order, field))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def default_table_attributes
|
|
54
|
+
default_attributes.reject do |attribute|
|
|
55
|
+
inheritance_column?(attribute)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def default_form_attributes
|
|
60
|
+
default_attributes.reject do |attribute|
|
|
61
|
+
primary_key?(attribute) || inheritance_column?(attribute)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
def default_attributes
|
|
67
|
+
model.db_schema.map do |column_name, column_attrs|
|
|
68
|
+
if column_name.to_s.end_with?("_id") && (name = column_name.to_s.sub(/_id$/, '')) && (reflection = model.association_reflection(name.to_sym))
|
|
69
|
+
Attribute::Association.new(column_name, class: -> { reflection.associated_class }, name: name)
|
|
70
|
+
else
|
|
71
|
+
Attribute.new(column_name, column_attrs[:type])
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def primary_key?(attribute)
|
|
77
|
+
attribute.name.to_s == model.primary_key.to_s
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def inheritance_column?(attribute)
|
|
81
|
+
model.respond_to?(:sti_key) && attribute.name.to_s == model.sti_key.to_s
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|