lib/avo/base_resource.rb in avo-3.0.0.pre13 vs lib/avo/base_resource.rb in avo-3.0.0.pre14
- old
+ new
@@ -82,18 +82,22 @@
def scope(scope_class)
deprecated_dsl_api __method__, "scopes"
end
# This resolves the scope when doing "where" queries (not find queries)
+ #
+ # It's used to apply the authorization feature.
def query_scope
authorization.apply_policy Avo::ExecutionContext.new(
target: index_query,
query: model_class
).handle
end
# This resolves the scope when finding records (not "where" queries)
+ #
+ # It's used to apply the authorization feature.
def find_scope
authorization.apply_policy model_class
end
def authorization
@@ -125,26 +129,119 @@
get_available_models.find do |m|
m.to_s == model_name.to_s
end
end
+ # Returns the model class being used for this resource.
+ #
+ # The Resource instance has a model_class method too so it can support the STI use cases
+ # where we figure out the model class from the record
+ def model_class(record_class: nil)
+ # get the model class off of the static property
+ return @model_class if @model_class.present?
+
+ # get the model class off of the record for STI models
+ return record_class if record_class.present?
+
+ # generate a model class
+ class_name.safe_constantize
+ end
+
+ # This is used as the model class ID
+ # We use this instead of the route_key to maintain compatibility with uncountable models
+ # With uncountable models route key appends an _index suffix (Fish->fish_index)
+ # Example: User->users, MediaItem->media_items, Fish->fish
+ def model_key
+ model_class.model_name.plural
+ end
+
def class_name
- name.demodulize
+ to_s.demodulize
end
def route_key
class_name.underscore.pluralize
end
def singular_route_key
route_key.singularize
end
+
+ def translation_key
+ @translation_key || "avo.resource_translations.#{class_name.underscore}"
+ end
+
+ def name
+ default = class_name.underscore.humanize
+
+ if translation_key
+ t(translation_key, count: 1, default: default).capitalize
+ else
+ default
+ end
+ end
+ alias_method :singular_name, :name
+
+ def plural_name
+ default = name.pluralize
+
+ if translation_key
+ t(translation_key, count: 2, default: default).capitalize
+ else
+ default
+ end
+ end
+
+ def underscore_name
+ return @name if @name.present?
+
+ name.demodulize.underscore
+ end
+
+ def navigation_label
+ plural_name.humanize
+ end
+
+ def find_record(id, query: nil, params: nil)
+ Avo::ExecutionContext.new(
+ target: find_record_method,
+ query: query || find_scope, # If no record is given we'll use the default
+ id: id,
+ params: params
+ ).handle
+ end
+
+ def search_query
+ search.dig(:query)
+ end
+
+ def fetch_search(key, record: nil)
+ # self.class.fetch_search
+ Avo::ExecutionContext.new(target: search[key], resource: self, record: record).handle
+ end
end
delegate :context, to: ::Avo::Current
+ delegate :name, to: :class
+ delegate :singular_name, to: :class
+ delegate :plural_name, to: :class
+ delegate :underscore_name, to: :class
+ delegate :underscore_name, to: :class
+ delegate :find_record, to: :class
+ delegate :model_key, to: :class
- def initialize
+ def initialize(record: nil, view: nil, user: nil, params: nil)
+ @view = view if view.present?
+ @user = user if user.present?
+ @params = params if params.present?
+
+ if record.present?
+ @record = record
+
+ hydrate_model_with_default_values if @view == :new
+ end
+
detect_fields
unless self.class.model_class.present?
if model_class.present? && model_class.respond_to?(:base_class)
self.class.model_class = model_class.base_class
@@ -192,11 +289,11 @@
entity_loader(entity).bag
end
# def get_action_arguments / def get_filter_arguments / def get_scope_arguments
define_method "get_#{entity}_arguments" do |entity_class|
- send("get_#{plural_entity}").find { |entity| entity[:class] == entity_class.constantize }[:arguments]
+ send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }[:arguments]
end
end
def hydrate(record: nil, view: nil, user: nil, params: nil)
@view = view if view.present?
@@ -223,19 +320,18 @@
when :new
t("avo.create_new_item", item: name.downcase).upcase_first
end
end
+ # Returns the model class being used for this resource.
+ #
+ # We use the class method as a fallback but we pass it the record too so it can support the STI use cases
+ # where we figure out the model class from that record.
def model_class
- # get the model class off of the static property
- return self.class.model_class if self.class.model_class.present?
+ record_class = @record&.class
- # get the model class off of the record
- return @record.base_class if @record.present?
-
- # generate a model class
- class_name.safe_constantize
+ self.class.model_class record_class: record_class
end
def record_title
return name if @record.nil?
@@ -249,50 +345,10 @@
when Proc
Avo::ExecutionContext.new(target: title, resource: self, record: @record).handle
end
end
- def translation_key
- self.class.translation_key || "avo.resource_translations.#{class_name.underscore}"
- end
-
- def name
- return @name if @name.present?
-
- default = class_name.underscore.humanize
-
- if translation_key
- t(translation_key, count: 1, default: default).capitalize
- else
- default
- end
- end
-
- def singular_name
- name
- end
-
- def plural_name
- default = name.pluralize
-
- if translation_key
- t(translation_key, count: 2, default: default).capitalize
- else
- default
- end
- end
-
- def underscore_name
- return @name if @name.present?
-
- self.class.name.demodulize.underscore
- end
-
- def navigation_label
- plural_name.humanize
- end
-
def available_view_types
if self.class.view_types.present?
return Array(
Avo::ExecutionContext.new(
target: self.class.view_types,
@@ -308,27 +364,29 @@
view_types << :map if map_view.present?
view_types
end
- def attached_file_fields
+ def attachment_fields
get_field_definitions.select do |field|
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
end
end
- def fill_record(record, params, extra_params: [])
- # Map the received params to their actual fields
- fields_by_database_id = get_field_definitions
+ # Map the received params to their actual fields
+ def fields_by_database_id
+ get_field_definitions
.reject do |field|
field.computed
end
.map do |field|
[field.database_id.to_s, field]
end
.to_h
+ end
+ def fill_record(record, params, extra_params: [])
# Write the field values
params.each do |key, value|
field = fields_by_database_id[key]
next unless field.present?
@@ -381,53 +439,41 @@
default_values = get_fields
.select do |field|
!field.computed
end
.map do |field|
- id = field.id
value = field.value
if field.type == "belongs_to"
- id = field.foreign_key.to_sym
reflection = @record._reflections[@params[:via_relation]]
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
# set the value to the actual record
- via_resource = Avo::App.resources.get_resource_by_model_class(@params[:via_relation_class])
+ via_resource = Avo.resource_manager.get_resource_by_model_class(@params[:via_relation_class])
value = via_resource.find_record(@params[:via_record_id])
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
- resource = Avo::App.resources.get_resource_by_model_class params[:via_relation_class]
+ resource = Avo.resource_manager.get_resource_by_model_class params[:via_relation_class]
record = resource.find_record @params[:via_record_id], params: params
id_param = reflection.options[:primary_key] || :id
value = record.send(id_param)
end
end
- [id, value]
+ [field, value]
end
.to_h
- .select do |id, value|
+ .select do |_, value|
value.present?
end
- default_values.each do |id, value|
- if @record.send(id).nil?
- @record.send("#{id}=", value)
- end
+ default_values.each do |field, value|
+ field.assign_value record: @record, value: value
end
end
- # This is used as the model class ID
- # We use this instead of the route_key to maintain compatibility with uncountable models
- # With uncountable models route key appends an _index suffix (Fish->fish_index)
- # Example: User->users, MediaItem->media_items, Fish->fish
- def model_key
- model_class.model_name.plural
- end
-
def model_name
model_class.model_name
end
def singular_model_key
@@ -472,19 +518,10 @@
def has_record_id?
record.present? && record_id.present?
end
- def find_record(id, query: nil, params: nil)
- Avo::ExecutionContext.new(
- target: self.class.find_record_method,
- query: query || self.class.find_scope,
- id: id,
- params: params
- ).handle
- end
-
def id_attribute
:id
end
def record_id
@@ -495,17 +532,9 @@
{
view: view,
resource: self,
record: record
}
- end
-
- def search_query
- self.class.search.dig(:query)
- end
-
- def fetch_search(key)
- Avo::ExecutionContext.new(target: self.class.search[key], resource: self, record: record).handle
end
private
def entity_loader(entity)