tiun 0.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.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/TODO +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/tiun +5 -0
- data/lib/config/routes.rb +16 -0
- data/lib/layouts/tiun.html.erb +10 -0
- data/lib/tiun/actor/validate.rb +9 -0
- data/lib/tiun/actor.rb +34 -0
- data/lib/tiun/attributes.rb +33 -0
- data/lib/tiun/autocontroller.rb.erb +18 -0
- data/lib/tiun/autolistserializer.rb.erb +9 -0
- data/lib/tiun/automigration.rb.erb +11 -0
- data/lib/tiun/automodel.rb.erb +7 -0
- data/lib/tiun/autopolicy.rb.erb +5 -0
- data/lib/tiun/autoserializer.rb.erb +9 -0
- data/lib/tiun/base.rb +371 -0
- data/lib/tiun/cli.rb +88 -0
- data/lib/tiun/core_controller.rb +6 -0
- data/lib/tiun/core_helper.rb +13 -0
- data/lib/tiun/engine.rb +35 -0
- data/lib/tiun/list_serializer.rb +20 -0
- data/lib/tiun/meta_controller.rb +13 -0
- data/lib/tiun/migration.rb +105 -0
- data/lib/tiun/mixins.rb +48 -0
- data/lib/tiun/model.rb +108 -0
- data/lib/tiun/policy.rb +71 -0
- data/lib/tiun/serializer.rb +31 -0
- data/lib/tiun/version.rb +5 -0
- data/lib/tiun.rb +491 -0
- data/tiun.gemspec +54 -0
- metadata +343 -0
data/lib/tiun/model.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'tiun/version'
|
2
|
+
|
3
|
+
module Tiun::Model
|
4
|
+
# +tiun+ sets up tiuner for the model. This exports corresponding record fields to default
|
5
|
+
# dashboard method, which loads the react component. When the model has been set up, the method
|
6
|
+
# returns the compiled data of the model.
|
7
|
+
#
|
8
|
+
# Examples:
|
9
|
+
#
|
10
|
+
# tiun
|
11
|
+
#
|
12
|
+
# Model.tiun
|
13
|
+
#
|
14
|
+
def tiun
|
15
|
+
## return self.instance_variable_get(:@tiun) if self.instance_variables.include?(:@tiun)
|
16
|
+
|
17
|
+
## self.instance_variable_set(:@tiun, { fields: _tiun_parse_model})
|
18
|
+
|
19
|
+
## tiuns = self.class.instance_variables.include?(:@tiun) && self.class.instance_variable_get(:@tiuns) || []
|
20
|
+
## tiuns << self
|
21
|
+
## self.class.instance_variable_set(:@tiuns, tiuns)
|
22
|
+
#
|
23
|
+
# belongs_to, has_many, has_one
|
24
|
+
end
|
25
|
+
|
26
|
+
# +tiuns+ returns lists of the tiuned models. In case the list is absent returns blank
|
27
|
+
# +Array+.
|
28
|
+
#
|
29
|
+
# Examples:
|
30
|
+
#
|
31
|
+
# Model.tiuns # => [ Model ]
|
32
|
+
#
|
33
|
+
# ActiveRecord::Base.tiuns # => []
|
34
|
+
#
|
35
|
+
def tiuns
|
36
|
+
self.class.instance_variable_get(:@tiuns) || []
|
37
|
+
end
|
38
|
+
|
39
|
+
# {"id"=>#<ActiveModel::Type::Integer:0x00007fbd4365de18 @limit=4, @precision=nil, @range=-2147483648...2147483648, @scale=nil>,
|
40
|
+
# "date"=>#<ActiveModel::Type::String:0x00007fbd4363bb38 @false="f", @limit=nil, @precision=nil, @scale=nil, @true="t">,
|
41
|
+
# "language_code"=>#<ActiveModel::Type::String:0x00007fbd4363bb38 @false="f", @limit=nil, @precision=nil, @scale=nil, @true="t">,
|
42
|
+
# "alphabeth_code"=>#<ActiveModel::Type::String:0x00007fbd4363bb38 @false="f", @limit=nil, @precision=nil, @scale=nil, @true="t">,
|
43
|
+
# "created_at"=>#<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Timestamp:0x00007fbd4363f0f8 @limit=nil, @precision=nil, @scale=nil>,
|
44
|
+
# "updated_at"=>#<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Timestamp:0x00007fbd4363f0f8 @limit=nil, @precision=nil, @scale=nil>,
|
45
|
+
# "place_id"=>#<ActiveModel::Type::Integer:0x00007fbd4365de18 @limit=4, @precision=nil, @range=-2147483648...2147483648, @scale=nil>,
|
46
|
+
# "author_name"=>#<ActiveModel::Type::String:0x00007fbd4363bb38 @false="f", @limit=nil, @precision=nil, @scale=nil, @true="t">,
|
47
|
+
# "council"=>#<ActiveModel::Type::String:0x00007fbd4363bb38 @false="f", @limit=nil, @precision=nil, @scale=nil, @true="t">,
|
48
|
+
# "licit"=>#<ActiveModel::Type::Boolean:0x00007fbd4365d3f0 @limit=nil, @precision=nil, @scale=nil>,
|
49
|
+
# "meta"=>#<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb:0x00007fbd4365cc70 @limit=nil, @precision=nil, @scale=nil>}
|
50
|
+
#
|
51
|
+
# def attribute_types
|
52
|
+
# binding.pry
|
53
|
+
#Tiun.attribute_types_for(self).attribute_map.reduce({}) {|ats, a| ats.merge(a.name => a.type)}
|
54
|
+
# super
|
55
|
+
# @_tiun_attribute_types ||= Tiun.attribute_types_for(self) || super
|
56
|
+
# end
|
57
|
+
|
58
|
+
# Specify range to return
|
59
|
+
def range range
|
60
|
+
offset(range.begin).limit(range.end - range.begin + 1)
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
# :nodoc:
|
66
|
+
def _tiun_parse_model
|
67
|
+
self.attribute_types.map do |( name, attr )|
|
68
|
+
if !["created_at", "updated_at"].include?( name )
|
69
|
+
kind = case attr.class.to_s.split("::").last
|
70
|
+
when /Integer|SQLite3Integer/
|
71
|
+
:integer
|
72
|
+
when "String"
|
73
|
+
:string
|
74
|
+
when "Text"
|
75
|
+
:text
|
76
|
+
when /DateTime|TimeZoneConverter/
|
77
|
+
:datetime
|
78
|
+
when "Date"
|
79
|
+
:date
|
80
|
+
when "Time"
|
81
|
+
:time
|
82
|
+
when "Boolean"
|
83
|
+
:boolean
|
84
|
+
else
|
85
|
+
end
|
86
|
+
|
87
|
+
if kind
|
88
|
+
props = { type: kind }
|
89
|
+
props[ :size ] = attr.limit if attr.limit
|
90
|
+
|
91
|
+
[name.to_sym, props]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end.compact.to_h
|
95
|
+
rescue ActiveRecord::ConnectionNotEstablished
|
96
|
+
[]
|
97
|
+
end
|
98
|
+
|
99
|
+
#TODO
|
100
|
+
#defaults fields: :user
|
101
|
+
# tiun as: :branch /as: :is
|
102
|
+
# include user(without *_at)/all fields (to list/form),
|
103
|
+
# all scopes (to list),
|
104
|
+
# all havings - has_many/ones (to form)
|
105
|
+
# tiunable_by :field/s - for text search by this field/s
|
106
|
+
end
|
107
|
+
|
108
|
+
Model = Tiun::Model
|
data/lib/tiun/policy.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module Tiun::Policy
|
2
|
+
class NotAuthorizedError < StandardError; end
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
attr_reader :user, :record
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def all?
|
15
|
+
default?
|
16
|
+
end
|
17
|
+
|
18
|
+
def index?
|
19
|
+
default?
|
20
|
+
end
|
21
|
+
|
22
|
+
def show?
|
23
|
+
scope.where(id: record.id).exists?
|
24
|
+
end
|
25
|
+
|
26
|
+
def create?
|
27
|
+
default?
|
28
|
+
end
|
29
|
+
|
30
|
+
def new?
|
31
|
+
default?
|
32
|
+
end
|
33
|
+
|
34
|
+
def update?
|
35
|
+
default?
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy?
|
39
|
+
default?
|
40
|
+
end
|
41
|
+
|
42
|
+
def scope
|
43
|
+
defined?(Pundit) && Pundit.policy_scope!(user, record.class) || ActiveRecord::Base
|
44
|
+
end
|
45
|
+
|
46
|
+
class Scope
|
47
|
+
attr_reader :user, :scope
|
48
|
+
|
49
|
+
def initialize(user, scope)
|
50
|
+
@user = user
|
51
|
+
@scope = scope
|
52
|
+
end
|
53
|
+
|
54
|
+
def resolve
|
55
|
+
scope
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def initialize user, record
|
62
|
+
@user = user
|
63
|
+
@record = record
|
64
|
+
end
|
65
|
+
|
66
|
+
def default?
|
67
|
+
user.respond_to?(:admin?) && user.admin?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Policy = Tiun::Policy
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ::Tiun::Serializer
|
2
|
+
class UndefinedModelError < StandardError; end
|
3
|
+
|
4
|
+
def self.included kls
|
5
|
+
kls.class_eval do
|
6
|
+
def initialize model = nil
|
7
|
+
raise UndefinedModelError if !model
|
8
|
+
|
9
|
+
@model = model
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_json *args
|
15
|
+
serializable_hash
|
16
|
+
end
|
17
|
+
|
18
|
+
def serializable_hash
|
19
|
+
binding.pry
|
20
|
+
{
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json *args
|
25
|
+
binding.pry
|
26
|
+
@objects.jsonize(context)
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Serializer = ::Tiun::Serializer
|
data/lib/tiun/version.rb
ADDED
data/lib/tiun.rb
ADDED
@@ -0,0 +1,491 @@
|
|
1
|
+
begin
|
2
|
+
require 'pry'
|
3
|
+
rescue NameError, LoadError
|
4
|
+
end
|
5
|
+
require 'erb'
|
6
|
+
require 'action_controller'
|
7
|
+
require 'active_record'
|
8
|
+
|
9
|
+
require "tiun/mixins"
|
10
|
+
require "tiun/version"
|
11
|
+
require "tiun/migration"
|
12
|
+
require "tiun/attributes"
|
13
|
+
require "tiun/base"
|
14
|
+
require "tiun/core_helper"
|
15
|
+
|
16
|
+
module Tiun
|
17
|
+
class NoRailsError < StandardError ;end
|
18
|
+
class InvalidControllerError < StandardError ;end
|
19
|
+
class InvalidModelError < StandardError ;end
|
20
|
+
# extend ActiveSupport::Concern
|
21
|
+
extend Tiun::Migration
|
22
|
+
extend Tiun::Attributes
|
23
|
+
|
24
|
+
MAP = {
|
25
|
+
'get' => {
|
26
|
+
%r{(?:/(?<c>[^:/]+)).json} => 'index',
|
27
|
+
%r{(?:/(?<c>[^/]+)/:[^/]+).json} => 'show',
|
28
|
+
},
|
29
|
+
'post' => 'create',
|
30
|
+
'patch' => 'update',
|
31
|
+
'put' => 'update',
|
32
|
+
'delete' => 'destroy'
|
33
|
+
}
|
34
|
+
|
35
|
+
TYPE_MAP = {
|
36
|
+
"string" => "string",
|
37
|
+
"sequence" => "integer",
|
38
|
+
"uri" => "string",
|
39
|
+
"list" => nil,
|
40
|
+
"json" => "jsonb",
|
41
|
+
"enum" => "string",
|
42
|
+
}
|
43
|
+
|
44
|
+
TEMPLATES = {
|
45
|
+
model: ERB.new(IO.read(File.join(File.dirname(__FILE__), "tiun", "automodel.rb.erb"))),
|
46
|
+
policy: ERB.new(IO.read(File.join(File.dirname(__FILE__), "tiun", "autopolicy.rb.erb"))),
|
47
|
+
controller: ERB.new(IO.read(File.join(File.dirname(__FILE__), "tiun", "autocontroller.rb.erb"))),
|
48
|
+
# list_serializer: ERB.new(IO.read(File.join(File.dirname(__FILE__), "tiun", "autolistserializer.rb.erb"))),
|
49
|
+
# serializer: ERB.new(IO.read(File.join(File.dirname(__FILE__), "tiun", "autoserializer.rb.erb")))
|
50
|
+
}
|
51
|
+
|
52
|
+
class << self
|
53
|
+
def setup
|
54
|
+
if defined?(::Rails) && ::Rails.root && !@config
|
55
|
+
files = Dir.glob(::Rails.root&.join("config", "tiun", "*.{yml,yaml}")) |
|
56
|
+
Dir.glob(::Rails.root&.join("config", "tiun.{yml,yaml}"))
|
57
|
+
|
58
|
+
setup_with(*files)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def setup_if_not
|
63
|
+
@setup ||= setup
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_with *files
|
67
|
+
setup_migrations
|
68
|
+
|
69
|
+
files.each do |file|
|
70
|
+
config = append_config(file)
|
71
|
+
# load_error_codes_from( config )
|
72
|
+
load_types_from(config)
|
73
|
+
load_defaults_from(config)
|
74
|
+
%i(model controller policy).each do |kind|
|
75
|
+
instance_variable_set("@#{kind.to_s.pluralize}", parse_objects(kind, config))
|
76
|
+
end
|
77
|
+
load_routes_from(config)
|
78
|
+
end
|
79
|
+
|
80
|
+
# validates
|
81
|
+
config
|
82
|
+
end
|
83
|
+
|
84
|
+
def kind_for context
|
85
|
+
context.methods.reduce(nil) { |k, m| k || m.kind }
|
86
|
+
end
|
87
|
+
|
88
|
+
def model_name_for context
|
89
|
+
if type = find_type(kind_for(context))
|
90
|
+
type.model || type.name
|
91
|
+
else
|
92
|
+
context.model ||
|
93
|
+
%r{(?:/(?<c>[^/]+)/:[^/]+|/(?<c>[^:/]+)).json} =~ context.path && c ||
|
94
|
+
context.name.split(".").first
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def controller_name_for context
|
99
|
+
if type = find_type(kind_for(context))
|
100
|
+
type.controller || type.model || type.name
|
101
|
+
else
|
102
|
+
context.controller ||
|
103
|
+
%r{^(?:(?<c>.+)/:[^/]+|/(?<c>[^:]+)).json} =~ context.path && c ||
|
104
|
+
context.name.split(".").first
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def model_title_for context
|
109
|
+
name = model_name_for(context)
|
110
|
+
|
111
|
+
name ? name.singularize.camelize : raise(InvalidModelError)
|
112
|
+
end
|
113
|
+
|
114
|
+
def controller_title_for context
|
115
|
+
name = controller_name_for(context)
|
116
|
+
|
117
|
+
name ? name.pluralize.camelize + 'Controller' : raise(InvalidControllerError)
|
118
|
+
end
|
119
|
+
|
120
|
+
def controller_default_arg_for context
|
121
|
+
/:(?<arg>[^\.]+)/ =~ context.path
|
122
|
+
|
123
|
+
arg
|
124
|
+
end
|
125
|
+
|
126
|
+
def route_title_for context
|
127
|
+
name = controller_name_for(context)
|
128
|
+
|
129
|
+
name ? name.pluralize.tableize : raise(InvalidControllerError)
|
130
|
+
end
|
131
|
+
|
132
|
+
def table_title_for context
|
133
|
+
context.table || model_name_for(context).tableize
|
134
|
+
end
|
135
|
+
|
136
|
+
def table_title_for type
|
137
|
+
type.name.tableize
|
138
|
+
end
|
139
|
+
|
140
|
+
def policy_title_for context
|
141
|
+
context.policy || model_name_for(context).singularize.camelize + "Policy"
|
142
|
+
end
|
143
|
+
|
144
|
+
# def serializer_title_for context
|
145
|
+
# context.serializer || model_name_for(context).singularize.camelize + "Serializer"
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# def list_serializer_title_for context
|
149
|
+
# context.list_serializer || model_name_for(context).singularize.camelize + "ListSerializer"
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# find type record in type record table for last version of
|
153
|
+
#
|
154
|
+
def find_type type_names_in
|
155
|
+
type_names = "#{type_names_in}".split(/\s+/)
|
156
|
+
|
157
|
+
types.reduce(nil) do |t, type|
|
158
|
+
type_names.include?(type.name) && (!t || !t.version || type.version && t.version < type.version) ? type : t
|
159
|
+
end unless type_names.blank?
|
160
|
+
end
|
161
|
+
|
162
|
+
# +type_attributes_for+ renders attributes array for the type name or type itself specified,
|
163
|
+
# if no type name has been found, it returns a blank array.
|
164
|
+
#
|
165
|
+
def type_attributes_for type_name_in
|
166
|
+
type = type_name_in.is_a?(OpenStruct) ? type_name_in : find_type(type_name_in)
|
167
|
+
|
168
|
+
return [] unless type
|
169
|
+
|
170
|
+
type.fields.map do |x|
|
171
|
+
if sub = Tiun.find_type(x.kind)
|
172
|
+
{ x.name => type_attributes_for(sub) }
|
173
|
+
else
|
174
|
+
x.name
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def detect_type type_in
|
180
|
+
type = TYPE_MAP[type_in]
|
181
|
+
type || !type.nil? && "reference" || nil
|
182
|
+
#type_in.split(/\s+/).reject {|x|x =~ /^</}.map do |type_tmp|
|
183
|
+
# type = TYPE_MAP[type_tmp] #.keys.find {|key| key == type_tmp}
|
184
|
+
# type || !type.nil? && "reference" || nil
|
185
|
+
#end.compact.uniq.join("_")
|
186
|
+
end
|
187
|
+
|
188
|
+
def load_types_from config
|
189
|
+
@types = types | (config.types || [])
|
190
|
+
end
|
191
|
+
|
192
|
+
def action_names_for context
|
193
|
+
actions = (context["methods"] || {}).map do |method|
|
194
|
+
method_name = method.name
|
195
|
+
rule = MAP[method_name]
|
196
|
+
|
197
|
+
action = rule.is_a?(String) && rule || rule.reduce(nil) do |a, (re, action)|
|
198
|
+
a || context.path =~ re && action || nil
|
199
|
+
end
|
200
|
+
|
201
|
+
# TODO validated types
|
202
|
+
if ! action
|
203
|
+
error :no_action_detected_for_resource_method, { name: context.name, method: method_name }
|
204
|
+
end
|
205
|
+
|
206
|
+
action ? [action, method] : nil
|
207
|
+
end.compact.to_h
|
208
|
+
|
209
|
+
if actions.blank?
|
210
|
+
error :no_valid_method_defined_for_resource, { name: context.name }
|
211
|
+
end
|
212
|
+
|
213
|
+
actions
|
214
|
+
end
|
215
|
+
|
216
|
+
def string_eval string, name
|
217
|
+
tokens = name.split("::")[0...-1]
|
218
|
+
default = tokens[0].blank? && Object || Object.const_get(tokens[0])
|
219
|
+
|
220
|
+
(tokens[1..-1] || []).reduce(default) do |o, token|
|
221
|
+
o.constants.include?(token.to_sym) && o.const_get(token) || o.const_set(token, Module.new)
|
222
|
+
end
|
223
|
+
|
224
|
+
eval(string)
|
225
|
+
end
|
226
|
+
|
227
|
+
def config_reduce config, default
|
228
|
+
config.resources.reduce(default) do |res, context|
|
229
|
+
if context.name.is_a?(String)
|
230
|
+
yield(res, context.name, context)
|
231
|
+
else
|
232
|
+
res
|
233
|
+
end
|
234
|
+
end
|
235
|
+
rescue NoMethodError
|
236
|
+
error :no_resources_section_defined_in_config, {config: config, default: default}
|
237
|
+
|
238
|
+
[]
|
239
|
+
end
|
240
|
+
|
241
|
+
def load_defaults_from config
|
242
|
+
@defaults = defaults.to_h.merge(config.defaults.to_h).to_os
|
243
|
+
end
|
244
|
+
|
245
|
+
def parse_objects kind, config
|
246
|
+
config_reduce(config, send(kind.to_s.pluralize)) do |res, name, context|
|
247
|
+
object_name = send("#{kind}_title_for", context)
|
248
|
+
|
249
|
+
unless search_for(kind.to_s.pluralize, object_name)
|
250
|
+
object_in = constantize(object_name)
|
251
|
+
code = TEMPLATES[kind].result(binding)
|
252
|
+
object = string_eval(code, object_name)
|
253
|
+
|
254
|
+
res | [{ name: object_name, code: code, const: object }.to_os]
|
255
|
+
else
|
256
|
+
res
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def load_routes_from config
|
262
|
+
@routes =
|
263
|
+
config_reduce(config, routes) do |r, name, context|
|
264
|
+
controller = route_title_for(context)
|
265
|
+
actions = action_names_for(context)
|
266
|
+
|
267
|
+
actions.reduce(r) do |res, (action, method)|
|
268
|
+
/(\.(?<format>[^.]+))$/ =~ context.path
|
269
|
+
|
270
|
+
path =
|
271
|
+
/(?<pre>.*)<(?<key>\w+)>(?<post>.*)/ =~ context.path &&
|
272
|
+
"#{pre}:#{key}#{post}" || context.path
|
273
|
+
|
274
|
+
if res.select {|x| x[:uri] == path && x[:kind] == action }.blank?
|
275
|
+
attrs = { uri: path, path: "#{controller}##{action}", kind: method.name }
|
276
|
+
attrs = attrs.merge(options: {defaults: { format: format }, constraints: { format: format }}) if format
|
277
|
+
|
278
|
+
res | [attrs]
|
279
|
+
else
|
280
|
+
res
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def default_route
|
287
|
+
{
|
288
|
+
uri: '/meta.json',
|
289
|
+
path: 'meta#index',
|
290
|
+
kind: 'get',
|
291
|
+
options: { defaults: { format: 'json' }, constraints: { format: 'json' }}
|
292
|
+
}
|
293
|
+
end
|
294
|
+
|
295
|
+
def draw_routes e
|
296
|
+
setup_if_not
|
297
|
+
routes.each do |route|
|
298
|
+
attrs = { route[:uri] => route[:path] }.merge(route[:options])
|
299
|
+
e.send(route[:kind], **attrs)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def search_for kind, value
|
304
|
+
send(kind).find {|x| x.name == value }
|
305
|
+
end
|
306
|
+
|
307
|
+
def search_all_for kind, value
|
308
|
+
send(kind).select {|x| x.name == value }
|
309
|
+
end
|
310
|
+
|
311
|
+
def error_codes
|
312
|
+
@error_codes ||= []
|
313
|
+
end
|
314
|
+
|
315
|
+
def types
|
316
|
+
@types ||= []
|
317
|
+
end
|
318
|
+
|
319
|
+
def models
|
320
|
+
@models ||= []
|
321
|
+
end
|
322
|
+
|
323
|
+
def policies
|
324
|
+
@policies ||= []
|
325
|
+
end
|
326
|
+
|
327
|
+
# def serializers
|
328
|
+
# @serializers ||= []
|
329
|
+
# end
|
330
|
+
#
|
331
|
+
# def list_serializers
|
332
|
+
# @list_serializers ||= []
|
333
|
+
# end
|
334
|
+
#
|
335
|
+
def controllers
|
336
|
+
@controllers ||= []
|
337
|
+
end
|
338
|
+
|
339
|
+
def routes
|
340
|
+
@routes ||= [default_route]
|
341
|
+
end
|
342
|
+
|
343
|
+
def config
|
344
|
+
@config ||= {}
|
345
|
+
end
|
346
|
+
|
347
|
+
def defaults
|
348
|
+
@defaults ||= {}.to_os
|
349
|
+
end
|
350
|
+
|
351
|
+
def errors
|
352
|
+
@errors ||= []
|
353
|
+
end
|
354
|
+
|
355
|
+
def append_config file
|
356
|
+
c = YAML.load(IO.read( file )).to_os
|
357
|
+
config[ File.expand_path( file )] = c
|
358
|
+
end
|
359
|
+
|
360
|
+
def settings
|
361
|
+
@settings ||= setup_classes(tiuns.map { | model | [ model.name.underscore.to_sym, model.tiun ]}.to_h)
|
362
|
+
end
|
363
|
+
|
364
|
+
def tiuns
|
365
|
+
::Rails.configuration.paths['app/models'].to_a.each do | path |
|
366
|
+
Dir.glob("#{path}/**/*.rb").each { |file| require(file) }
|
367
|
+
end
|
368
|
+
|
369
|
+
ActiveRecord::Base.tiuns
|
370
|
+
end
|
371
|
+
|
372
|
+
# def model_names
|
373
|
+
# settings.keys.map(&:to_s)
|
374
|
+
# end
|
375
|
+
#
|
376
|
+
def constantize name
|
377
|
+
name.constantize
|
378
|
+
rescue NameError
|
379
|
+
end
|
380
|
+
|
381
|
+
def base_model
|
382
|
+
@base_model ||= ActiveRecord::Base
|
383
|
+
end
|
384
|
+
|
385
|
+
def base_controller
|
386
|
+
@base_controller ||= ActionController::Base
|
387
|
+
end
|
388
|
+
|
389
|
+
def error code, options
|
390
|
+
errors << { code: code, options: options }
|
391
|
+
end
|
392
|
+
|
393
|
+
def valid?
|
394
|
+
errors.blank?
|
395
|
+
end
|
396
|
+
|
397
|
+
#def target_version
|
398
|
+
#
|
399
|
+
#end
|
400
|
+
|
401
|
+
# def type_of kind
|
402
|
+
# case kind
|
403
|
+
# when 'string'
|
404
|
+
# :"ActiveModel::Type::String"
|
405
|
+
# when 'integer', 'index'
|
406
|
+
# :"ActiveRecord::ConnectionAdapters::SQLite3Adapter::SQLite3Integer"
|
407
|
+
# else
|
408
|
+
# error :invalid_attribute_type_for_kind, { kind: kind }
|
409
|
+
# end
|
410
|
+
# end
|
411
|
+
# def plain_parm parm
|
412
|
+
# case parm
|
413
|
+
# when String
|
414
|
+
# array = parm.split( /\s*,\s*/ )
|
415
|
+
#
|
416
|
+
# if array.size > 1
|
417
|
+
# plain_array( array )
|
418
|
+
# else
|
419
|
+
# array.first.to_sym
|
420
|
+
# end
|
421
|
+
# when Hash
|
422
|
+
# plain_hash( parm )
|
423
|
+
# when Array
|
424
|
+
# plain_array( parm )
|
425
|
+
# else
|
426
|
+
# nil
|
427
|
+
# end
|
428
|
+
# end
|
429
|
+
#
|
430
|
+
# def plain_hash hash
|
431
|
+
# hash.map do |( key, parms )|
|
432
|
+
# [ key.to_sym, plain_parm( parms )]
|
433
|
+
# end.to_h
|
434
|
+
# end
|
435
|
+
#
|
436
|
+
# def plain_array array
|
437
|
+
# array.map do | parm |
|
438
|
+
# plain_parm( parm )
|
439
|
+
# end.flatten
|
440
|
+
# end
|
441
|
+
#
|
442
|
+
# def setup_classes settings
|
443
|
+
# settings.each do | (model_name, tiun) |
|
444
|
+
# name = -> { model_name.to_s.camelize }
|
445
|
+
# names = -> { model_name.to_s.pluralize.camelize }
|
446
|
+
# params = -> { tiun[:fields].map(&:first) }
|
447
|
+
#
|
448
|
+
# binding.pry
|
449
|
+
# controller_rb = <<-RB
|
450
|
+
# class #{names[]}Controller < #{base_controller}
|
451
|
+
# include Tiun::Base
|
452
|
+
#
|
453
|
+
# def model
|
454
|
+
# ::#{name[]} ;end
|
455
|
+
#
|
456
|
+
# def object_serializer
|
457
|
+
# #{name[]}Serializer ;end
|
458
|
+
#
|
459
|
+
# def objects_serializer
|
460
|
+
# #{names[]}Serializer
|
461
|
+
# rescue NameError
|
462
|
+
# Tiun::PagedCollectionSerializer ;end
|
463
|
+
#
|
464
|
+
# def permitted_params
|
465
|
+
# params.require( '#{model_name}' ).permit( #{params[]} ) ;end;end
|
466
|
+
# RB
|
467
|
+
#
|
468
|
+
# policy_rb = <<-RB
|
469
|
+
# class #{name[]}Policy
|
470
|
+
# include Tiun::Policy
|
471
|
+
# end
|
472
|
+
# RB
|
473
|
+
#
|
474
|
+
# class_eval(controller_rb)
|
475
|
+
# class_eval(policy_rb)
|
476
|
+
# end
|
477
|
+
# end
|
478
|
+
#
|
479
|
+
def root
|
480
|
+
Gem::Specification.find_by_name( "tiun" ).full_gem_path
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
# included do
|
486
|
+
# end
|
487
|
+
end
|
488
|
+
|
489
|
+
require "tiun/base"
|
490
|
+
require "tiun/policy"
|
491
|
+
require "tiun/engine"
|