labimotion 2.1.0.rc4 → 2.1.0.rc5
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 +4 -4
- data/lib/labimotion/apis/generic_element_api.rb +39 -3
- data/lib/labimotion/libs/sample_association.rb +4 -3
- data/lib/labimotion/models/concerns/element_fetchable.rb +53 -0
- data/lib/labimotion/models/device_description.rb +36 -0
- data/lib/labimotion/models/reaction.rb +36 -0
- data/lib/labimotion/models/research_plan.rb +40 -0
- data/lib/labimotion/models/sample.rb +36 -0
- data/lib/labimotion/models/screen.rb +36 -0
- data/lib/labimotion/models/wellplate.rb +40 -0
- data/lib/labimotion/version.rb +1 -1
- data/lib/labimotion.rb +8 -0
- metadata +9 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e23b274f29ceb300bbb97f91830dbe2fdc454966d229e88608cd434b6586a3b3
         | 
| 4 | 
            +
              data.tar.gz: da620e95cb04ce10a69cba25d8cb63f22cb1e21142a1a6a3c93d9fecc33840aa
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: db1827e8ad8c56f05c55215f3cd5e3830174f937875c2af49e7899dc4875180364111b1788eecc430b6f3ca8b39e3e0234eb21a3c1036c3b7ab064676f8bb4d1
         | 
| 7 | 
            +
              data.tar.gz: 3f1667aa18030745ab178330cac70f234d4aa3eab46e3622546aeb4268aaf379e9d8dd0369060324327dd3db67efa2da6e94b6568feb33a88e987bec8030a737
         | 
| @@ -87,6 +87,37 @@ module Labimotion | |
| 87 87 | 
             
                    end
         | 
| 88 88 | 
             
                  end
         | 
| 89 89 |  | 
| 90 | 
            +
                  namespace :search_basic_by_like do
         | 
| 91 | 
            +
                    desc 'Search basic elements by name and short label (case-insensitive like search)'
         | 
| 92 | 
            +
                    params do
         | 
| 93 | 
            +
                      requires :klass_name, type: String, desc: 'Class name (device_description or wellplate or ...etc.)', default: 'device_description'
         | 
| 94 | 
            +
                      requires :name, type: String, desc: 'Search query for basic element name'
         | 
| 95 | 
            +
                      requires :short_label, type: String, desc: 'Search query for basic element short label'
         | 
| 96 | 
            +
                      optional :limit, type: Integer, desc: 'Maximum number of results', default: 20
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
                    get do
         | 
| 99 | 
            +
                      # Convert snake_case to PascalCase (e.g. device_description -> DeviceDescription)
         | 
| 100 | 
            +
                      klass_name = params[:klass_name].camelize
         | 
| 101 | 
            +
                      klass = "Labimotion::#{klass_name}".constantize
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                      scope = klass.fetch_for_user(
         | 
| 104 | 
            +
                        current_user.id,
         | 
| 105 | 
            +
                        name: params[:name],
         | 
| 106 | 
            +
                        short_label: params[:short_label],
         | 
| 107 | 
            +
                        limit: params[:limit]
         | 
| 108 | 
            +
                      )
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                      results = scope.map do |record|
         | 
| 111 | 
            +
                        Labimotion::ElementLookupEntity.represent(record)
         | 
| 112 | 
            +
                      end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                      { elements: results, total_count: results.count }
         | 
| 115 | 
            +
                    rescue StandardError => e
         | 
| 116 | 
            +
                      Labimotion.log_exception(e, current_user)
         | 
| 117 | 
            +
                      { elements: [], total_count: 0, error: e.message }
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
             | 
| 90 121 | 
             
                  namespace :export do
         | 
| 91 122 | 
             
                    desc 'export element'
         | 
| 92 123 | 
             
                    params do
         | 
| @@ -253,12 +284,13 @@ module Labimotion | |
| 253 284 | 
             
                    desc 'list Generic Element Klass'
         | 
| 254 285 | 
             
                    params do
         | 
| 255 286 | 
             
                      optional :is_generic, type: Boolean, desc: 'Is Generic or Non-Generic Element'
         | 
| 256 | 
            -
                      optional :is_active, type: Boolean, desc: 'Active or Inactive | 
| 287 | 
            +
                      optional :is_active, type: Boolean, desc: 'Active or Inactive'
         | 
| 257 288 | 
             
                      optional :displayed_in_list, type: Boolean, desc: 'Display in list format', default: true
         | 
| 258 289 | 
             
                    end
         | 
| 259 290 | 
             
                    get do
         | 
