admin_it 1.0.1

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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +5 -0
  7. data/README.md +58 -0
  8. data/README_RU.md +52 -0
  9. data/Rakefile +23 -0
  10. data/admin_it.gemspec +38 -0
  11. data/app/assets/fonts/admin_it/FontAwesome.otf +0 -0
  12. data/app/assets/fonts/admin_it/fontawesome-webfont.eot +0 -0
  13. data/app/assets/fonts/admin_it/fontawesome-webfont.svg +414 -0
  14. data/app/assets/fonts/admin_it/fontawesome-webfont.ttf +0 -0
  15. data/app/assets/fonts/admin_it/fontawesome-webfont.woff +0 -0
  16. data/app/assets/fonts/admin_it/glyphicons-halflings-regular.eot +0 -0
  17. data/app/assets/fonts/admin_it/glyphicons-halflings-regular.svg +229 -0
  18. data/app/assets/fonts/admin_it/glyphicons-halflings-regular.ttf +0 -0
  19. data/app/assets/fonts/admin_it/glyphicons-halflings-regular.woff +0 -0
  20. data/app/assets/javascript/admin_it/admin_it.js +89 -0
  21. data/app/assets/javascript/admin_it/bootstrap.min.js +6 -0
  22. data/app/assets/stylesheets/admin_it/admin_it.css +25 -0
  23. data/app/assets/stylesheets/admin_it/bootstrap-theme.min.css +7 -0
  24. data/app/assets/stylesheets/admin_it/bootstrap.min.css +7 -0
  25. data/app/assets/stylesheets/admin_it/font-awesome.min.css +4 -0
  26. data/app/views/admin_it/context/_table.html.slim +38 -0
  27. data/app/views/admin_it/context/_tiles.html.slim +23 -0
  28. data/app/views/admin_it/edit.html.slim +2 -0
  29. data/app/views/admin_it/new.html.slim +2 -0
  30. data/app/views/admin_it/shared/_child.html.slim +15 -0
  31. data/app/views/admin_it/shared/_fields.html.slim +19 -0
  32. data/app/views/admin_it/shared/_filters.html.slim +40 -0
  33. data/app/views/admin_it/shared/_form.html.slim +50 -0
  34. data/app/views/admin_it/shared/_pagination.html.slim +41 -0
  35. data/app/views/admin_it/shared/_toolbar.html.slim +30 -0
  36. data/app/views/admin_it/show.html.slim +6 -0
  37. data/app/views/admin_it/table.html.slim +2 -0
  38. data/app/views/admin_it/tiles.html.slim +2 -0
  39. data/app/views/layouts/admin_it.html.slim +37 -0
  40. data/app/views/layouts/admin_it_dialog.html.slim +8 -0
  41. data/config.ru +7 -0
  42. data/lib/admin_it/config.rb +24 -0
  43. data/lib/admin_it/context/collection_context.rb +239 -0
  44. data/lib/admin_it/context/context.rb +232 -0
  45. data/lib/admin_it/context/show_context.rb +45 -0
  46. data/lib/admin_it/context/single_context.rb +199 -0
  47. data/lib/admin_it/context/table_context.rb +66 -0
  48. data/lib/admin_it/context/tiles_context.rb +31 -0
  49. data/lib/admin_it/context.rb +6 -0
  50. data/lib/admin_it/controller.rb +42 -0
  51. data/lib/admin_it/data/active_record.rb +283 -0
  52. data/lib/admin_it/data/data_behavior.rb +18 -0
  53. data/lib/admin_it/data/hash.rb +27 -0
  54. data/lib/admin_it/data/object.rb +51 -0
  55. data/lib/admin_it/data.rb +24 -0
  56. data/lib/admin_it/definitions.rb +89 -0
  57. data/lib/admin_it/engine.rb +56 -0
  58. data/lib/admin_it/env.rb +37 -0
  59. data/lib/admin_it/errors.rb +5 -0
  60. data/lib/admin_it/field/field.rb +174 -0
  61. data/lib/admin_it/field.rb +1 -0
  62. data/lib/admin_it/filters/entity_filter.rb +4 -0
  63. data/lib/admin_it/filters/field_filter.rb +31 -0
  64. data/lib/admin_it/filters/filter.rb +150 -0
  65. data/lib/admin_it/filters/value_filter.rb +52 -0
  66. data/lib/admin_it/filters.rb +4 -0
  67. data/lib/admin_it/helpers/field.rb +25 -0
  68. data/lib/admin_it/helpers/input.rb +22 -0
  69. data/lib/admin_it/helpers/page.rb +26 -0
  70. data/lib/admin_it/helpers/table.rb +85 -0
  71. data/lib/admin_it/helpers/tiles.rb +17 -0
  72. data/lib/admin_it/helpers/toolbar.rb +40 -0
  73. data/lib/admin_it/helpers/top_menu.rb +39 -0
  74. data/lib/admin_it/helpers.rb +12 -0
  75. data/lib/admin_it/locales/en.yml +14 -0
  76. data/lib/admin_it/locales/ru.yml +14 -0
  77. data/lib/admin_it/renderable.rb +18 -0
  78. data/lib/admin_it/resource.rb +292 -0
  79. data/lib/admin_it/utils.rb +21 -0
  80. data/lib/admin_it/version.rb +5 -0
  81. data/lib/admin_it.rb +19 -0
  82. data/lib/extend_it/array_of.rb +181 -0
  83. data/lib/extend_it/asserts.rb +38 -0
  84. data/lib/extend_it/callbacks.rb +105 -0
  85. data/lib/extend_it/caller.rb +35 -0
  86. data/lib/extend_it/class.rb +47 -0
  87. data/lib/extend_it/dsl.rb +94 -0
  88. data/lib/extend_it/refines.rb +6 -0
  89. data/lib/extend_it/symbolize.rb +39 -0
  90. data/lib/extend_it.rb +5 -0
  91. data/spec/internal/config/database.yml +3 -0
  92. data/spec/internal/config/routes.rb +3 -0
  93. data/spec/internal/db/combustion_test.sqlite +0 -0
  94. data/spec/internal/db/schema.rb +3 -0
  95. data/spec/internal/log/.gitignore +1 -0
  96. data/spec/internal/public/favicon.ico +0 -0
  97. data/spec/lib/context/collection_context_spec.rb +20 -0
  98. data/spec/lib/context/context_spec.rb +28 -0
  99. data/spec/lib/context/single_context_spec.rb +26 -0
  100. data/spec/lib/data/object_spec.rb +29 -0
  101. data/spec/lib/definitions_spec.rb +171 -0
  102. data/spec/lib/field_spec.rb +62 -0
  103. data/spec/lib/resource_spec.rb +39 -0
  104. data/spec/lib/utils_spec.rb +39 -0
  105. data/spec/spec_helper.rb +21 -0
  106. data/spec/support/example_groups/context_example_group.rb +50 -0
  107. data/spec/support/shared_examples/context.rb +2 -0
  108. metadata +337 -0
