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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -14
  3. data/Rakefile +24 -15
  4. data/app/assets/javascripts/upmin/application.js +0 -1
  5. data/app/assets/stylesheets/upmin/base.css.scss +4 -0
  6. data/app/assets/stylesheets/upmin/instances.css.scss +11 -1
  7. data/app/controllers/upmin/models_controller.rb +52 -42
  8. data/app/views/layouts/upmin/_navbar.html.haml +3 -3
  9. data/app/views/layouts/upmin/application.html.haml +2 -1
  10. data/app/views/upmin/models/new.html.haml +3 -3
  11. data/app/views/upmin/models/search.html.haml +5 -4
  12. data/app/views/upmin/models/show.html.haml +3 -3
  13. data/app/views/upmin/partials/actions/_action.html.haml +6 -21
  14. data/app/views/upmin/partials/associations/_associations.html.haml +8 -10
  15. data/app/views/upmin/partials/attributes/_boolean.html.haml +8 -6
  16. data/app/views/upmin/partials/attributes/_datetime.html.haml +38 -36
  17. data/app/views/upmin/partials/attributes/_decimal.html.haml +10 -0
  18. data/app/views/upmin/partials/attributes/_float.html.haml +10 -6
  19. data/app/views/upmin/partials/attributes/_integer.html.haml +10 -6
  20. data/app/views/upmin/partials/attributes/_progress_bar.html.haml +1 -0
  21. data/app/views/upmin/partials/attributes/_string.html.haml +17 -6
  22. data/app/views/upmin/partials/attributes/_text.html.haml +8 -6
  23. data/app/views/upmin/partials/attributes/_unknown.html.haml +5 -3
  24. data/app/views/upmin/partials/models/_model.html.haml +18 -46
  25. data/app/views/upmin/partials/models/_new_model.html.haml +9 -31
  26. data/app/views/upmin/partials/parameters/_block_parameter.haml +0 -0
  27. data/app/views/upmin/partials/parameters/_opt_parameter.html.haml +14 -0
  28. data/app/views/upmin/partials/parameters/_req_parameter.html.haml +4 -0
  29. data/app/views/upmin/partials/search_boxes/_ransack_search_box.html.haml +2 -3
  30. data/app/views/upmin/partials/search_results/_results.html.haml +9 -2
  31. data/lib/upmin/action.rb +50 -0
  32. data/lib/upmin/active_record/association.rb +47 -0
  33. data/lib/upmin/active_record/model.rb +54 -0
  34. data/lib/upmin/active_record/query.rb +12 -0
  35. data/lib/upmin/admin.rb +24 -2
  36. data/lib/upmin/association.rb +73 -0
  37. data/lib/upmin/attribute.rb +87 -0
  38. data/lib/upmin/automatic_delegation.rb +76 -0
  39. data/lib/upmin/configuration.rb +103 -0
  40. data/lib/upmin/data_mapper/association.rb +57 -0
  41. data/lib/upmin/data_mapper/model.rb +62 -0
  42. data/lib/upmin/data_mapper/query.rb +57 -0
  43. data/lib/upmin/engine.rb +2 -0
  44. data/lib/upmin/errors.rb +43 -0
  45. data/lib/upmin/model.rb +267 -98
  46. data/lib/upmin/parameter.rb +43 -0
  47. data/lib/upmin/query.rb +51 -0
  48. data/lib/upmin/railtie.rb +11 -1
  49. data/lib/upmin/railties/active_record.rb +5 -50
  50. data/lib/upmin/railties/data_mapper.rb +18 -0
  51. data/lib/upmin/railties/render.rb +34 -98
  52. data/lib/upmin/railties/render_helpers.rb +119 -53
  53. data/lib/upmin/version.rb +1 -1
  54. data/spec/factories/factories.rb +6 -0
  55. data/spec/features/action_spec.rb +39 -46
  56. data/spec/features/edit_model_spec.rb +4 -2
  57. data/spec/features/navbar_spec.rb +48 -0
  58. data/spec/features/new_model_spec.rb +1 -0
  59. data/spec/features/search_spec.rb +7 -4
  60. data/spec/lib/configuration_spec.rb +60 -0
  61. data/spec/spec_helper.rb +14 -8
  62. metadata +25 -7
  63. data/app/assets/javascripts/upmin/moment.js +0 -2856
  64. data/app/helpers/upmin/instances_helper.rb +0 -13
  65. data/app/views/upmin/partials/attributes/_nilable.html.haml +0 -14
  66. data/app/views/upmin/partials/search_results/_result.html.haml +0 -8
  67. 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