| 260 291 | 
             
                      scope = params[:displayed_in_list] ? Labimotion::ElementKlass.for_list_display : Labimotion::ElementKlass.all
         | 
| 261 292 | 
             
                      scope = scope.where(is_generic: params[:is_generic]) if params.key?(:is_generic)
         | 
| 293 | 
            +
                      scope = scope.where(is_active: params[:is_active]) if params.key?(:is_active)
         | 
| 262 294 |  | 
| 263 295 | 
             
                      list = scope.sort_by(&:place)
         | 
| 264 296 | 
             
                      present list, with: Labimotion::ElementKlassEntity, root: 'klass', displayed_in_list: params[:displayed_in_list]
         | 
| @@ -498,8 +530,12 @@ module Labimotion | |
| 498 530 | 
             
              class ElementLookupEntity < Grape::Entity
         | 
| 499 531 | 
             
                expose :id
         | 
| 500 532 | 
             
                expose :name
         | 
| 501 | 
            -
                expose :short_label
         | 
| 502 | 
            -
             | 
| 533 | 
            +
                expose :short_label do |element|
         | 
| 534 | 
            +
                  element.respond_to?(:short_label) ? element.short_label : nil
         | 
| 535 | 
            +
                end
         | 
| 536 | 
            +
                expose :element_klass_id, as: :element_klass_id do |element|
         | 
| 537 | 
            +
                  element.element_klass&.id
         | 
| 538 | 
            +
                end
         | 
| 503 539 | 
             
                expose :klass_label, as: :klass_label do |element|
         | 
| 504 540 | 
             
                  element.element_klass&.label
         | 
| 505 541 | 
             
                end
         | 
| @@ -113,11 +113,12 @@ module Labimotion | |
| 113 113 | 
             
                      Labimotion::ElementsElement.find_or_create_by(parent_id: element.id, element_id: el.id)
         | 
| 114 114 | 
             
                      els << el.id
         | 
| 115 115 | 
             
                    end
         | 
| 116 | 
            -
             | 
| 117 116 | 
             
                  end
         | 
| 118 117 | 
             
                  if element.present?
         | 
| 119 | 
            -
                     | 
| 120 | 
            -
                     | 
| 118 | 
            +
                    sds = sds.flatten.uniq
         | 
| 119 | 
            +
                    els = els.flatten.uniq
         | 
| 120 | 
            +
                    es_list = sds.present? ? Labimotion::ElementsSample.where(element_id: element.id).where.not(sample_id: sds) : Labimotion::ElementsSample.where(element_id: element.id)
         | 
| 121 | 
            +
                    ee_list = els.present? ? Labimotion::ElementsElement.where(parent_id: element.id).where.not(element_id: els) : Labimotion::ElementsElement.where(parent_id: element.id)
         | 
| 121 122 | 
             
                    es_list.destroy_all if es_list.present?
         | 
| 122 123 | 
             
                    ee_list.destroy_all if ee_list.present?
         | 
| 123 124 | 
             
                  end
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Labimotion
         | 
| 4 | 
            +
              module ElementFetchable
         | 
| 5 | 
            +
                extend ActiveSupport::Concern
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                class_methods do
         | 
| 8 | 
            +
                  def element_klass
         | 
| 9 | 
            +
                    Labimotion::ElementKlass.find_by(name: element_klass_name)
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def fetch_for_user(user_id, name: nil, short_label: nil, limit: 20)
         | 
| 13 | 
            +
                    # Prevent abuse by capping and validating limit
         | 
| 14 | 
            +
                    limit = [limit.to_i, 100].min
         | 
| 15 | 
            +
                    limit = 20 if limit <= 0
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    # Build base scope with common filters
         | 
| 18 | 
            +
                    apply_filters = lambda do |scope|
         | 
| 19 | 
            +
                      scope = scope.where("#{table_name}.name ILIKE ?", "%#{sanitize_sql_like(name)}%") if name.present?
         | 
| 20 | 
            +
                      scope = scope.where("#{table_name}.short_label ILIKE ?", "%#{sanitize_sql_like(short_label)}%") if short_label.present? && column_names.include?('short_label')
         | 
| 21 | 
            +
                      scope
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    # Owned records
         | 
| 25 | 
            +
                    owned = apply_filters.call(
         | 
| 26 | 
            +
                      joins(collections: :user).where(collections: { user_id: user_id })
         | 
| 27 | 
            +
                    )
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    # Shared (synced) records
         | 
| 30 | 
            +
                    shared = apply_filters.call(
         | 
| 31 | 
            +
                      joins(collections: :sync_collections_users).where(sync_collections_users: { user_id: user_id })
         | 
| 32 | 
            +
                    )
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    # Combine (remove duplicates), order, and limit
         | 
