upmin-admin 0.0.39 → 0.1.0
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/README.md +25 -14
- data/Rakefile +24 -15
- data/app/assets/javascripts/upmin/application.js +0 -1
- data/app/assets/stylesheets/upmin/base.css.scss +4 -0
- data/app/assets/stylesheets/upmin/instances.css.scss +11 -1
- data/app/controllers/upmin/models_controller.rb +52 -42
- data/app/views/layouts/upmin/_navbar.html.haml +3 -3
- data/app/views/layouts/upmin/application.html.haml +2 -1
- data/app/views/upmin/models/new.html.haml +3 -3
- data/app/views/upmin/models/search.html.haml +5 -4
- data/app/views/upmin/models/show.html.haml +3 -3
- data/app/views/upmin/partials/actions/_action.html.haml +6 -21
- data/app/views/upmin/partials/associations/_associations.html.haml +8 -10
- data/app/views/upmin/partials/attributes/_boolean.html.haml +8 -6
- data/app/views/upmin/partials/attributes/_datetime.html.haml +38 -36
- data/app/views/upmin/partials/attributes/_decimal.html.haml +10 -0
- data/app/views/upmin/partials/attributes/_float.html.haml +10 -6
- data/app/views/upmin/partials/attributes/_integer.html.haml +10 -6
- data/app/views/upmin/partials/attributes/_progress_bar.html.haml +1 -0
- data/app/views/upmin/partials/attributes/_string.html.haml +17 -6
- data/app/views/upmin/partials/attributes/_text.html.haml +8 -6
- data/app/views/upmin/partials/attributes/_unknown.html.haml +5 -3
- data/app/views/upmin/partials/models/_model.html.haml +18 -46
- data/app/views/upmin/partials/models/_new_model.html.haml +9 -31
- data/app/views/upmin/partials/parameters/_block_parameter.haml +0 -0
- data/app/views/upmin/partials/parameters/_opt_parameter.html.haml +14 -0
- data/app/views/upmin/partials/parameters/_req_parameter.html.haml +4 -0
- data/app/views/upmin/partials/search_boxes/_ransack_search_box.html.haml +2 -3
- data/app/views/upmin/partials/search_results/_results.html.haml +9 -2
- data/lib/upmin/action.rb +50 -0
- data/lib/upmin/active_record/association.rb +47 -0
- data/lib/upmin/active_record/model.rb +54 -0
- data/lib/upmin/active_record/query.rb +12 -0
- data/lib/upmin/admin.rb +24 -2
- data/lib/upmin/association.rb +73 -0
- data/lib/upmin/attribute.rb +87 -0
- data/lib/upmin/automatic_delegation.rb +76 -0
- data/lib/upmin/configuration.rb +103 -0
- data/lib/upmin/data_mapper/association.rb +57 -0
- data/lib/upmin/data_mapper/model.rb +62 -0
- data/lib/upmin/data_mapper/query.rb +57 -0
- data/lib/upmin/engine.rb +2 -0
- data/lib/upmin/errors.rb +43 -0
- data/lib/upmin/model.rb +267 -98
- data/lib/upmin/parameter.rb +43 -0
- data/lib/upmin/query.rb +51 -0
- data/lib/upmin/railtie.rb +11 -1
- data/lib/upmin/railties/active_record.rb +5 -50
- data/lib/upmin/railties/data_mapper.rb +18 -0
- data/lib/upmin/railties/render.rb +34 -98
- data/lib/upmin/railties/render_helpers.rb +119 -53
- data/lib/upmin/version.rb +1 -1
- data/spec/factories/factories.rb +6 -0
- data/spec/features/action_spec.rb +39 -46
- data/spec/features/edit_model_spec.rb +4 -2
- data/spec/features/navbar_spec.rb +48 -0
- data/spec/features/new_model_spec.rb +1 -0
- data/spec/features/search_spec.rb +7 -4
- data/spec/lib/configuration_spec.rb +60 -0
- data/spec/spec_helper.rb +14 -8
- metadata +25 -7
- data/app/assets/javascripts/upmin/moment.js +0 -2856
- data/app/helpers/upmin/instances_helper.rb +0 -13
- data/app/views/upmin/partials/attributes/_nilable.html.haml +0 -14
- data/app/views/upmin/partials/search_results/_result.html.haml +0 -8
- data/lib/upmin/klass.rb +0 -170
@@ -0,0 +1,103 @@
|
|
1
|
+
module Upmin
|
2
|
+
# Add Config Stuff to Upmin
|
3
|
+
class << self
|
4
|
+
attr_accessor :configuration
|
5
|
+
|
6
|
+
def configuration
|
7
|
+
@configuration ||= Configuration.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def configure
|
11
|
+
yield(configuration) if block_given?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Configuration
|
16
|
+
attr_writer :colors
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
::Rails.application.eager_load!
|
20
|
+
end
|
21
|
+
|
22
|
+
def colors=(colors)
|
23
|
+
@custom_colors = true
|
24
|
+
@colors = colors
|
25
|
+
end
|
26
|
+
|
27
|
+
def colors
|
28
|
+
if defined?(@custom_colors)
|
29
|
+
return @colors
|
30
|
+
else
|
31
|
+
return default_colors
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def models=(models)
|
36
|
+
@custom_models = true
|
37
|
+
@models = models
|
38
|
+
end
|
39
|
+
|
40
|
+
def models
|
41
|
+
if defined?(@custom_models)
|
42
|
+
return @models
|
43
|
+
else
|
44
|
+
return default_models
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def default_models
|
51
|
+
def_models = []
|
52
|
+
orm_found = false
|
53
|
+
|
54
|
+
if defined?(Rails) && Rails.application
|
55
|
+
::Rails.application.eager_load!
|
56
|
+
else
|
57
|
+
raise "We kinda need rails for a rails engine :("
|
58
|
+
end
|
59
|
+
|
60
|
+
if defined?(ActiveRecord)
|
61
|
+
orm_found = true
|
62
|
+
::Rails.application.eager_load!
|
63
|
+
def_models += ::ActiveRecord::Base.descendants
|
64
|
+
.map(&:to_s)
|
65
|
+
.select{ |m| m != "ActiveRecord::SchemaMigration" }
|
66
|
+
.sort
|
67
|
+
.map(&:underscore)
|
68
|
+
.map(&:to_sym)
|
69
|
+
end
|
70
|
+
|
71
|
+
if defined?(DataMapper)
|
72
|
+
orm_found = true
|
73
|
+
::Rails.application.eager_load!
|
74
|
+
def_models += ::DataMapper::Model.descendants.entries
|
75
|
+
.map(&:to_s)
|
76
|
+
.sort
|
77
|
+
.map(&:underscore)
|
78
|
+
.map(&:to_sym)
|
79
|
+
end
|
80
|
+
|
81
|
+
unless orm_found
|
82
|
+
raise UnsupportedObjectMapper.new
|
83
|
+
end
|
84
|
+
|
85
|
+
return def_models
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_colors
|
89
|
+
return [
|
90
|
+
:light_blue,
|
91
|
+
:blue_green,
|
92
|
+
:red,
|
93
|
+
:yellow,
|
94
|
+
:orange,
|
95
|
+
:purple,
|
96
|
+
:dark_blue,
|
97
|
+
:dark_red,
|
98
|
+
:green
|
99
|
+
]
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Upmin::DataMapper
|
2
|
+
module Association
|
3
|
+
|
4
|
+
def type
|
5
|
+
return @type if defined?(@type)
|
6
|
+
|
7
|
+
if relationship
|
8
|
+
# NOTE(jon): I believe many to one is the only type where child_model_name is incorrect, but I could be wrong.
|
9
|
+
if relationship.is_a?(DataMapper::Associations::ManyToOne::Relationship)
|
10
|
+
@type = relationship.parent_model_name
|
11
|
+
else
|
12
|
+
@type = relationship.child_model_name
|
13
|
+
end
|
14
|
+
|
15
|
+
@type = @type.underscore
|
16
|
+
|
17
|
+
if collection?
|
18
|
+
@type = @type.pluralize.to_sym
|
19
|
+
else
|
20
|
+
@type = @type.to_sym
|
21
|
+
end
|
22
|
+
else
|
23
|
+
@type = :unknown
|
24
|
+
end
|
25
|
+
|
26
|
+
if @type == :unknown
|
27
|
+
@type = infer_type_from_value
|
28
|
+
end
|
29
|
+
|
30
|
+
return @type
|
31
|
+
end
|
32
|
+
|
33
|
+
def collection?
|
34
|
+
if relationship
|
35
|
+
return relationship.max > 1
|
36
|
+
elsif value
|
37
|
+
return value.responts_to?(:each)
|
38
|
+
else
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def relationship
|
47
|
+
return @relationship if defined?(@relationship)
|
48
|
+
|
49
|
+
@relationship = model.model_class.relationships.select do |r|
|
50
|
+
r.name == name
|
51
|
+
end.first
|
52
|
+
|
53
|
+
return @relationship
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Upmin::DataMapper
|
2
|
+
module Model
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def new_record?
|
6
|
+
return model.new?
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_key
|
10
|
+
return [model.id]
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# NOTE - ANY method added here must be added to the bottom of
|
16
|
+
# Upmin::Model. This ensures that an instance of the class was
|
17
|
+
# created, which in turn ensures that the correct module was
|
18
|
+
# included in the class.
|
19
|
+
|
20
|
+
def find(*args)
|
21
|
+
return model_class.get(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_attributes
|
25
|
+
return model_class.properties.map(&:name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def attribute_type(attribute)
|
29
|
+
property = model_class.properties.select{ |p| p.name == attribute }.first
|
30
|
+
type = property.class.to_s.demodulize.underscore.to_sym
|
31
|
+
|
32
|
+
case type
|
33
|
+
when :serial
|
34
|
+
return :integer
|
35
|
+
when :date_time
|
36
|
+
return :datetime
|
37
|
+
else
|
38
|
+
return type
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def associations
|
43
|
+
return @associations if defined?(@associations)
|
44
|
+
|
45
|
+
all = []
|
46
|
+
ignored = []
|
47
|
+
model_class.relationships.each do |relationship|
|
48
|
+
all << relationship.name
|
49
|
+
|
50
|
+
# This may need dropped later if we find that it is more useful to show these.
|
51
|
+
if relationship.is_a?(DataMapper::Associations::ManyToMany::Relationship)
|
52
|
+
ignored << relationship.options[:through]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
return @associations = (all - ignored).uniq
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Upmin::DataMapper
|
2
|
+
module Query
|
3
|
+
|
4
|
+
def results
|
5
|
+
return klass.model_class.all(prepared_search)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def prepared_search
|
11
|
+
return @prepared_search if defined?(@prepared_search)
|
12
|
+
@prepared_search = {}
|
13
|
+
if search_options
|
14
|
+
search_options.each do |key, value|
|
15
|
+
next if value.empty?
|
16
|
+
|
17
|
+
if op = create_operator(key)
|
18
|
+
@prepared_search[op] = value
|
19
|
+
else
|
20
|
+
raise InvalidSearchSuffix.new(key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
return @prepared_search
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_operator(key)
|
28
|
+
if m = key.to_s.match(/(.*)_(#{valid_suffixes.join("|")})/)
|
29
|
+
target = m.captures.first
|
30
|
+
operator = operator_for(m.captures.second)
|
31
|
+
return DataMapper::Query::Operator.new(target, operator)
|
32
|
+
else
|
33
|
+
return nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def valid_suffixes
|
38
|
+
return [
|
39
|
+
:gteq,
|
40
|
+
:lteq,
|
41
|
+
:cont
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
def operator_for(suffix)
|
46
|
+
op_map = {
|
47
|
+
gteq: :gte,
|
48
|
+
lteq: :lte,
|
49
|
+
cont: :like
|
50
|
+
}
|
51
|
+
return op_map[suffix.to_sym]
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/upmin/engine.rb
CHANGED
data/lib/upmin/errors.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Upmin
|
2
|
+
class InvalidAction < ArgumentError
|
3
|
+
def initialize(action)
|
4
|
+
super("Invalid action: #{action}")
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class MissingArgument < ArgumentError
|
9
|
+
def initialize(arg)
|
10
|
+
super("Missing argument: #{arg}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ArgumentError < ArgumentError
|
15
|
+
def initialize(arg)
|
16
|
+
super("Invalid argument: #{arg}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class MissingPartial < ::StandardError
|
21
|
+
def initialize(data)
|
22
|
+
super("Could not find a matching partial with the following data: #{data.as_json}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class UnsupportedObjectMapper < ::StandardError
|
27
|
+
def initialize
|
28
|
+
super("The ORM or ODM you are using is not supported. Please create an issue on github if one doesn't exist - https://github.com/upmin/upmin-admin-ruby/issues")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class UninferrableAdminError < NameError
|
33
|
+
def initialize(klass)
|
34
|
+
super("Could not infer an Admin class for #{klass}.")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class UninferrableSourceError < NameError
|
39
|
+
def initialize(klass)
|
40
|
+
super("Could not infer a source for #{klass}.")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/upmin/model.rb
CHANGED
@@ -1,137 +1,306 @@
|
|
1
1
|
module Upmin
|
2
2
|
class Model
|
3
|
+
include Upmin::Engine.routes.url_helpers
|
4
|
+
include Upmin::AutomaticDelegation
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
+
attr_reader :model
|
7
|
+
alias_method :object, :model
|
6
8
|
|
7
|
-
def initialize(
|
8
|
-
self.
|
9
|
-
|
9
|
+
def initialize(model = nil, options = {})
|
10
|
+
if self.class.active_record?
|
11
|
+
self.class.send(:include, Upmin::ActiveRecord::Model)
|
12
|
+
elsif self.class.data_mapper?
|
13
|
+
self.class.send(:include, Upmin::DataMapper::Model)
|
14
|
+
end
|
15
|
+
|
16
|
+
if model.is_a?(Hash)
|
17
|
+
unless model.has_key?(:id)
|
18
|
+
raise ":id or model instance is required."
|
19
|
+
end
|
20
|
+
@model = self.class.find(model[:id])
|
21
|
+
elsif model.nil?
|
22
|
+
@model = self.model_class.new
|
23
|
+
else
|
24
|
+
@model = model
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def path
|
29
|
+
if new_record?
|
30
|
+
return upmin_new_model_path(klass: model_class_name)
|
31
|
+
else
|
32
|
+
return upmin_model_path(klass: model_class_name, id: id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_path
|
37
|
+
return upmin_create_model_path(klass: model_class_name)
|
10
38
|
end
|
11
39
|
|
12
|
-
## Methods for rendering in views
|
13
40
|
def title
|
14
|
-
return "#{
|
41
|
+
return "#{humanized_name(:singular)} # #{id}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def attributes
|
45
|
+
return @attributes if defined?(@attributes)
|
46
|
+
@attributes = []
|
47
|
+
self.class.attributes.each do |attr_name|
|
48
|
+
@attributes << Upmin::Attribute.new(self, attr_name)
|
49
|
+
end
|
50
|
+
return @attributes
|
51
|
+
end
|
52
|
+
|
53
|
+
def associations
|
54
|
+
return @associations if defined?(@associations)
|
55
|
+
@associations = []
|
56
|
+
self.class.associations.each do |assoc_name|
|
57
|
+
@associations << Upmin::Association.new(self, assoc_name)
|
58
|
+
end
|
59
|
+
return @associations
|
15
60
|
end
|
16
61
|
|
62
|
+
def actions
|
63
|
+
return @actions if defined?(@actions)
|
64
|
+
@actions = []
|
65
|
+
self.class.actions.each do |action_name|
|
66
|
+
@actions << Upmin::Action.new(self, action_name)
|
67
|
+
end
|
68
|
+
return @actions
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
###########################################################
|
73
|
+
### Delegated instance methods
|
74
|
+
###########################################################
|
75
|
+
|
76
|
+
# TODO(jon): Delegations here weren't working in 3.2 so this is done with normal old methods.
|
77
|
+
# delegate(:color, to: :class)
|
17
78
|
def color
|
18
|
-
return
|
19
|
-
end
|
20
|
-
|
21
|
-
def
|
22
|
-
return
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
79
|
+
return self.class.color
|
80
|
+
end
|
81
|
+
# delegate(:humanized_name, to: :class)
|
82
|
+
def humanized_name(type = :plural)
|
83
|
+
return self.class.humanized_name(type)
|
84
|
+
end
|
85
|
+
# delegate(:underscore_name, to: :class)
|
86
|
+
def underscore_name
|
87
|
+
return self.class.underscore_name
|
88
|
+
end
|
89
|
+
# delegate(:model_class, to: :class)
|
90
|
+
def model_class
|
91
|
+
return self.class.model_class
|
92
|
+
end
|
93
|
+
# delegate(:model_class_name, to: :class)
|
94
|
+
def model_class_name
|
95
|
+
return self.class.model_class_name
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
###########################################################
|
102
|
+
### Class methods
|
103
|
+
###########################################################
|
104
|
+
|
105
|
+
def Model.count(*args)
|
106
|
+
return model_class.count(*args)
|
107
|
+
end
|
108
|
+
|
109
|
+
def Model.find_class(model)
|
110
|
+
return find_or_create_class(model.to_s)
|
111
|
+
end
|
112
|
+
|
113
|
+
def Model.find_or_create_class(model_name)
|
114
|
+
::Rails.application.eager_load!
|
115
|
+
return "Admin#{model_name}".constantize
|
116
|
+
rescue NameError
|
117
|
+
eval("class ::Admin#{model_name} < Upmin::Model; end")
|
118
|
+
return "Admin#{model_name}".constantize
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns all upmin models.
|
122
|
+
def Model.all
|
123
|
+
all = []
|
124
|
+
Upmin.configuration.models.each do |m|
|
125
|
+
all << find_or_create_class(m.to_s.camelize)
|
59
126
|
end
|
127
|
+
return all
|
128
|
+
end
|
60
129
|
|
61
|
-
|
130
|
+
def Model.model_class
|
131
|
+
@model_class ||= inferred_model_class
|
62
132
|
end
|
63
133
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
return false
|
68
|
-
return false if attr_name == :created_at
|
69
|
-
return false if attr_name == :updated_at
|
70
|
-
# TODO(jon): Add a way to declare which attributes are editable and which are not later.
|
71
|
-
return instance.respond_to?("#{attr_name}=")
|
134
|
+
def Model.model_class?
|
135
|
+
return model_class
|
136
|
+
rescue Upmin::UninferrableSourceError
|
137
|
+
return false
|
72
138
|
end
|
73
139
|
|
74
|
-
|
75
|
-
|
76
|
-
attr_name = attr_name.to_sym
|
77
|
-
# TODO(jon): Add some way to handle exceptions. Probably a custom error that we display.
|
78
|
-
return instance.send(attr_name)
|
140
|
+
def Model.model_class
|
141
|
+
return @model_class ||= inferred_model_class
|
79
142
|
end
|
80
143
|
|
81
|
-
def
|
82
|
-
|
144
|
+
def Model.inferred_model_class
|
145
|
+
name = model_class_name
|
146
|
+
return name.constantize
|
147
|
+
rescue NameError => error
|
148
|
+
raise if name && !error.missing_name?(name)
|
149
|
+
raise Upmin::UninferrableSourceError.new(self)
|
83
150
|
end
|
84
151
|
|
85
|
-
def
|
86
|
-
|
152
|
+
def Model.model_class_name
|
153
|
+
raise NameError if name.nil? || name.demodulize !~ /Admin.+$/
|
154
|
+
return name.demodulize[5..-1]
|
87
155
|
end
|
88
156
|
|
157
|
+
def Model.model_name
|
158
|
+
return ActiveModel::Name.new(model_class)
|
159
|
+
end
|
89
160
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
if type == :unknown && data = association(assoc_name).first
|
95
|
-
type = data.class.name.underscore
|
161
|
+
def Model.humanized_name(type = :plural)
|
162
|
+
names = model_class_name.split(/(?=[A-Z])/)
|
163
|
+
if type == :plural
|
164
|
+
names[names.length-1] = names.last.pluralize
|
96
165
|
end
|
97
|
-
return
|
166
|
+
return names.join(" ")
|
98
167
|
end
|
99
168
|
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
association = association.limit(5)
|
106
|
-
end
|
169
|
+
def Model.underscore_name(type = :singular)
|
170
|
+
if type == :singular
|
171
|
+
return model_class_name.underscore
|
172
|
+
else
|
173
|
+
return model_class_name.pluralize.underscore
|
107
174
|
end
|
108
|
-
return association
|
109
175
|
end
|
110
176
|
|
111
|
-
def
|
112
|
-
|
177
|
+
def Model.search_path
|
178
|
+
return Upmin::Engine.routes.url_helpers.upmin_search_path(klass: model_class_name)
|
179
|
+
end
|
180
|
+
|
181
|
+
def Model.color
|
182
|
+
return @color if defined?(@color)
|
183
|
+
@color = Model.next_color
|
184
|
+
return @color
|
185
|
+
end
|
186
|
+
|
187
|
+
def Model.colors
|
188
|
+
return Upmin.configuration.colors
|
113
189
|
end
|
114
190
|
|
115
|
-
def
|
116
|
-
|
117
|
-
|
191
|
+
def Model.next_color
|
192
|
+
@color_index ||= 0
|
193
|
+
next_color = colors[@color_index]
|
194
|
+
@color_index = (@color_index + 1) % colors.length
|
195
|
+
return next_color
|
196
|
+
end
|
197
|
+
|
198
|
+
# This is not currently used, but could be used to ensure colors are always the same.
|
199
|
+
def Model.color_index
|
200
|
+
return @color_index if defined?(@color_index)
|
201
|
+
@color_index = model_class_name.split("").map(&:ord).inject(:+) % colors.length
|
202
|
+
return @color_index
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
def Model.active_record?
|
207
|
+
if defined?(ActiveRecord)
|
208
|
+
return model_class.superclass == ::ActiveRecord::Base
|
209
|
+
else
|
210
|
+
return false
|
118
211
|
end
|
212
|
+
end
|
119
213
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
214
|
+
def Model.data_mapper?
|
215
|
+
if defined?(DataMapper)
|
216
|
+
return model_class.is_a?(::DataMapper::Model)
|
217
|
+
else
|
218
|
+
return false
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
###########################################################
|
225
|
+
### Customization methods for Admin<Model> classes
|
226
|
+
###########################################################
|
227
|
+
|
228
|
+
# Add a single attribute to upmin attributes.
|
229
|
+
# If this is called before upmin_attributes
|
230
|
+
# the attributes will not include any defaults
|
231
|
+
# attributes.
|
232
|
+
def Model.attribute(attribute = nil)
|
233
|
+
@extra_attrs = [] unless defined?(@extra_attrs)
|
234
|
+
@extra_attrs << attribute.to_sym if attribute
|
235
|
+
end
|
236
|
+
|
237
|
+
# Sets the attributes to the provided attributes # if any are any provided.
|
238
|
+
# If no attributes are provided then the
|
239
|
+
# attributes are set to the default attributes of
|
240
|
+
# the model class.
|
241
|
+
def Model.attributes(*attributes)
|
242
|
+
@extra_attrs = [] unless defined?(@extra_attrs)
|
243
|
+
|
244
|
+
if attributes.any?
|
245
|
+
@attributes = attributes.map{|a| a.to_sym}
|
246
|
+
end
|
247
|
+
@attributes ||= default_attributes
|
248
|
+
|
249
|
+
return (@attributes + @extra_attrs).uniq
|
250
|
+
end
|
251
|
+
|
252
|
+
# Add a single action to upmin actions. If this is called
|
253
|
+
# before upmin_actions the actions will not include any defaults
|
254
|
+
# actions.
|
255
|
+
def Model.action(action)
|
256
|
+
@actions ||= []
|
257
|
+
|
258
|
+
action = action.to_sym
|
259
|
+
@actions << action unless @actions.include?(action)
|
260
|
+
end
|
261
|
+
|
262
|
+
# Sets the upmin_actions to the provided actions if any are
|
263
|
+
# provided.
|
264
|
+
# If no actions are provided, and upmin_actions hasn't been defined,
|
265
|
+
# then the upmin_actions are set to the default actions.
|
266
|
+
# Returns the upmin_actions
|
267
|
+
def Model.actions(*actions)
|
268
|
+
if actions.any?
|
269
|
+
# set the actions
|
270
|
+
@actions = actions.map{|a| a.to_sym}
|
131
271
|
end
|
132
|
-
|
272
|
+
@actions ||= []
|
273
|
+
return @actions
|
133
274
|
end
|
134
275
|
|
135
276
|
|
277
|
+
|
278
|
+
###########################################################
|
279
|
+
### Methods that need to be to be overridden. If the
|
280
|
+
### Model.method_name version of these are ever called it
|
281
|
+
### means that it wasn't overridden, or an instance of
|
282
|
+
### the class hasn't been created yet.
|
283
|
+
###########################################################
|
284
|
+
|
285
|
+
def Model.find(*args)
|
286
|
+
new
|
287
|
+
return find(*args)
|
288
|
+
end
|
289
|
+
|
290
|
+
def Model.default_attributes
|
291
|
+
new
|
292
|
+
return default_attributes
|
293
|
+
end
|
294
|
+
|
295
|
+
def Model.attribute_type(attribute)
|
296
|
+
new
|
297
|
+
return attribute_type(attribute)
|
298
|
+
end
|
299
|
+
|
300
|
+
def Model.associations
|
301
|
+
new
|
302
|
+
return associations
|
303
|
+
end
|
304
|
+
|
136
305
|
end
|
137
306
|
end
|