codn/adminpanel

View on GitHub
app/models/concerns/adminpanel/base.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Adminpanel API
# This file must be included on every adminpanel resource.

module Adminpanel
  module Base
    extend ActiveSupport::Concern

    module ClassMethods
      FILE_FIELD_NAME = 'adminpanel_file_field'


      def mount_images(relation)
        has_many relation, dependent: :destroy, as: :model
        accepts_nested_attributes_for relation, allow_destroy: true
        after_save :destroy_unattached_images
        after_save :correlative_order_gallery, if: Proc.new { |model| model.class.has_sortable_gallery? }
      end

      # implementing cache by default.
      def belongs_to(name, scope = nil, **options)
        super(name, scope, options.reverse_merge!({touch: true}))
      end

      # The fields and the types that should be used to generate form
      # and display fields
      def form_attributes
        []
      end

      # The name that is going to be shown in the new button and that is going
      # to be pluralized (if not overwritten) to generate collection_name
      def display_name
        'please overwrite self.display_name'
      end

      # fontawesome icon to be used in the side-menu
      def icon
        'truck'
      end

      # The word that is going to be shown in the side menu, routes and
      # breadcrumb.
      def collection_name
        display_name.pluralize(I18n.default_locale)
      end

      def get_attribute_label(field)
        form_attributes.each do |attribute|
          attribute.each do |name, properties|
            if name == field
              return properties['label']
            end
          end
        end
        return field
      end

      # returns the attributes that should be shown in the correspondin view
      # (some attributes may be filtered from the index table, from the show
      # or even both)
      def display_attributes(type)
        display_attributes = []
        form_attributes.each do |attribute|
          attribute.each do |_, properties|
            if (
              properties['show'].nil? ||
              properties['show'] == 'true' ||
              (
                properties['show'] == type &&
                properties['type'] != FILE_FIELD_NAME #file fields get only displayed in form
              )
            )
              display_attributes << attribute
            end
          end
        end
        return display_attributes
      end

      # Check if this models has a gallery in its attributes
      # @return boolean
      def has_gallery?
        form_attributes.each do |fields|
          fields.each do |attribute, properties|
            if properties['type'] == FILE_FIELD_NAME
              return true
            end
          end
        end
        false
      end

      # Check if this models has a trix editor with a gallery in its attributes
      # @return boolean
      def has_trix_gallery?
        form_attributes.each do |fields|
          fields.each do |attribute, properties|
            if properties['type'] == 'wysiwyg_field' && properties['uploader'].present?
              return true
            end
          end
        end
        false
      end

      # Returns an array with all the adminpanel_file_field`s attributes found
      # in form_attributes
      # @return Hash
      # => { sectionfiles: Adminpanel::SectionFile, ... }
      def galleries
        galleries = {}
        form_attributes.each do |fields|
          fields.each do |relation, properties|
            if properties['type'] == FILE_FIELD_NAME
              galleries["#{relation.singularize}"] = "adminpanel/#{relation}".classify.constantize.to_s
            end
          end
        end

        return galleries
      end

      # Returns an array with all the adminpanel_file_field`s attributes who are
      # sortable found in form_attributes
      # @return Hash
      def sortable_galleries
        galleries = {}
        form_attributes.each do |fields|
          fields.each do |relation, properties|
            if properties['type'] == FILE_FIELD_NAME && "adminpanel/#{relation}".classify.constantize.is_sortable?
              galleries["#{relation.singularize}"] = "adminpanel/#{relation}".classify.constantize.to_s
            end
          end
        end

        galleries
      end

      # returns the attribute that should be namespaced to be the class
      # ex: returns 'productfiles', so class is Adminpanel::Productfile
      def gallery_relationship
        form_attributes.each do |fields|
          fields.each do |attribute, properties|
            if properties['type'] == FILE_FIELD_NAME
              return attribute
            end
          end
        end
        return false
      end

      # gets the class gallery and return it's class
      def gallery_class
        "adminpanel/#{gallery_relationship}".classify.constantize
      end

      # Search for a model attribute's that are of a given type
      # @return Array
      # Usage:
      # To get all classes of all belongs_to attributes:
      #   @model.relationships_of('belongs_to')
      #   # => ['Adminpanel::Category', Adminpanel::ModelBelongTo]
      def relationships_of(type_property)
        classes_of_relation = []
        form_attributes.each do |fields|
          fields.each do |attribute, properties|
            if properties['type'] == type_property
              classes_of_relation << properties['model'].classify.constantize
            end
          end
        end
        return classes_of_relation
      end

      # routes options to be used when generating this model routes
      # @return Hash
      def routes_options
        { path: collection_name.parameterize }
      end

      def has_route?(route)
        if (!exclude_route?(route)) && include_route?(route)
          true
        else
          false
        end
      end

      def fb_share?
        false
      end

      # Additional member routes for this resource
      def member_routes
        []
      end

      # Additional collection routes for this resource
      def collection_routes
        []
      end

      def is_sortable?
        false
      end

      def has_sortable_gallery?
        !sortable_galleries.empty?
      end

      def to_controller_name
        to_s.demodulize.underscore.pluralize
      end

      def form_url
        self
      end

      private

        def exclude_route?(route)
          if routes_options[:except].nil?
            false
          elsif routes_options[:except].include?(route)
            true
          else
            false
          end
        end

        def include_route?(route)
          if routes_options[:only].nil? || routes_options[:only].include?(route)
            true
          else
            false
          end
        end

      end

      def destroy_unattached_images
        self.class.galleries.each{|gallery| gallery.last.constantize.where(model_id: nil).delete_all }
      end

      def correlative_order_gallery
        self.class.galleries.each do |gallery|
          self.send(gallery.first.pluralize).ordered.each_with_index{ |image, index| image.update(position: index + 1) }
        end
      end
  end
end