| 35 | 
            +
                    order_column = column_names.include?('short_label') ? :short_label : :name
         | 
| 36 | 
            +
                    from("(#{owned.to_sql} UNION #{shared.to_sql}) AS #{table_name}")
         | 
| 37 | 
            +
                      .order(order_column => :desc)
         | 
| 38 | 
            +
                      .limit(limit)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  private
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def element_klass_name
         | 
| 44 | 
            +
                    raise NotImplementedError, "Subclass must define element_klass_name"
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Instance method to get element_klass for a record
         | 
| 49 | 
            +
                def element_klass
         | 
| 50 | 
            +
                  self.class.element_klass
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file extends the existing DeviceDescription model in the consuming app
         | 
| 4 | 
            +
            # and defines a Labimotion::DeviceDescription wrapper for convenient access.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ActiveSupport.on_load(:active_record) do
         | 
| 7 | 
            +
              if defined?(::DeviceDescription)
         | 
| 8 | 
            +
                ::DeviceDescription.class_eval do
         | 
| 9 | 
            +
                  include Labimotion::ElementFetchable
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def self.element_klass_name
         | 
| 12 | 
            +
                    'device_description'
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              else
         | 
| 16 | 
            +
                warn "[Labimotion] DeviceDescription is not defined when Labimotion extension was loaded."
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            # Namespace wrapper to keep your preferred call style
         | 
| 21 | 
            +
            module Labimotion
         | 
| 22 | 
            +
              module DeviceDescription
         | 
| 23 | 
            +
                # Delegate class methods to ::DeviceDescription
         | 
| 24 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 25 | 
            +
                  if ::DeviceDescription.respond_to?(method)
         | 
| 26 | 
            +
                    ::DeviceDescription.public_send(method, *args, &block)
         | 
| 27 | 
            +
                  else
         | 
| 28 | 
            +
                    super
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.respond_to_missing?(method, include_private = false)
         | 
| 33 | 
            +
                  ::DeviceDescription.respond_to?(method, include_private) || super
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file extends the existing Reaction model in the consuming app
         | 
| 4 | 
            +
            # and defines a Labimotion::Reaction wrapper for convenient access.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ActiveSupport.on_load(:active_record) do
         | 
| 7 | 
            +
              if defined?(::Reaction)
         | 
| 8 | 
            +
                ::Reaction.class_eval do
         | 
| 9 | 
            +
                  include Labimotion::ElementFetchable
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def self.element_klass_name
         | 
| 12 | 
            +
                    'reaction'
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              else
         | 
| 16 | 
            +
                warn "[Labimotion] Reaction is not defined when Labimotion extension was loaded."
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            # Namespace wrapper to keep your preferred call style
         | 
| 21 | 
            +
            module Labimotion
         | 
| 22 | 
            +
              module Reaction
         | 
| 23 | 
            +
                # Delegate class methods to ::Reaction
         | 
| 24 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 25 | 
            +
                  if ::Reaction.respond_to?(method)
         | 
| 26 | 
            +
                    ::Reaction.public_send(method, *args, &block)
         | 
| 27 | 
            +
                  else
         | 
| 28 | 
            +
                    super
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.respond_to_missing?(method, include_private = false)
         | 
| 33 | 
            +
                  ::Reaction.respond_to?(method, include_private) || super
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file extends the existing ResearchPlan model in the consuming app
         | 
| 4 | 
            +
            # and defines a Labimotion::ResearchPlan wrapper for convenient access.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # rubocop:disable Style/RedundantConstantBase
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ActiveSupport.on_load(:active_record) do
         | 
| 9 | 
            +
              if defined?(::ResearchPlan)
         | 
| 10 | 
            +
                ::ResearchPlan.class_eval do
         | 
| 11 | 
            +
                  include Labimotion::ElementFetchable
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def self.element_klass_name
         | 
| 14 | 
            +
                    'research_plan'
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              else
         | 
| 18 | 
            +
                warn '[Labimotion] ResearchPlan is not defined when Labimotion extension was loaded.'
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # Namespace wrapper to keep your preferred call style
         | 
| 23 | 
            +
            module Labimotion
         | 
| 24 | 
            +
              module ResearchPlan
         | 
| 25 | 
            +
                # Delegate class methods to ::ResearchPlan
         | 
| 26 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 27 | 
            +
                  if ::ResearchPlan.respond_to?(method)
         | 
| 28 | 
            +
                    ::ResearchPlan.public_send(method, *args, &block)
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    super
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def self.respond_to_missing?(method, include_private = false)
         | 
