habarico 7.2.0.pre.beta.5
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/LICENSE +21 -0
- data/README.md +82 -0
- data/Rakefile +15 -0
- data/VERSION +1 -0
- data/app/controllers/habarico/action_schema_controller.rb +41 -0
- data/app/controllers/habarico/application_controller.rb +15 -0
- data/app/controllers/habarico/contrib/preferences/user_preferences_controller.rb +105 -0
- data/app/controllers/habarico/global_schema_controller.rb +11 -0
- data/app/controllers/habarico/local_schema_controller.rb +35 -0
- data/app/helpers/habarico/application_helper.rb +4 -0
- data/app/models/habarico/application_record.rb +5 -0
- data/app/views/layouts/habarico/application.html.erb +17 -0
- data/config/locales/cs.yml +39 -0
- data/config/locales/de.yml +39 -0
- data/config/locales/en.yml +39 -0
- data/config/locales/es.yml +39 -0
- data/config/locales/fr.yml +39 -0
- data/config/locales/it.yml +39 -0
- data/config/locales/ja.yml +39 -0
- data/config/locales/nl.yml +39 -0
- data/config/locales/pl.yml +39 -0
- data/config/locales/pt.yml +39 -0
- data/config/locales/ro.yml +39 -0
- data/config/locales/sk.yml +39 -0
- data/config/locales/uk.yml +39 -0
- data/config/routes.rb +1 -0
- data/lib/generators/habarico/preferences/install_generator.rb +27 -0
- data/lib/generators/habarico/preferences/templates/create_habarico_user_preferences.rb.tt +15 -0
- data/lib/habarico/active_model/references.rb +68 -0
- data/lib/habarico/authenticatable.rb +31 -0
- data/lib/habarico/config.rb +71 -0
- data/lib/habarico/context.rb +126 -0
- data/lib/habarico/contrib/preferences/base_preferences.rb +40 -0
- data/lib/habarico/contrib/preferences/config.rb +31 -0
- data/lib/habarico/contrib/preferences/errors.rb +79 -0
- data/lib/habarico/contrib/preferences/locales/cs.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/de.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/en.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/es.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/fr.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/it.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/ja.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/nl.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/pl.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/pt.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/ro.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/sk.yml +8 -0
- data/lib/habarico/contrib/preferences/locales/uk.yml +8 -0
- data/lib/habarico/contrib/preferences/registry.rb +293 -0
- data/lib/habarico/contrib/preferences/routes.rb +17 -0
- data/lib/habarico/contrib/preferences/schemas.rb +129 -0
- data/lib/habarico/contrib/preferences/serializer.rb +19 -0
- data/lib/habarico/contrib/preferences/user_preference.rb +16 -0
- data/lib/habarico/contrib/preferences.rb +32 -0
- data/lib/habarico/controller.rb +584 -0
- data/lib/habarico/definition/action_reference.rb +18 -0
- data/lib/habarico/definition/actions/action.rb +14 -0
- data/lib/habarico/definition/actions/create_action.rb +18 -0
- data/lib/habarico/definition/actions/delete_action.rb +20 -0
- data/lib/habarico/definition/actions/edit_action.rb +18 -0
- data/lib/habarico/definition/actions/link_action.rb +11 -0
- data/lib/habarico/definition/actions/resource_action.rb +12 -0
- data/lib/habarico/definition/actions/save_action.rb +14 -0
- data/lib/habarico/definition/actions/show_action.rb +18 -0
- data/lib/habarico/definition/actions/upload_images_action.rb +11 -0
- data/lib/habarico/definition/actions/view_action.rb +11 -0
- data/lib/habarico/definition/boxes/array_box.rb +10 -0
- data/lib/habarico/definition/boxes/box.rb +32 -0
- data/lib/habarico/definition/boxes/gallery_box.rb +10 -0
- data/lib/habarico/definition/boxes/grid_box.rb +10 -0
- data/lib/habarico/definition/boxes/grid_item_box.rb +10 -0
- data/lib/habarico/definition/boxes/list_box.rb +10 -0
- data/lib/habarico/definition/boxes/object_box.rb +10 -0
- data/lib/habarico/definition/boxes/tab_box.rb +10 -0
- data/lib/habarico/definition/boxes/tab_item_box.rb +10 -0
- data/lib/habarico/definition/boxes/wizard_box.rb +10 -0
- data/lib/habarico/definition/concerns/definition_model.rb +38 -0
- data/lib/habarico/definition/definition.rb +206 -0
- data/lib/habarico/definition/field_reference.rb +9 -0
- data/lib/habarico/definition/filter_reference.rb +7 -0
- data/lib/habarico/definition/menu/link_menu_item.rb +12 -0
- data/lib/habarico/definition/menu/menu_item.rb +9 -0
- data/lib/habarico/definition/menu/text_menu_item.rb +12 -0
- data/lib/habarico/definition/menu/view_menu_item.rb +13 -0
- data/lib/habarico/definition/response.rb +13 -0
- data/lib/habarico/definition/views/action_view.rb +11 -0
- data/lib/habarico/definition/views/create_view.rb +15 -0
- data/lib/habarico/definition/views/edit_view.rb +15 -0
- data/lib/habarico/definition/views/list_view.rb +17 -0
- data/lib/habarico/definition/views/show_view.rb +15 -0
- data/lib/habarico/definition/views/view.rb +10 -0
- data/lib/habarico/engine.rb +6 -0
- data/lib/habarico/file_validations.rb +119 -0
- data/lib/habarico/generators/abstract_generator.rb +21 -0
- data/lib/habarico/generators/action/action_schema_generator.rb +111 -0
- data/lib/habarico/generators/action/confirm_dialog_properties_generator.rb +30 -0
- data/lib/habarico/generators/action/global_resource_action_schema_generator.rb +46 -0
- data/lib/habarico/generators/action/link_action_parameters_generator.rb +31 -0
- data/lib/habarico/generators/action/resource_action_endpoint_parameters_generator.rb +70 -0
- data/lib/habarico/generators/action/resource_action_parameters_generator.rb +40 -0
- data/lib/habarico/generators/action/resource_action_schema_generator.rb +51 -0
- data/lib/habarico/generators/action/save_action_parameters_generator.rb +26 -0
- data/lib/habarico/generators/action/upload_images_action_parameters_generator.rb +41 -0
- data/lib/habarico/generators/action/view_action_endpoint_parameters_generator.rb +37 -0
- data/lib/habarico/generators/action/view_action_parameters_generator.rb +56 -0
- data/lib/habarico/generators/endpoint/dynamic_render_options_generator.rb +26 -0
- data/lib/habarico/generators/endpoint/endpoints_schema_generator.rb +61 -0
- data/lib/habarico/generators/endpoint/enum_type_generator.rb +45 -0
- data/lib/habarico/generators/endpoint/field_options_generator.rb +179 -0
- data/lib/habarico/generators/endpoint/field_schema_generator.rb +381 -0
- data/lib/habarico/generators/endpoint/fields_schema_generator.rb +35 -0
- data/lib/habarico/generators/endpoint/filter_schema_generator.rb +201 -0
- data/lib/habarico/generators/endpoint/filters_schema_generator.rb +25 -0
- data/lib/habarico/generators/endpoint/method_schema_generator.rb +34 -0
- data/lib/habarico/generators/endpoint/number_field_options_generator.rb +45 -0
- data/lib/habarico/generators/endpoint/phone_field_options_generator.rb +29 -0
- data/lib/habarico/generators/endpoint/relation_field_options_generator.rb +90 -0
- data/lib/habarico/generators/endpoint/search_filter_schema_generator.rb +44 -0
- data/lib/habarico/generators/menu/menu_group_schema_generator.rb +63 -0
- data/lib/habarico/generators/menu/menu_link_parameters_generator.rb +31 -0
- data/lib/habarico/generators/menu/menu_schema_generator.rb +105 -0
- data/lib/habarico/generators/menu/menu_view_endpoint_parameters_generator.rb +44 -0
- data/lib/habarico/generators/menu/menu_view_parameters_generator.rb +50 -0
- data/lib/habarico/generators/resource/action_resource_schema_generator.rb +84 -0
- data/lib/habarico/generators/resource/global_resource_schema_generator.rb +70 -0
- data/lib/habarico/generators/resource/local_resource_schema_generator.rb +111 -0
- data/lib/habarico/generators/resource/object_resource_schema_generator.rb +49 -0
- data/lib/habarico/generators/resource/resource_schema_generator.rb +31 -0
- data/lib/habarico/generators/view/action_descriptor_generator.rb +88 -0
- data/lib/habarico/generators/view/array_box_parameters_generator.rb +34 -0
- data/lib/habarico/generators/view/box_options_generator.rb +23 -0
- data/lib/habarico/generators/view/box_schema_generator.rb +194 -0
- data/lib/habarico/generators/view/detail_view_parameters_generator.rb +57 -0
- data/lib/habarico/generators/view/field_descriptor_generator.rb +107 -0
- data/lib/habarico/generators/view/filter_descriptor_generator.rb +75 -0
- data/lib/habarico/generators/view/gallery_box_parameters_generator.rb +71 -0
- data/lib/habarico/generators/view/global_view_schema_generator.rb +59 -0
- data/lib/habarico/generators/view/grid_item_box_parameters_generator.rb +44 -0
- data/lib/habarico/generators/view/list_box_parameters_generator.rb +124 -0
- data/lib/habarico/generators/view/list_view_parameters_generator.rb +120 -0
- data/lib/habarico/generators/view/object_box_parameters_generator.rb +26 -0
- data/lib/habarico/generators/view/sort_descriptor_generator.rb +30 -0
- data/lib/habarico/generators/view/tab_box_parameters_generator.rb +26 -0
- data/lib/habarico/generators/view/view_endpoint_parameters_generator.rb +71 -0
- data/lib/habarico/generators/view/view_schema_generator.rb +87 -0
- data/lib/habarico/generators/view/wizard_box_parameters_generator.rb +32 -0
- data/lib/habarico/helpers/action_helper.rb +9 -0
- data/lib/habarico/helpers/attributes_helper.rb +67 -0
- data/lib/habarico/helpers/box_helper.rb +19 -0
- data/lib/habarico/helpers/callable_helper.rb +15 -0
- data/lib/habarico/helpers/filter_params_helper.rb +49 -0
- data/lib/habarico/helpers/order_by_helper.rb +56 -0
- data/lib/habarico/helpers/reflection_helper.rb +61 -0
- data/lib/habarico/helpers/sorting_helper.rb +136 -0
- data/lib/habarico/schema/action/action_schema.rb +46 -0
- data/lib/habarico/schema/action/confirm_dialog_properties.rb +13 -0
- data/lib/habarico/schema/action/global_resource_action_schema.rb +29 -0
- data/lib/habarico/schema/action/link_action_parameters.rb +15 -0
- data/lib/habarico/schema/action/resource_action_endpoint_parameters.rb +24 -0
- data/lib/habarico/schema/action/resource_action_parameters.rb +17 -0
- data/lib/habarico/schema/action/resource_action_schema.rb +14 -0
- data/lib/habarico/schema/action/save_action_parameters.rb +10 -0
- data/lib/habarico/schema/action/upload_images_action_parameters.rb +23 -0
- data/lib/habarico/schema/action/view_action_endpoint_parameters.rb +16 -0
- data/lib/habarico/schema/action/view_action_parameters.rb +27 -0
- data/lib/habarico/schema/endpoint/ai_field_options.rb +10 -0
- data/lib/habarico/schema/endpoint/box_options.rb +10 -0
- data/lib/habarico/schema/endpoint/choices_field_options.rb +10 -0
- data/lib/habarico/schema/endpoint/dynamic_render_options.rb +14 -0
- data/lib/habarico/schema/endpoint/endpoints_schema.rb +22 -0
- data/lib/habarico/schema/endpoint/enum_type.rb +21 -0
- data/lib/habarico/schema/endpoint/field_options.rb +56 -0
- data/lib/habarico/schema/endpoint/field_schema.rb +65 -0
- data/lib/habarico/schema/endpoint/filter_schema.rb +44 -0
- data/lib/habarico/schema/endpoint/image_field_options.rb +13 -0
- data/lib/habarico/schema/endpoint/key_value.rb +13 -0
- data/lib/habarico/schema/endpoint/method_schema.rb +13 -0
- data/lib/habarico/schema/endpoint/number_field_options.rb +24 -0
- data/lib/habarico/schema/endpoint/phone_field_options.rb +13 -0
- data/lib/habarico/schema/endpoint/relation_field_options.rb +39 -0
- data/lib/habarico/schema/extensible_enum.rb +20 -0
- data/lib/habarico/schema/menu/action_view_choice.rb +13 -0
- data/lib/habarico/schema/menu/menu_group_schema.rb +26 -0
- data/lib/habarico/schema/menu/menu_schema.rb +36 -0
- data/lib/habarico/schema/resource/global_resource_schema.rb +14 -0
- data/lib/habarico/schema/resource/local_resource_schema.rb +14 -0
- data/lib/habarico/schema/resource/object_resource_schema.rb +8 -0
- data/lib/habarico/schema/resource/resource_schema.rb +16 -0
- data/lib/habarico/schema/types.rb +102 -0
- data/lib/habarico/schema/view/action_descriptor.rb +30 -0
- data/lib/habarico/schema/view/array_box_parameters.rb +13 -0
- data/lib/habarico/schema/view/box_schema.rb +67 -0
- data/lib/habarico/schema/view/detail_view_parameters.rb +16 -0
- data/lib/habarico/schema/view/field_descriptor.rb +50 -0
- data/lib/habarico/schema/view/field_wrapper_properties.rb +13 -0
- data/lib/habarico/schema/view/filter_descriptor.rb +24 -0
- data/lib/habarico/schema/view/gallery_box_parameters.rb +31 -0
- data/lib/habarico/schema/view/global_view_schema.rb +25 -0
- data/lib/habarico/schema/view/grid_item_box_parameters.rb +13 -0
- data/lib/habarico/schema/view/list_box_parameters.rb +44 -0
- data/lib/habarico/schema/view/list_view_parameters.rb +31 -0
- data/lib/habarico/schema/view/object_box_parameters.rb +10 -0
- data/lib/habarico/schema/view/sort_descriptor.rb +15 -0
- data/lib/habarico/schema/view/sortable_parameters.rb +13 -0
- data/lib/habarico/schema/view/tab_box_parameters.rb +10 -0
- data/lib/habarico/schema/view/view_action_descriptor_parameters.rb +21 -0
- data/lib/habarico/schema/view/view_endpoint_parameters.rb +22 -0
- data/lib/habarico/schema/view/view_schema.rb +33 -0
- data/lib/habarico/schema/view/wizard_box_parameters.rb +13 -0
- data/lib/habarico/search/field_resolver.rb +138 -0
- data/lib/habarico/search/search_matcher.rb +152 -0
- data/lib/habarico/serializers/meta_serializer.rb +42 -0
- data/lib/habarico/serializers/record_serializer.rb +33 -0
- data/lib/habarico/serializers/serializer.rb +61 -0
- data/lib/habarico/services/resource_service.rb +69 -0
- data/lib/habarico/services/routing_service.rb +160 -0
- data/lib/habarico/services/schema_service.rb +72 -0
- data/lib/habarico/version.rb +5 -0
- data/lib/habarico.rb +262 -0
- metadata +324 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
module Habarico
|
|
2
|
+
class FieldSchemaGenerator < AbstractGenerator
|
|
3
|
+
|
|
4
|
+
def generate(model, field_name, subfields: [], force_name: nil, field_reference: nil)
|
|
5
|
+
# Recognise field variant (active model or active record) and validate arguments
|
|
6
|
+
if Habarico::ReflectionHelper.is_attributes_model_class?(model) && model.has_simple_attr?(field_name) # simple attribute on attributes model
|
|
7
|
+
variant = :attributes_model
|
|
8
|
+
attr_name = field_name
|
|
9
|
+
elsif Habarico::ReflectionHelper.is_attributes_model_class?(model) && model.has_complex_attr?(field_name) # complex attribute on attributes model
|
|
10
|
+
variant = :attributes_model
|
|
11
|
+
attr_name = field_name
|
|
12
|
+
elsif Habarico::ReflectionHelper.is_active_record_class?(model) && model.columns_hash[field_name.to_s] # standard DB column on active record
|
|
13
|
+
variant = :active_record
|
|
14
|
+
attr_name = field_name
|
|
15
|
+
elsif Habarico::ReflectionHelper.is_active_record_class?(model) && model.attribute_names.include?(field_name.to_s) # virtual attribute (attribute :x) - not a DB column
|
|
16
|
+
variant = :active_model
|
|
17
|
+
attr_name = field_name
|
|
18
|
+
elsif Habarico::ReflectionHelper.is_active_model_class?(model) && model.attribute_names.include?(field_name.to_s) # standard attribute accessor on active model
|
|
19
|
+
variant = :active_model
|
|
20
|
+
attr_name = field_name
|
|
21
|
+
elsif Habarico::ReflectionHelper.is_belongs_to_association?(model, field_name) # belongs to association on active record
|
|
22
|
+
variant = :active_record
|
|
23
|
+
attr_name = model.reflect_on_association(field_name.to_sym).foreign_key
|
|
24
|
+
elsif Habarico::ReflectionHelper.is_has_one_association?(model, field_name) # has one association on active record
|
|
25
|
+
variant = :attributes_model # foreign key is on the other model and must be delegated to this model via a simple attribute, so we treat it as active model attribute
|
|
26
|
+
attr_name = model.reflect_on_association(field_name.to_sym).foreign_key
|
|
27
|
+
unless Habarico::ReflectionHelper.is_attributes_model_class?(model) && model.has_simple_attr?(attr_name)
|
|
28
|
+
raise Eluvia::Errors::StandardError.new("Argument `model` must be an ActiveRecord::Base and Eluvia::ActiveModel::Attributes subclass and attribute `#{attr_name}` must exist on the model")
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
raise Eluvia::Errors::StandardError.new("Argument `model` must be an ActiveRecord::Base or Eluvia::ActiveModel::Attributes subclass and field or attribute `#{field_name}` must exist on the model")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Create model
|
|
35
|
+
schema = Habarico::FieldSchema.new(
|
|
36
|
+
name: generate_name(model, field_name, attr_name, variant, force_name),
|
|
37
|
+
type: generate_type(model, field_name, attr_name, variant),
|
|
38
|
+
format: generate_format(model, field_name, attr_name, variant),
|
|
39
|
+
label: generate_label(model, field_name, attr_name, variant),
|
|
40
|
+
help_text: generate_help_text(model, field_name, attr_name, variant),
|
|
41
|
+
read_only: generate_read_only(model, field_name, attr_name, variant),
|
|
42
|
+
write_only: generate_write_only(model, field_name, attr_name, variant),
|
|
43
|
+
nullable: generate_nullable(model, field_name, attr_name, variant),
|
|
44
|
+
required: generate_required(model, field_name, attr_name, variant),
|
|
45
|
+
sortable: generate_sortable(model, field_name, attr_name, variant),
|
|
46
|
+
sort_by: generate_sort_by(model, field_name, attr_name, variant),
|
|
47
|
+
reference: generate_reference(model, field_name, attr_name, variant),
|
|
48
|
+
enum: generate_enum(model, field_name, attr_name, variant),
|
|
49
|
+
items: generate_items(model, field_name, attr_name, variant, subfields),
|
|
50
|
+
properties: generate_properties(model, field_name, attr_name, variant, subfields),
|
|
51
|
+
options: generate_options(model, field_name, attr_name, variant),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
Habarico::AttributesHelper.apply_field_reference_overrides(schema, field_reference)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
# ***********************************************************************
|
|
60
|
+
# Schema generators
|
|
61
|
+
# ***********************************************************************
|
|
62
|
+
|
|
63
|
+
def enum_type_generator
|
|
64
|
+
@enum_type_generator ||= definition.enum_type_generator.new(definition, resource_path)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def field_schema_generator
|
|
68
|
+
@field_schema_generator ||= definition.field_schema_generator.new(definition, resource_path)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def fields_schema_generator
|
|
72
|
+
@fields_schema_generator ||= definition.fields_schema_generator.new(definition, resource_path)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def field_options_generator
|
|
76
|
+
@field_options_generator ||= definition.field_options_generator.new(definition, resource_path)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# ***********************************************************************
|
|
80
|
+
# Attribute generators
|
|
81
|
+
# ***********************************************************************
|
|
82
|
+
|
|
83
|
+
def generate_name(_model, field_name, _attr_name, _variant, force_name)
|
|
84
|
+
force_name || field_name
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def map_active_record_type(type)
|
|
88
|
+
case type
|
|
89
|
+
when :integer then 'integer'
|
|
90
|
+
when :boolean then 'boolean'
|
|
91
|
+
when :float, :decimal then 'number'
|
|
92
|
+
when :datetime then 'string'
|
|
93
|
+
when :date then 'string'
|
|
94
|
+
when :text then 'string'
|
|
95
|
+
when :uuid then 'string'
|
|
96
|
+
else 'string'
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def map_attributes_model_type(type)
|
|
101
|
+
case type
|
|
102
|
+
when :integer then 'integer'
|
|
103
|
+
when :boolean then 'boolean'
|
|
104
|
+
when :float then 'number'
|
|
105
|
+
when :datetime then 'string'
|
|
106
|
+
when :date then 'string'
|
|
107
|
+
when :string then 'string'
|
|
108
|
+
when :uuid then 'string'
|
|
109
|
+
else 'string'
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def map_active_model_type(type)
|
|
114
|
+
case type
|
|
115
|
+
when 'ActiveModel::Type::Integer' then 'integer'
|
|
116
|
+
when 'ActiveModel::Type::String' then 'string'
|
|
117
|
+
else 'string'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def generate_type(model, _field_name, attr_name, variant)
|
|
122
|
+
# Special types and annotations
|
|
123
|
+
return 'object' if model.respond_to?(:has_attr?) && model.has_attr?(attr_name, type: :has_one)
|
|
124
|
+
return 'object' if model.respond_to?(:has_object_attr?) && model.has_object_attr?(attr_name)
|
|
125
|
+
return 'array' if model.respond_to?(:has_attr?) && model.has_attr?(attr_name, type: :has_many)
|
|
126
|
+
return 'array' if model.respond_to?(:has_array_attr?) && model.has_array_attr?(attr_name)
|
|
127
|
+
return 'string' if model.respond_to?(:has_enum_attr?) && model.has_enum_attr?(attr_name)
|
|
128
|
+
|
|
129
|
+
# Basic types are computed specific for active model and active record variants
|
|
130
|
+
if variant == :attributes_model
|
|
131
|
+
attr = model.find_simple_attr(attr_name)
|
|
132
|
+
return map_attributes_model_type(attr[:type]) if attr
|
|
133
|
+
end
|
|
134
|
+
if variant == :active_record
|
|
135
|
+
type = model.columns_hash[attr_name.to_s].type
|
|
136
|
+
return map_active_record_type(type)
|
|
137
|
+
end
|
|
138
|
+
if variant == :active_model
|
|
139
|
+
type = model.attribute_types[attr_name.to_s].class.to_s
|
|
140
|
+
return map_active_model_type(type)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
'string'
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def map_active_record_format(type)
|
|
147
|
+
case type
|
|
148
|
+
when :datetime then 'date-time'
|
|
149
|
+
when :date then 'date'
|
|
150
|
+
when :time then 'time'
|
|
151
|
+
when :text then 'text'
|
|
152
|
+
when :uuid then 'uuid'
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def map_attributes_model_format(type)
|
|
157
|
+
case type
|
|
158
|
+
when :datetime then 'date-time'
|
|
159
|
+
when :date then 'date'
|
|
160
|
+
when :uuid then 'uuid'
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def generate_format(model, field_name, attr_name, variant)
|
|
165
|
+
# Special types and annotations
|
|
166
|
+
if model.respond_to?(:has_file_attr?) && model.has_file_attr?(attr_name)
|
|
167
|
+
if model.find_file_attr(attr_name).fetch(:nature) == :image
|
|
168
|
+
return 'base64-image'
|
|
169
|
+
else
|
|
170
|
+
return 'base64-file'
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
return 'range' if model.respond_to?(:has_range_attr?) && model.has_range_attr?(attr_name)
|
|
174
|
+
return nil if model.respond_to?(:has_array_attr?) && model.has_array_attr?(attr_name)
|
|
175
|
+
return nil if model.respond_to?(:has_object_attr?) && model.has_object_attr?(attr_name)
|
|
176
|
+
return 'relation' if Habarico::ReflectionHelper.is_has_one_reference?(model, field_name)
|
|
177
|
+
return 'relation' if Habarico::ReflectionHelper.is_belongs_to_association?(model, field_name)
|
|
178
|
+
return 'relation' if Habarico::ReflectionHelper.is_has_one_association?(model, field_name)
|
|
179
|
+
return 'choices' if model.respond_to?(:has_enum_attr?) && model.has_enum_attr?(attr_name)
|
|
180
|
+
|
|
181
|
+
# Basic types are computed specific for active model and active record variants
|
|
182
|
+
if variant == :attributes_model
|
|
183
|
+
attr = model.find_simple_attr(attr_name)
|
|
184
|
+
return map_attributes_model_format(attr[:type]) if attr
|
|
185
|
+
end
|
|
186
|
+
if variant == :active_record
|
|
187
|
+
type = model.columns_hash[attr_name.to_s].type
|
|
188
|
+
return map_active_record_format(type)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
nil
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def generate_label(model, field_name, _attr_name, _variant)
|
|
195
|
+
Habarico::AttributesHelper.generate_attr_variants(model, field_name).each do |field_name_variant|
|
|
196
|
+
label = I18n.t("#{model.i18n_scope}.attributes.#{model.model_name.i18n_key}.#{field_name_variant}", default: nil)
|
|
197
|
+
return label if label.present?
|
|
198
|
+
end
|
|
199
|
+
field_name.to_s.humanize
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def generate_help_text(model, field_name, _attr_name, _variant)
|
|
203
|
+
Habarico::AttributesHelper.generate_attr_variants(model, field_name).each do |field_name_variant|
|
|
204
|
+
help_text = I18n.t("#{model.i18n_scope}.attributes.#{model.model_name.i18n_key}.#{field_name_variant}_help_text", default: nil)
|
|
205
|
+
return help_text if help_text.present?
|
|
206
|
+
end
|
|
207
|
+
nil
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def generate_read_only(_model, _field_name, _attr_name, _variant)
|
|
211
|
+
# not implemented yet
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def generate_write_only(_model, _field_name, _attr_name, _variant)
|
|
215
|
+
# not implemented yet
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def generate_nullable(model, _field_name, attr_name, variant)
|
|
219
|
+
# For an attributes model, this is always true as there are no built-in validators
|
|
220
|
+
if variant == :attributes_model
|
|
221
|
+
return true
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# For active record, this is derived from database column nullability
|
|
225
|
+
if variant == :active_record
|
|
226
|
+
return model.columns_hash[attr_name.to_s].null
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# For active model, this is always true as there are no built-in validators
|
|
230
|
+
if variant == :active_model
|
|
231
|
+
return true
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
nil
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def generate_required(model, field_name, _attr_name, variant)
|
|
238
|
+
# For an attributes model, this is always false as there are no built-in validators
|
|
239
|
+
if variant == :attributes_model
|
|
240
|
+
return false
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# For active record, this is derived from presence validators
|
|
244
|
+
if variant == :active_record
|
|
245
|
+
model.validators_on(field_name).any? do |v|
|
|
246
|
+
v.is_a?(::ActiveModel::Validations::PresenceValidator)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# For active model, this is always false as there are no built-in validators
|
|
251
|
+
if variant == :active_model
|
|
252
|
+
return false
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
nil
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def generate_sortable(model, field_name, attr_name, variant)
|
|
259
|
+
generate_sort_by(model, field_name, attr_name, variant).present?
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def generate_sort_by(model, field_name, attr_name, _variant)
|
|
263
|
+
Habarico::SortingHelper.schema_sort_by(definition, model, field_name, attr_name: attr_name)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def generate_reference(model, field_name, _attr_name, _variant)
|
|
267
|
+
# Manually declared "has one" reference
|
|
268
|
+
if Habarico::ReflectionHelper.is_has_one_reference?(model, field_name)
|
|
269
|
+
reference = model.find_reference(field_name)
|
|
270
|
+
reference_class = reference[:class_name].constantize
|
|
271
|
+
if reference_class.const_defined?(:REFERENCE)
|
|
272
|
+
return reference_class.const_get(:REFERENCE)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# Reference derived from "belongs to" association
|
|
277
|
+
if Habarico::ReflectionHelper.is_belongs_to_association?(model, field_name)
|
|
278
|
+
reflection = model.reflect_on_association(field_name.to_sym)
|
|
279
|
+
if reflection
|
|
280
|
+
return Habarico::ResourceService.instance.find_resource_name_by_model_class(reflection.klass)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Reference derived from "has one" association
|
|
285
|
+
if Habarico::ReflectionHelper.is_has_one_association?(model, field_name)
|
|
286
|
+
reflection = model.reflect_on_association(field_name.to_sym)
|
|
287
|
+
if reflection
|
|
288
|
+
return Habarico::ResourceService.instance.find_resource_name_by_model_class(reflection.klass)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
nil
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def generate_enum(model, _field_name, attr_name, _variant)
|
|
296
|
+
if model.respond_to?(:has_enum_attr?) && model.has_enum_attr?(attr_name)
|
|
297
|
+
return model.find_enum_attr(attr_name).keys.map do |choice|
|
|
298
|
+
enum_type_generator.generate(model, attr_name, choice)
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
nil
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def generate_items(model, field_name, attr_name, _variant, subfields)
|
|
305
|
+
name = ''
|
|
306
|
+
label = generate_label(model, field_name, attr_name, nil)
|
|
307
|
+
|
|
308
|
+
# Manually declared "has many" reference is interpreted as array of relations, so we need to define items schema
|
|
309
|
+
if Habarico::ReflectionHelper.is_has_many_reference?(model, field_name)
|
|
310
|
+
reference = model.find_reference(field_name)
|
|
311
|
+
reference_class = reference[:class_name].constantize
|
|
312
|
+
if reference_class.const_defined?(:REFERENCE)
|
|
313
|
+
return Habarico::FieldSchema.new(
|
|
314
|
+
name: name,
|
|
315
|
+
label: label,
|
|
316
|
+
type: 'string',
|
|
317
|
+
format: 'relation',
|
|
318
|
+
reference: reference_class.const_get(:REFERENCE),
|
|
319
|
+
)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# "Array" attribute is interpreted as array of simple types, like string, integer, etc.
|
|
324
|
+
if model.respond_to?(:has_array_attr?) && model.has_array_attr?(attr_name)
|
|
325
|
+
array_attr = model.find_array_attr(attr_name)
|
|
326
|
+
return Habarico::FieldSchema.new(
|
|
327
|
+
name: name,
|
|
328
|
+
label: label,
|
|
329
|
+
type: map_attributes_model_type(array_attr[:type]),
|
|
330
|
+
format: map_attributes_model_format(array_attr[:type]),
|
|
331
|
+
)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# "Has many" attribute is interpreted as array of objects
|
|
335
|
+
if model.respond_to?(:has_attr?) && model.has_attr?(attr_name, type: :has_many)
|
|
336
|
+
array_attr = model.find_attr(attr_name, type: :has_many)
|
|
337
|
+
if array_attr[:class_name]
|
|
338
|
+
return Habarico::FieldSchema.new(
|
|
339
|
+
name: name,
|
|
340
|
+
label: label,
|
|
341
|
+
type: 'object',
|
|
342
|
+
properties: fields_schema_generator.generate(array_attr[:class_name].constantize, subfields)
|
|
343
|
+
)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
nil
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def generate_properties(model, _field_name, attr_name, _variant, subfields)
|
|
351
|
+
# "Object" attribute is just a collection of attributes existing on the same model
|
|
352
|
+
if model.respond_to?(:has_object_attr?) && model.has_object_attr?(attr_name)
|
|
353
|
+
result = []
|
|
354
|
+
object_attr = model.find_object_attr(attr_name)
|
|
355
|
+
object_attr[:fields].each do |field|
|
|
356
|
+
key = field.keys.first
|
|
357
|
+
underlying_attr_name = field.values.first
|
|
358
|
+
result << field_schema_generator.generate(model, underlying_attr_name, force_name: key)
|
|
359
|
+
end
|
|
360
|
+
return result
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# "Has one" attribute is a collection of attributes existing on a different class
|
|
364
|
+
if model.respond_to?(:has_attr?) && model.has_attr?(attr_name, type: :has_one)
|
|
365
|
+
object_attr = model.find_attr(attr_name, type: :has_one)
|
|
366
|
+
if object_attr[:class_name] == 'Eluvia::File'
|
|
367
|
+
return fields_schema_generator.generate(object_attr[:class_name].constantize, %i[type url filename size content])
|
|
368
|
+
else
|
|
369
|
+
return fields_schema_generator.generate(object_attr[:class_name].constantize, subfields)
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
nil
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def generate_options(model, _field_name, attr_name, _variant)
|
|
377
|
+
field_options_generator.generate(model, attr_name, nil)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
end
|
|
381
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Habarico
|
|
2
|
+
class FieldsSchemaGenerator < AbstractGenerator
|
|
3
|
+
|
|
4
|
+
def generate(model, fields)
|
|
5
|
+
# Validate arguments
|
|
6
|
+
raise Eluvia::Errors::StandardError.new('Argument `fields` must be an Array of String, Symbol, Hash or Habarico::FieldReference instances') unless fields.is_a?(::Array) && fields.all? { |f| f.is_a?(::String) || f.is_a?(::Symbol) || f.is_a?(::Hash) || f.is_a?(Habarico::FieldReference) }
|
|
7
|
+
|
|
8
|
+
# Generate result
|
|
9
|
+
fields.map do |field|
|
|
10
|
+
field_reference = nil
|
|
11
|
+
if field.is_a?(::Symbol) || field.is_a?(::String)
|
|
12
|
+
field_name = field.to_s
|
|
13
|
+
subfields = []
|
|
14
|
+
elsif field.is_a?(Habarico::FieldReference)
|
|
15
|
+
field_name = field.name.to_s
|
|
16
|
+
subfields = []
|
|
17
|
+
field_reference = field # its set attributes (format, label, sortable, ...) override the model-derived ones
|
|
18
|
+
elsif field.is_a?(::Hash)
|
|
19
|
+
field_name = field.keys.first.to_s
|
|
20
|
+
subfields = field.values.first # We assume that this is also an array of strings / symbols / hashes, if not, the recursive call will catch it
|
|
21
|
+
else
|
|
22
|
+
next nil
|
|
23
|
+
end
|
|
24
|
+
field_schema_generator.generate(model, field_name, subfields: subfields, field_reference: field_reference)
|
|
25
|
+
end.compact
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
protected
|
|
29
|
+
|
|
30
|
+
def field_schema_generator
|
|
31
|
+
@field_schema_generator ||= definition.field_schema_generator.new(definition, resource_path)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
module Habarico
|
|
2
|
+
class FilterSchemaGenerator < AbstractGenerator
|
|
3
|
+
|
|
4
|
+
def generate(model, filter_name)
|
|
5
|
+
# Validate arguments
|
|
6
|
+
raise Eluvia::Errors::StandardError.new('Argument `model` must be an Eluvia::ActiveRecord::Filtering subclass') unless model.ancestors.include?(Eluvia::ActiveRecord::Filtering)
|
|
7
|
+
raise Eluvia::Errors::StandardError.new("Filter `#{filter_name}` not found on model `#{model}`") unless model.filter_params[filter_name.to_sym]
|
|
8
|
+
filter_param = model.filter_params[filter_name.to_sym]
|
|
9
|
+
|
|
10
|
+
# Create model
|
|
11
|
+
Habarico::FilterSchema.new(
|
|
12
|
+
name: generate_name(model, filter_name, filter_param),
|
|
13
|
+
type: generate_type(model, filter_name, filter_param),
|
|
14
|
+
format: generate_format(model, filter_name, filter_param),
|
|
15
|
+
label: generate_label(model, filter_name, filter_param),
|
|
16
|
+
help_text: generate_help_text(model, filter_name, filter_param),
|
|
17
|
+
reference: generate_reference(model, filter_name, filter_param),
|
|
18
|
+
enum: generate_enum(model, filter_name, filter_param),
|
|
19
|
+
items: generate_items(model, filter_name, filter_param),
|
|
20
|
+
properties: generate_properties(model, filter_name, filter_param),
|
|
21
|
+
options: generate_options(model, filter_name, filter_param)
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
protected
|
|
26
|
+
|
|
27
|
+
# ***********************************************************************
|
|
28
|
+
# Schema generators
|
|
29
|
+
# ***********************************************************************
|
|
30
|
+
|
|
31
|
+
def enum_type_generator
|
|
32
|
+
@enum_type_generator ||= definition.enum_type_generator.new(definition, resource_path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def field_schema_generator
|
|
36
|
+
@field_schema_generator ||= definition.field_schema_generator.new(definition, resource_path)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def field_options_generator
|
|
40
|
+
@field_options_generator ||= definition.field_options_generator.new(definition, resource_path)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# ***********************************************************************
|
|
44
|
+
# Attribute generators
|
|
45
|
+
# ***********************************************************************
|
|
46
|
+
|
|
47
|
+
def generate_name(_model, filter_name, _filter_param)
|
|
48
|
+
filter_name
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def map_type(type)
|
|
52
|
+
case type
|
|
53
|
+
when :integer then 'integer'
|
|
54
|
+
when :boolean then 'boolean'
|
|
55
|
+
when :float, :decimal then 'number'
|
|
56
|
+
when :datetime then 'string'
|
|
57
|
+
when :date then 'string'
|
|
58
|
+
when :text then 'string'
|
|
59
|
+
when :uuid then 'string'
|
|
60
|
+
else 'string'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def generate_type(_model, _filter_name, filter_param)
|
|
65
|
+
type = filter_param[:type]
|
|
66
|
+
|
|
67
|
+
# Special types and annotations
|
|
68
|
+
return 'object' if type == :range
|
|
69
|
+
|
|
70
|
+
# Basic types
|
|
71
|
+
map_type(type)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def map_format(type)
|
|
75
|
+
case type
|
|
76
|
+
when :integer then nil
|
|
77
|
+
when :boolean then nil
|
|
78
|
+
when :float, :decimal then nil
|
|
79
|
+
when :datetime then 'date-time'
|
|
80
|
+
when :date then 'date'
|
|
81
|
+
when :time then 'time'
|
|
82
|
+
when :text then 'text'
|
|
83
|
+
when :uuid then 'uuid'
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def generate_format(_model, _filter_name, filter_param)
|
|
88
|
+
type = filter_param[:type]
|
|
89
|
+
attr_name = filter_param[:attr_name]
|
|
90
|
+
filters_model_class = filter_param[:model] # this is not the same as `_model` argument!
|
|
91
|
+
|
|
92
|
+
# Special types and annotations
|
|
93
|
+
return 'range' if type == :range
|
|
94
|
+
return 'relation' if type == :has_one
|
|
95
|
+
return 'relation' if filters_model_class.respond_to?(:has_attr?) && filters_model_class.has_attr?(attr_name, type: :has_one)
|
|
96
|
+
return 'choices' if filters_model_class.respond_to?(:has_enum_attr?) && filters_model_class.has_enum_attr?(attr_name)
|
|
97
|
+
|
|
98
|
+
# Basic types
|
|
99
|
+
map_format(type)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def generate_label(_model, _filter_name, filter_param)
|
|
103
|
+
return filter_param[:label] if filter_param.fetch(:label, nil).present?
|
|
104
|
+
|
|
105
|
+
attr_name = filter_param[:attr_name]
|
|
106
|
+
filters_model_class = filter_param[:model] # this is not the same as `_model` argument!
|
|
107
|
+
i18n_model_class = resolve_i18n_model_class(filters_model_class)
|
|
108
|
+
|
|
109
|
+
Habarico::AttributesHelper.generate_attr_variants(filters_model_class, attr_name).each do |attr_name_variant|
|
|
110
|
+
label = I18n.t("#{i18n_model_class.i18n_scope}.attributes.#{i18n_model_class.model_name.i18n_key}.#{attr_name_variant}", default: nil)
|
|
111
|
+
return label if label.present?
|
|
112
|
+
end
|
|
113
|
+
attr_name.to_s.humanize
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# `filters_model_class` (`filter_param[:model]`) is usually a nested `Eluvia::ActiveRecord::FiltersModel`
|
|
117
|
+
# proxy class (e.g. `Employee::Filters`), not the real AR model — its own i18n_scope/model_name don't match
|
|
118
|
+
# where attribute translations actually live. Resolve back to the real model the same way generate_reference
|
|
119
|
+
# does for class names (strip the `::Filters` suffix), falling back to the proxy class itself if that fails.
|
|
120
|
+
def resolve_i18n_model_class(filters_model_class)
|
|
121
|
+
filters_model_class.name.to_s.delete_suffix('::Filters').constantize
|
|
122
|
+
rescue StandardError
|
|
123
|
+
filters_model_class
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def generate_help_text(_model, _filter_name, _filter_param)
|
|
127
|
+
# not implemented yet
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def generate_reference(_model, _filter_name, filter_param)
|
|
131
|
+
type = filter_param[:type]
|
|
132
|
+
attr_name = filter_param[:attr_name]
|
|
133
|
+
filters_model_class = filter_param[:model] # this is not the same as `_model` argument!
|
|
134
|
+
|
|
135
|
+
# Reference derived from filter attribute with type "has_one" on the filters model
|
|
136
|
+
if type == :has_one
|
|
137
|
+
attr = filters_model_class.find_filter_attr(attr_name)
|
|
138
|
+
class_name = attr.fetch(:options, nil)&.fetch(:class_name, nil)
|
|
139
|
+
if class_name
|
|
140
|
+
return Habarico::ResourceService.instance.find_resource_name_by_model_class(class_name.delete_suffix("::Filters").constantize)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Reference derived from "has one" attribute on the filters model
|
|
145
|
+
if filters_model_class.respond_to?(:has_attr?) && filters_model_class.has_attr?(attr_name, type: :has_one)
|
|
146
|
+
attr = filters_model_class.find_attr(attr_name, type: :has_one)
|
|
147
|
+
class_name = attr.fetch(:class_name, nil)
|
|
148
|
+
if class_name
|
|
149
|
+
return Habarico::ResourceService.instance.find_resource_name_by_model_class(class_name.delete_suffix("::Filters").constantize)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
nil
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def generate_enum(_model, _filter_name, filter_param)
|
|
157
|
+
attr_name = filter_param[:attr_name]
|
|
158
|
+
filters_model_class = filter_param[:model] # this is not the same as `_model` argument!
|
|
159
|
+
|
|
160
|
+
# Generate enum item schema for each choice in enum attribute
|
|
161
|
+
if filters_model_class.respond_to?(:has_enum_attr?) && filters_model_class.has_enum_attr?(attr_name)
|
|
162
|
+
return filters_model_class.find_enum_attr(attr_name).keys.map do |choice|
|
|
163
|
+
enum_type_generator.generate(filters_model_class, attr_name, choice)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
nil
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def generate_items(_model, _filter_name, _filter_param)
|
|
171
|
+
# not implemented yet
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def generate_properties(_model, _filter_name, filter_param)
|
|
175
|
+
attr_name = filter_param[:attr_name]
|
|
176
|
+
filters_model_class = filter_param[:model] # this is not the same as `_model` argument!
|
|
177
|
+
|
|
178
|
+
# Object attribute is just a collection of attributes existing on the same model. In this case it's
|
|
179
|
+
# usually a range attribute which is defined as a special case of object.
|
|
180
|
+
if filters_model_class.respond_to?(:has_object_attr?) && filters_model_class.has_object_attr?(attr_name)
|
|
181
|
+
result = []
|
|
182
|
+
object_attr = filters_model_class.find_object_attr(attr_name)
|
|
183
|
+
object_attr[:fields].each do |field|
|
|
184
|
+
key = field.keys.first
|
|
185
|
+
underlying_attr_name = field.values.first
|
|
186
|
+
result << field_schema_generator.generate(filters_model_class, underlying_attr_name, force_name: key)
|
|
187
|
+
end
|
|
188
|
+
return result
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
nil
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def generate_options(_model, _filter_name, filter_param)
|
|
195
|
+
attr_name = filter_param[:attr_name]
|
|
196
|
+
filters_model_class = filter_param[:model] # this is not the same as `_model` argument!
|
|
197
|
+
field_options_generator.generate(filters_model_class, attr_name, nil)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Habarico
|
|
2
|
+
class FiltersSchemaGenerator < AbstractGenerator
|
|
3
|
+
|
|
4
|
+
def generate(model, filters)
|
|
5
|
+
# Validate arguments
|
|
6
|
+
raise Eluvia::Errors::StandardError.new('Argument `filters` must be an Array of String or Symbol instances') unless filters.is_a?(::Array) && filters.all? { |f| f.is_a?(::String) || f.is_a?(::Symbol) }
|
|
7
|
+
|
|
8
|
+
# Generate result
|
|
9
|
+
result = filters.map { |filter_name| filter_schema_generator.generate(model, filter_name) }.compact
|
|
10
|
+
result << search_filter_schema_generator.generate(model)
|
|
11
|
+
result
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
def filter_schema_generator
|
|
17
|
+
@filter_schema_generator ||= definition.filter_schema_generator.new(definition, resource_path)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def search_filter_schema_generator
|
|
21
|
+
@search_filter_schema_generator ||= definition.search_filter_schema_generator.new(definition, resource_path)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Habarico
|
|
2
|
+
class MethodSchemaGenerator < AbstractGenerator
|
|
3
|
+
|
|
4
|
+
def generate(model, fields, filters)
|
|
5
|
+
Habarico::MethodSchema.new(
|
|
6
|
+
fields: generate_fields(model, fields, filters),
|
|
7
|
+
filters: generate_filters(model, fields, filters)
|
|
8
|
+
)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def fields_schema_generator
|
|
14
|
+
@fields_schema_generator ||= definition.fields_schema_generator.new(definition, resource_path)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def filters_schema_generator
|
|
18
|
+
@filters_schema_generator ||= definition.filters_schema_generator.new(definition, resource_path)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# ***********************************************************************
|
|
22
|
+
# Attribute generators
|
|
23
|
+
# ***********************************************************************
|
|
24
|
+
|
|
25
|
+
def generate_fields(model, fields, _filters)
|
|
26
|
+
fields_schema_generator.generate(model, fields)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def generate_filters(model, _fields, filters)
|
|
30
|
+
filters_schema_generator.generate(model, filters)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|