upmin-admin 0.0.39 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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