| 35 | 
            +
                  ::ResearchPlan.respond_to?(method, include_private) || super
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            # rubocop:enable Style/RedundantConstantBase
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file extends the existing Sample model in the consuming app
         | 
| 4 | 
            +
            # and defines a Labimotion::Sample wrapper for convenient access.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ActiveSupport.on_load(:active_record) do
         | 
| 7 | 
            +
              if defined?(::Sample)
         | 
| 8 | 
            +
                ::Sample.class_eval do
         | 
| 9 | 
            +
                  include Labimotion::ElementFetchable
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def self.element_klass_name
         | 
| 12 | 
            +
                    'sample'
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              else
         | 
| 16 | 
            +
                warn "[Labimotion] Sample is not defined when Labimotion extension was loaded."
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            # Namespace wrapper to keep your preferred call style
         | 
| 21 | 
            +
            module Labimotion
         | 
| 22 | 
            +
              module Sample
         | 
| 23 | 
            +
                # Delegate class methods to ::Sample
         | 
| 24 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 25 | 
            +
                  if ::Sample.respond_to?(method)
         | 
| 26 | 
            +
                    ::Sample.public_send(method, *args, &block)
         | 
| 27 | 
            +
                  else
         | 
| 28 | 
            +
                    super
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.respond_to_missing?(method, include_private = false)
         | 
| 33 | 
            +
                  ::Sample.respond_to?(method, include_private) || super
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file extends the existing Screen model in the consuming app
         | 
| 4 | 
            +
            # and defines a Labimotion::Screen wrapper for convenient access.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ActiveSupport.on_load(:active_record) do
         | 
| 7 | 
            +
              if defined?(::Screen)
         | 
| 8 | 
            +
                ::Screen.class_eval do
         | 
| 9 | 
            +
                  include Labimotion::ElementFetchable
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def self.element_klass_name
         | 
| 12 | 
            +
                    'screen'
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              else
         | 
| 16 | 
            +
                warn "[Labimotion] Screen is not defined when Labimotion extension was loaded."
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            # Namespace wrapper to keep your preferred call style
         | 
| 21 | 
            +
            module Labimotion
         | 
| 22 | 
            +
              module Screen
         | 
| 23 | 
            +
                # Delegate class methods to ::Screen
         | 
| 24 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 25 | 
            +
                  if ::Screen.respond_to?(method)
         | 
| 26 | 
            +
                    ::Screen.public_send(method, *args, &block)
         | 
| 27 | 
            +
                  else
         | 
| 28 | 
            +
                    super
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.respond_to_missing?(method, include_private = false)
         | 
| 33 | 
            +
                  ::Screen.respond_to?(method, include_private) || super
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This file extends the existing Wellplate model in the consuming app
         | 
| 4 | 
            +
            # and defines a Labimotion::Wellplate wrapper for convenient access.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # rubocop:disable Style/RedundantConstantBase
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ActiveSupport.on_load(:active_record) do
         | 
| 9 | 
            +
              if defined?(::Wellplate)
         | 
| 10 | 
            +
                ::Wellplate.class_eval do
         | 
| 11 | 
            +
                  include Labimotion::ElementFetchable
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def self.element_klass_name
         | 
| 14 | 
            +
                    'wellplate'
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              else
         | 
| 18 | 
            +
                warn '[Labimotion] Wellplate is not defined when Labimotion extension was loaded.'
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # Namespace wrapper to keep your preferred call style
         | 
| 23 | 
            +
            module Labimotion
         | 
| 24 | 
            +
              module Wellplate
         | 
| 25 | 
            +
                # Delegate class methods to ::Wellplate
         | 
| 26 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 27 | 
            +
                  if ::Wellplate.respond_to?(method)
         | 
| 28 | 
            +
                    ::Wellplate.public_send(method, *args, &block)
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    super
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def self.respond_to_missing?(method, include_private = false)
         | 
| 35 | 
            +
                  ::Wellplate.respond_to?(method, include_private) || super
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            # rubocop:enable Style/RedundantConstantBase
         | 
    
        data/lib/labimotion/version.rb
    CHANGED
    
    
    
        data/lib/labimotion.rb
    CHANGED
    
    | @@ -113,9 +113,17 @@ module Labimotion | |
| 113 113 | 
             
              autoload :StdLayer, 'labimotion/models/std_layer'
         | 
| 114 114 | 
             
              autoload :StdLayersRevision, 'labimotion/models/std_layers_revision'
         | 
| 115 115 |  | 
| 116 | 
            +
              autoload :DeviceDescription, 'labimotion/models/device_description'
         | 
