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)