@@ -0,0 +1,199 @@
1
+ require File.join %w(extend_it dsl)
2
+ require File.join %w(extend_it symbolize)
3
+
4
+ using ExtendIt::Symbolize
5
+
6
+ module AdminIt
7
+ class Section
8
+ extend ExtendIt::Dsl
9
+ include Renderable
10
+ dsl_accessor :name, :display_name
11
+ dsl_boolean :visible
12
+ # dsl_block :render_context
13
+ def fields(*names)
14
+ names.empty? ? @fields ||= [] : @fields = names
15
+ end
16
+ end
17
+
18
+ module Identifiable
19
+ def self.included(base)
20
+ base.extend(ClassMethods)
21
+ end
22
+
23
+ def identity; end
24
+
25
+ protected
26
+
27
+ def context_param
28
+ identity.nil? ? super : "#{super}(#{identity})"
29
+ end
30
+
31
+ module ClassMethods
32
+ end
33
+ end
34
+
35
+ class SingleContext < Context
36
+ class << self
37
+ dsl_block :entity_getter, :entity_saver, :entity_destroyer
38
+ end
39
+
40
+ def self.sections
41
+ (@sections ||= {}).values
42
+ end
43
+
44
+ def self.section(*names, &block)
45
+ @sections ||= {}
46
+ names.ensure_symbols.each do |name|
47
+ if @sections.key?(name)
48
+ section = @sections[name]
49
+ else
50
+ if @sections.empty?
51
+ general = Section.new
52
+ general.name(:general)
53
+ # TODO: require this and other files after I18n config in engine.rb
54
+ #general.display_name(I18n.t('admin_it.collection.no_data'))
55
+ general.display_name('Основные свойства')
56
+ general.fields(*fields.map(&:field_name))
57
+ @sections[:general] = general
58
+ end
59
+ section = Section.new
60
+ section.name(name)
61
+ @sections[name] = section
62
+ end
63
+ section.instance_eval(&block) if block_given?
64
+ end
65
+ end
66
+
67
+ def self.single?
68
+ true
69
+ end
70
+
71
+ def self.path(entity)
72
+ AdminIt::Engine.routes.url_helpers.send(
73
+ "#{resource.name}_path",
74
+ entity
75
+ )
76
+ end
77
+
78
+ class_attr_reader :entity_getter, :entity_saver, :entity_destroyer, :sections
79
+ attr_accessor :entity
80
+
81
+ after_load do |store: {}, params: {}|
82
+ self.section = params[:section] || store[:section]
83
+ end
84
+
85
+ before_save do |params: {}|
86
+ params.merge!(section: section)
87
+ end
88
+
89
+ def values
90
+ return {} if @entity.nil?
91
+ Hash[fields(scope: :readable).map { |f| [f.name, f.read(@entity)] }]
92
+ end
93
+
94
+ def path(_entity: nil)
95
+ _entity ||= entity
96
+ self.class.path(_entity)
97
+ end
98
+
99
+ def section
100
+ @section ||= sections.empty? ? :none : :general
101
+ end
102
+
103
+ def section=(value)
104
+ value = value.downcase.to_sym if value.is_a?(String)
105
+ return unless value.is_a?(Symbol)
106
+ if sections.empty?
107
+ return if section != :none
108
+ else
109
+ return unless sections.map(&:name).include?(value)
110
+ end
111
+ @section = section
112
+ end
113
+
114
+ protected
115
+
116
+ def load_context
117
+ self.entity =
118
+ if entity_getter.nil?
119
+ getter = "#{resource.name}_#{name}_entity".to_sym
120
+ if controller.respond_to?(getter)
121
+ controller.send(getter)
122
+ else
123
+ getter = "#{name}_entity"
124
+ if controller.respond_to?(getter)
125
+ controller.send(getter, entity_class)
126
+ else
127
+ load_entity
128
+ end
129
+ end
130
+ else
131
+ entity_getter.call(controller.params)
132
+ end
133
+ end
134
+
135
+ def load_entity(identity: nil)
136
+ []
137
+ end
138
+ end
139
+
140
+ class SavableSingleContext < SingleContext
141
+ def self.save_action; end
142
+
143
+ def save_entity
144
+ if entity_saver.nil?
145
+ if controller.respond_to?("#{resource.name}_save")
146
+ controller.send("#{resource.name}_save", name)
147
+ elsif controller.respond_to?(:save)
148
+ controller.save(entity_class, name)
149
+ else
150
+ save_entity
151
+ end
152
+ else
153
+ entity_saver.call(controller, name)
154
+ end
155
+ end
156
+
157
+ class_attr_reader :save_action
158
+
159
+ protected
160
+
161
+ def save_entity; end
162
+ end
163
+
164
+ class EditContext < SavableSingleContext
165
+ include Identifiable
166
+
167
+ def self.path(entity)
168
+ AdminIt::Engine.routes.url_helpers.send(
169
+ "edit_#{resource.name}_path", entity
170
+ )
171
+ end
172
+
173
+ def self.save_action
174
+ :update
175
+ end
176
+
177
+ def self.entity_path?
178
+ true
179
+ end
180
+
181
+ class << self
182
+ protected
183
+
184
+ def default_icon
185
+ 'pencil'
186
+ end
187
+ end
188
+ end
189
+
190
+ class NewContext < SavableSingleContext
191
+ def self.path
192
+ AdminIt::Engine.routes.url_helpers.send("new_#{resource.name}_path")
193
+ end
194
+
195
+ def self.save_action
196
+ :create
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,66 @@
1
+ require File.join %w(extend_it dsl)
2
+
3
+ module AdminIt
4
+ class TableContext < CollectionContext
5
+ class << self
6
+ dsl_accessor :page_size, default: 10 do |value|
7
+ value.is_a?(Fixnum) && value > 0 ? value : 10
8
+ end
9
+
10
+ dsl_boolean :actions
11
+
12
+ dsl_block :row
13
+
14
+ protected
15
+
16
+ def default_icon
17
+ 'table'
18
+ end
19
+ end
20
+
21
+ def self.path
22
+ AdminIt::Engine.routes
23
+ .url_helpers.send("table_#{resource.plural}_path")
24
+ end
25
+
26
+ class_attr_reader :page_size, :actions?
27
+
28
+ after_load do |store: {}, params: {}|
29
+ self.page = params[:page] || store[:page]
30
+ end
31
+
32
+ before_save do |params: {}|
33
+ params.merge!(page: page)
34
+ end
35
+
36
+ def pages
37
+ @pages ||= (count.to_f / page_size).ceil
38
+ end
39
+
40
+ def page
41
+ @page ||= 1
42
+ end
43
+
44
+ def page=(value)
45
+ if value.is_a?(String)
46
+ value = case value.downcase
47
+ when 'next' then page + 1
48
+ when 'prev', 'previous' then page - 1
49
+ when 'first' then 1
50
+ when 'last' then pages
51
+ else value.to_i
52
+ end
53
+ end
54
+ if value.is_a?(Fixnum) && value > 0 && value <= pages
55
+ # reset entities enumerator if page changed
56
+ @enumerator = nil if !@enumerator.nil? && value != @page
57
+ @page = value
58
+ end
59
+ @page ||= 1
60
+ end
61
+
62
+ def headers
63
+ Hash[fields.map { |f| [f.name, f.display_name] }]
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,31 @@
1
+ require File.join %w(extend_it dsl)
2
+
3
+ module AdminIt
4
+ class TilesContext < CollectionContext
5
+ class << self
6
+ dsl_accessor :header do |value|
7
+ if value.nil?
8
+ fields.empty? ? nil : fields.first.name
9
+ else
10
+ field = fields.find { |f| f.field_name == value }
11
+ field.nil? ? header(nil) : field.field_name
12
+ end
13
+ end
14
+ end
15
+
16
+ def self.path
17
+ AdminIt::Engine.routes
18
+ .url_helpers.send("tiles_#{resource.plural}_path")
19
+ end
20
+
21
+ class << self
22
+ protected
23
+
24
+ def default_icon
25
+ 'th'
26
+ end
27
+ end
28
+
29
+ class_attr_reader :header
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ require File.join %w(admin_it context context)
2
+ require File.join %w(admin_it context single_context)
3
+ require File.join %w(admin_it context collection_context)
4
+ require File.join %w(admin_it context table_context)
5
+ require File.join %w(admin_it context tiles_context)
6
+ require File.join %w(admin_it context show_context)
@@ -0,0 +1,42 @@
1
+ module AdminIt
2
+ module Controller
3
+ def self.included(base)
4
+ base.class_eval do
5
+ attr_reader :context
6
+ helper_method :context, :resource
7
+ helper AdminIt::Helpers
8
+ helper AdminIt::Engine.routes.url_helpers
9
+
10
+ if AdminIt::Env.pundit?
11
+ collections = @resource.collections.map(&:context_name)
12
+ after_action :verify_authorized, except: collections
13
+ after_action :verify_policy_scoped, only: collections
14
+ end
15
+ end
16
+ end
17
+
18
+ def resource
19
+ self.class.instance_variable_get(:@resource)
20
+ end
21
+
22
+ def redirect_to_default
23
+ redirect_to(resource[resource.default_context].path)
24
+ end
25
+
26
+ private
27
+
28
+ def load_context(context_class)
29
+ @context = context_class.new(self)
30
+ yield if block_given?
31
+ layout = ['admin_it', params[:layout]].compact.join('_')
32
+ if !performed?
33
+ if layout == 'admin_it' && !request.query_parameters.empty?
34
+ redirect_to request.path
35
+ else
36
+ render template: "admin_it/#{context.name}", layout: layout
37
+ end
38
+ end
39
+ @context.save
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,283 @@
1
+ require File.join %w(extend_it class)
2
+
3
+ module AdminIt
4
+ module ActiveRecordData
5
+ module Resource
6
+ def display_name
7
+ entity_class
8
+ .model_name
9
+ .human#(count: 0)
10
+ .split(' ')
11
+ .map { |s| s.mb_chars.capitalize }
12
+ .join(' ')
13
+ end
14
+
15
+ protected
16
+
17
+ def default_fields(&block)
18
+ enum = Enumerator.new do |yielder|
19
+ exclude = []
20
+ entity_class.reflections.each do |name, a|
21
+ f = AdminIt::Field.create(name, entity_class, type: :relation)
22
+ f.assoc = a
23
+ yielder << f
24
+ exclude << "#{name}_id" if a.belongs_to?
25
+ end
26
+ entity_class.columns_hash.each do |name, c|
27
+ next if exclude.include?(name)
28
+ name = name.to_sym
29
+ opts = { type: c.type }
30
+ if name == :id
31
+ opts[:visible] = false
32
+ opts[:writable] = false
33
+ end
34
+ yielder << AdminIt::Field.create(name, entity_class, opts)
35
+ end
36
+ end
37
+ block_given? ? enum.each(&block) : enum
38
+ end
39
+
40
+ def default_filters
41
+ enum = Enumerator.new do |yielder|
42
+ fields.each do |field|
43
+ next if field.type == :relation
44
+ name = "#{field.field_name}_value"
45
+ yielder << AdminIt::ValueFilter.create(name, self, field)
46
+ end
47
+ end
48
+ block_given? ? enum.each(&block) : enum
49
+ end
50
+ end
51
+
52
+ module CollectionContext
53
+ def entities=(value)
54
+ super(value)
55
+ @count = value.count
56
+ end
57
+
58
+ protected
59
+
60
+ def load_entities
61
+ collection =
62
+ if AdminIt::Env.pundit?
63
+ controller.policy_scope(entity_class)
64
+ else
65
+ entity_class.all
66
+ end
67
+ if child?
68
+ collection = collection.where(parent.resource.name => parent.entity)
69
+ end
70
+ sort = {}
71
+ sorting.each do |_sort|
72
+ name, order = _sort.split(':')
73
+ sort[name.to_sym] = order.to_sym
74
+ end
75
+ collection = collection.order(sort) unless sort.empty?
76
+ collection
77
+ end
78
+ end
79
+
80
+ module SingleContext
81
+ protected
82
+
83
+ def load_entity(identity: nil)
84
+ identity ||= controller.params[:id]
85
+ entity = entity_class.find(identity)
86
+ if AdminIt::Env.pundit?
87
+ controller.authorize(entity, "#{name}?")
88
+ end
89
+ if child?
90
+ fields
91
+ .select { |f| f.type == :relation &&
92
+ f.assoc.klass == parent.entity_class }
93
+ .each do |f|
94
+ if f.assoc.collection?
95
+ entity.send(f.name) << parent.entity
96
+ else
97
+ entity.send("#{f.name}=", parent.entity)
98
+ end
99
+ end
100
+ end
101
+ entity
102
+ end
103
+ end
104
+
105
+ module SavableSingleContext
106
+ protected
107
+
108
+ def save_entity
109
+ if AdminIt::Env.pundit?
110
+ controller.authorize(entity, "#{self.class.save_action}?")
111
+ end
112
+ params = controller.params[resource.name]
113
+ fields(scope: :writable).each do |field|
114
+ next unless params.key?(field.name)
115
+ next unless field.writable?
116
+ next if field.type == :relation
117
+ field.write(entity, params[field.name])
118
+ end
119
+ if entity.save
120
+ controller.redirect_to_default
121
+ end
122
+ end
123
+
124
+ def add_child_context(for_resource, context_class: :table)
125
+ child_resource = AdminIt.resources[for_resource]
126
+ return nil if child_resource.nil?
127
+ child_resource[context_class].new(self)
128
+ end
129
+ end
130
+
131
+ module NewContext
132
+ def self.included(base)
133
+ base.after_initialize do
134
+ if child?
135
+ fields
136
+ .select { |f| f.type == :relation &&
137
+ f.assoc.klass == parent.entity_class }
138
+ .each do |f|
139
+ if f.assoc.collection?
140
+ entity.send(f.name) << parent.entity
141
+ else
142
+ entity.send("#{f.name}=", parent.entity)
143
+ end
144
+ f.visible = false
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ protected
151
+
152
+ def load_entity(identity: nil)
153
+ entity = entity_class.new
154
+ if AdminIt::Env.pundit?
155
+ controller.authorize(entity, "#{name}?")
156
+ end
157
+ entity
158
+ end
159
+ end
160
+
161
+ module ShowContext
162
+ def identity
163
+ entity.id
164
+ end
165
+
166
+ protected
167
+
168
+ def destroy
169
+ if AdminIt::Env.pundit?
170
+ controller.authorize(entity, :destroy?)
171
+ end
172
+ if entity.destroy
173
+ controller.redirect_to_default
174
+ end
175
+ end
176
+ end
177
+
178
+ module EditContext
179
+ def identity
180
+ entity.id
181
+ end
182
+ end
183
+
184
+ module TableContext
185
+ def entities
186
+ if @entities.count > page_size
187
+ # limit collection to current page
188
+ @entities = @entities
189
+ .offset(page_size * (page - 1))
190
+ .limit(page_size)
191
+ end
192
+ super
193
+ end
194
+ end
195
+
196
+ module Field
197
+ def self.included(base)
198
+ base.class_eval do
199
+ class << self
200
+ attr_accessor :assoc
201
+
202
+ protected
203
+
204
+ def default_display_name
205
+ entity_class.human_attribute_name(field_name)
206
+ end
207
+ end
208
+ class_attr_reader :assoc
209
+ end
210
+ end
211
+
212
+ protected
213
+
214
+ def read_value(entity)
215
+ value = entity.send(name)
216
+ if type == :relation
217
+ assoc.collection? ? value.map(&:id).to_json : value.id
218
+ else
219
+ value
220
+ end
221
+ end
222
+
223
+ def show_value(entity)
224
+ value = entity.send(name)
225
+ if type == :relation
226
+ resource = AdminIt.resources.values.find do |r|
227
+ r.entity_class == assoc.klass
228
+ end
229
+ return I18n.t('admin_it.relation.no_resource') if resource.nil?
230
+ context = resource.contexts.find { |c| c <= ShowContext }
231
+ return I18n.t('admin_it.relation.no_context') if context.nil?
232
+ if assoc.collection?
233
+ if value.count == 0
234
+ I18n.t('admin_it.collection.no_data')
235
+ else
236
+ context.read(value.first) + ' ...'
237
+ end
238
+ else
239
+ context.read(value)
240
+ end
241
+ else
242
+ value
243
+ end
244
+ end
245
+
246
+ def write_value(entity, value)
247
+ entity.send("#{name}=", value)
248
+ end
249
+ end
250
+
251
+ module ValueFilter
252
+ def all_values(collection = nil, &block)
253
+ enum = Enumerator.new do |yielder|
254
+ field
255
+ .entity_class
256
+ .select(self.class.field.field_name)
257
+ .group(self.class.field.field_name)
258
+ .count
259
+ .each do |v, c|
260
+ yielder << { value: v, count: c }
261
+ end
262
+ end
263
+ block_given? ? enum.each(&block) : enum
264
+ end
265
+
266
+ def apply(collection)
267
+ return collection if @values.empty?
268
+ binding = []
269
+ conditions = ''
270
+ if @values.size == 1 && @values[0].nil?
271
+ conditions = "#{field.field_name} IS NULL"
272
+ else
273
+ conditions = "#{field.field_name} IN (?)"
274
+ binding << @values.select { |v| !v.nil? }
275
+ if @values.any? { |v| v.nil? }
276
+ conditions += " OR #{field.field_name} IS NULL"
277
+ end
278
+ end
279
+ collection = collection.where(conditions, *binding)
280
+ end
281
+ end
282
+ end
283
+ end
@@ -0,0 +1,18 @@
1
+ module AdminIt
2
+ module DataBehavior
3
+ private
4
+
5
+ def import_data_module(base)
6
+ @data_module = AdminIt.data_module(@entity_class)
7
+ return unless @data_module.is_a?(Module)
8
+ parents.reverse.each do |mod|
9
+ next if mod.name.nil?
10
+ begin
11
+ import_module = @data_module.const_get(mod.name.split('::').last)
12
+ include(import_module) if import_module.is_a?(Module)
13
+ rescue NameError
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ module AdminIt
2
+ module HashData
3
+ module Context
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def load_fields
10
+ []
11
+ end
12
+ end
13
+ end
14
+
15
+ module Field
16
+ protected
17
+
18
+ def read_value(entity)
19
+ entity[name]
20
+ end
21
+
22
+ def write_value(entity, value)
23
+ entity[name] = value
24
+ end
25
+ end
26
+ end
27
+ end