@@ -3,5 +3,7 @@
3
3
  module Upmin
4
4
  class Engine < ::Rails::Engine
5
5
  isolate_namespace Upmin
6
+
7
+ config.autoload_paths << "#{::Rails.root}/app/upmin/models"
6
8
  end
7
9
  end
@@ -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
@@ -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
- attr_accessor :instance
5
- attr_accessor :klass
6
+ attr_reader :model
7
+ alias_method :object, :model
6
8
 
7
- def initialize(instance, options = {})
8
- self.instance = instance
9
- self.klass = Upmin::Klass.find(instance.class.name)
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 "#{klass.humanized_name(:singular)} # #{instance.id}"
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 klass.color
19
- end
20
-
21
- def path_hash
22
- return {
23
- klass: klass.name,
24
- id: instance.id
25
- }
26
- end
27
-
28
- def new_record?
29
- return instance.new_record?
30
- end
31
-
32
- ## Methods for getting attributes, associations, etc and anything relevant to them.
33
-
34
-
35
- # Returns the type of an attribute. If it is nil and we can't
36
- # figure it out from the db columns we just fall back to
37
- # :unknown
38
- def attribute_type(attr_name)
39
- type = klass.attribute_type(attr_name)
40
-
41
- if type == :unknown
42
- # See if we can deduce it by looking at the data
43
- data = attribute(attr_name)
44
- class_sym = data.class.to_s.underscore.to_sym
45
- if class_sym == :false_class || class_sym == :true_class
46
- type = :boolean
47
- elsif class_sym == :nil_class
48
- type = :unknown
49
- elsif class_sym == :fixnum
50
- type = :integer
51
- elsif class_sym == :big_decimal
52
- type = :decimal
53
- elsif class_sym == :"active_support/time_with_zone"
54
- type = :datetime
55
- else
56
- # This should prevent any classes from being skipped, but we may not have an exhaustive list yet.
57
- type = class_sym
58
- end
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
- return type
130
+ def Model.model_class
131
+ @model_class ||= inferred_model_class
62
132
  end
63
133
 
64
- # Returns whether or not the attr_name is an attribute that can be edited.
65
- def attribute_editable?(attr_name)
66
- attr_name = attr_name.to_sym
67
- return false if attr_name == :id
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
- # Returns the value of the attr_name method
75
- def attribute(attr_name)
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 attribute_form_id(attr_name)
82
- return "#{klass.name.underscore}_#{attr_name}"
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 attribute_label_name(attr_name)
86
- return attr_name.to_s.gsub(/_/, " ").capitalize
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
- # Returns the type of an association. If we can't figure it
91
- # out we fall back to :unknown
92
- def association_type(assoc_name)
93
- type = klass.association_type(assoc_name)
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 type
166
+ return names.join(" ")
98
167
  end
99
168
 
100
- def association(assoc_name, options = {})
101
- association = instance.send(assoc_name)
102
- if association.respond_to?(:each)
103
- # We have a collection, at least we hope we do.
104
- if options[:limit] && association.respond_to?(:limit)
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 action_parameters(action)
112
- instance.method(action).parameters
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 perform_action(action, arguments)
116
- unless klass.actions.include?(action.to_sym)
117
- raise "Invalid action: #{action}"
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
- params = action_parameters(action)
121
- params_array = []
122
- params.each do |param_type, param_name|
123
- if param_type == :req
124
- raise "Missing argument: #{param_name}" unless arguments[param_name]
125
- params_array << arguments[param_name]
126
- elsif param_type == :opt
127
- params_array << arguments[param_name] if arguments[param_name]
128
- else # :block or ??
129
- next
130
- end
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
- return instance.send(action, *params_array)
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