| 117 | 
            +
              autoload :Reaction, 'labimotion/models/reaction'
         | 
| 118 | 
            +
              autoload :ResearchPlan, 'labimotion/models/research_plan'
         | 
| 119 | 
            +
              autoload :Sample, 'labimotion/models/sample'
         | 
| 120 | 
            +
              autoload :Screen, 'labimotion/models/screen'
         | 
| 121 | 
            +
              autoload :Wellplate, 'labimotion/models/wellplate'
         | 
| 122 | 
            +
             | 
| 116 123 | 
             
              ######## Models/Concerns
         | 
| 117 124 | 
             
              autoload :GenericKlassRevisions, 'labimotion/models/concerns/generic_klass_revisions'
         | 
| 118 125 | 
             
              autoload :GenericRevisions, 'labimotion/models/concerns/generic_revisions'
         | 
| 126 | 
            +
              autoload :ElementFetchable, 'labimotion/models/concerns/element_fetchable'
         | 
| 119 127 | 
             
              autoload :Segmentable, 'labimotion/models/concerns/segmentable'
         | 
| 120 128 | 
             
              autoload :Datasetable, 'labimotion/models/concerns/datasetable'
         | 
| 121 129 | 
             
              autoload :AttachmentConverter, 'labimotion/models/concerns/attachment_converter.rb'
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: labimotion
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.1.0. | 
| 4 | 
            +
              version: 2.1.0.rc5
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Chia-Lin Lin
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2025-10- | 
| 12 | 
            +
            date: 2025-10-27 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: caxlsx
         | 
| @@ -116,6 +116,7 @@ files: | |
| 116 116 | 
             
            - lib/labimotion/models/collections_element.rb
         | 
| 117 117 | 
             
            - lib/labimotion/models/concerns/attachment_converter.rb
         | 
| 118 118 | 
             
            - lib/labimotion/models/concerns/datasetable.rb
         | 
| 119 | 
            +
            - lib/labimotion/models/concerns/element_fetchable.rb
         | 
| 119 120 | 
             
            - lib/labimotion/models/concerns/generic_klass.rb
         | 
| 120 121 | 
             
            - lib/labimotion/models/concerns/generic_klass_revisions.rb
         | 
| 121 122 | 
             
            - lib/labimotion/models/concerns/generic_revisions.rb
         | 
| @@ -126,6 +127,7 @@ files: | |
| 126 127 | 
             
            - lib/labimotion/models/dataset_klass.rb
         | 
| 127 128 | 
             
            - lib/labimotion/models/dataset_klasses_revision.rb
         | 
| 128 129 | 
             
            - lib/labimotion/models/datasets_revision.rb
         | 
| 130 | 
            +
            - lib/labimotion/models/device_description.rb
         | 
| 129 131 | 
             
            - lib/labimotion/models/element.rb
         | 
| 130 132 | 
             
            - lib/labimotion/models/element_klass.rb
         | 
| 131 133 | 
             
            - lib/labimotion/models/element_klasses_revision.rb
         | 
| @@ -133,6 +135,10 @@ files: | |
| 133 135 | 
             
            - lib/labimotion/models/elements_revision.rb
         | 
| 134 136 | 
             
            - lib/labimotion/models/elements_sample.rb
         | 
| 135 137 | 
             
            - lib/labimotion/models/hub_log.rb
         | 
| 138 | 
            +
            - lib/labimotion/models/reaction.rb
         | 
| 139 | 
            +
            - lib/labimotion/models/research_plan.rb
         | 
| 140 | 
            +
            - lib/labimotion/models/sample.rb
         | 
| 141 | 
            +
            - lib/labimotion/models/screen.rb
         | 
| 136 142 | 
             
            - lib/labimotion/models/segment.rb
         | 
| 137 143 | 
             
            - lib/labimotion/models/segment_klass.rb
         | 
| 138 144 | 
             
            - lib/labimotion/models/segment_klasses_revision.rb
         | 
| @@ -140,6 +146,7 @@ files: | |
| 140 146 | 
             
            - lib/labimotion/models/std_layer.rb
         | 
| 141 147 | 
             
            - lib/labimotion/models/std_layers_revision.rb
         | 
| 142 148 | 
             
            - lib/labimotion/models/vocabulary.rb
         | 
| 149 | 
            +
            - lib/labimotion/models/wellplate.rb
         | 
| 143 150 | 
             
            - lib/labimotion/utils/con_state.rb
         | 
| 144 151 | 
             
            - lib/labimotion/utils/export_utils.rb
         | 
| 145 152 | 
             
            - lib/labimotion/utils/field_type.rb
         |