linked_rails 0.0.4.pre.g2c53724b3 → 0.0.4.pre.g72bb595fe
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/app/controllers/linked_rails/bulk_controller.rb +34 -1
- data/app/models/linked_rails/form.rb +1 -0
- data/app/models/linked_rails/manifest.rb +24 -8
- data/app/models/linked_rails/menus/list.rb +1 -1
- data/app/models/linked_rails/ontology.rb +1 -0
- data/app/policies/linked_rails/form_policy.rb +13 -0
- data/app/policies/linked_rails/ontology_policy.rb +13 -0
- data/app/workers/linked_rails/invalidation_stream_worker.rb +16 -0
- data/lib/generators/linked_rails/install/templates/locales.yml +2 -0
- data/lib/linked_rails/controller/error_handling.rb +5 -0
- data/lib/linked_rails/errors/forbidden.rb +37 -0
- data/lib/linked_rails/errors.rb +3 -0
- data/lib/linked_rails/helpers/resource_helper.rb +7 -0
- data/lib/linked_rails/model/cacheable.rb +45 -0
- data/lib/linked_rails/model.rb +1 -0
- data/lib/linked_rails/policy.rb +4 -0
- data/lib/linked_rails/storage.rb +32 -0
- data/lib/linked_rails.rb +6 -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: 7810fdc42df9533cc1828c33aec04953486145ee0c744607b01b5f514d67dcb0
         | 
| 4 | 
            +
              data.tar.gz: 9056187a625becc1c3e4c234ae7b06b77e77f0d4d3bdcb5d6c24b1249e1e21a9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: d294b57b181d6995d88ee5967c61d9bd5c69a2a1e3dc6843848032c4f9ee36c7c762d2f163022e97cdd35219bc6d395392b0af9863ab7f0a4dcb924f5c4358ef
         | 
| 7 | 
            +
              data.tar.gz: 880a18f47ab624f736ab12421c3ea8c6a4810f9602149d35efca16e5edb21e9563280bfbe9721acf0860a5c7a2602632a0f7056ca5cd7b207e9e4c7582da9f5c
         | 
| @@ -21,8 +21,11 @@ module LinkedRails | |
| 21 21 | 
             
                  return response_for_wrong_host(opts) if wrong_host?(opts[:iri])
         | 
| 22 22 |  | 
| 23 23 | 
             
                  include = opts[:include].to_s == 'true'
         | 
| 24 | 
            +
                  resource = LinkedRails.iri_mapper.resource_from_iri(request_path_to_url(opts[:iri]), user_context)
         | 
| 24 25 |  | 
| 25 | 
            -
                  response_from_request(include, RDF::URI(opts[:iri]))
         | 
| 26 | 
            +
                  return response_from_request(include, RDF::URI(opts[:iri])) if resource.blank?
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  response_from_resource(include, opts[:iri], resource)
         | 
| 26 29 | 
             
                rescue StandardError => e
         | 
| 27 30 | 
             
                  handle_resource_error(opts, e)
         | 
| 28 31 | 
             
                end
         | 
| @@ -84,6 +87,13 @@ module LinkedRails | |
| 84 87 | 
             
                  false
         | 
| 85 88 | 
             
                end
         | 
| 86 89 |  | 
| 90 | 
            +
                def resource_cache_control(cacheable, status, resource_policy)
         | 
| 91 | 
            +
                  return :private unless status == 200 && cacheable
         | 
| 92 | 
            +
                  return 'no-cache' unless resource_policy.try(:public_resource?)
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  :public
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 87 97 | 
             
                def resource_params(param)
         | 
| 88 98 | 
             
                  params = param.permit(:include, :iri)
         | 
| 89 99 | 
             
                  params[:iri] = URI(params[:iri])
         | 
| @@ -131,6 +141,12 @@ module LinkedRails | |
| 131 141 | 
             
                  }.merge(opts)
         | 
| 132 142 | 
             
                end
         | 
| 133 143 |  | 
| 144 | 
            +
                def resource_status(resource_policy)
         | 
| 145 | 
            +
                  raise(LinkedRails::Errors::Forbidden.new(query: :show?)) unless resource_policy.show?
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                  200
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
             | 
| 134 150 | 
             
                def response_for_wrong_host(opts)
         | 
| 135 151 | 
             
                  iri = opts[:iri]
         | 
| 136 152 | 
             
                  term = term_from_vocab(iri)
         | 
| @@ -139,6 +155,23 @@ module LinkedRails | |
| 139 155 | 
             
                  ontology_term_response(iri, term, opts[:include])
         | 
| 140 156 | 
             
                end
         | 
| 141 157 |  | 
| 158 | 
            +
                def response_from_resource(include, iri, resource)
         | 
| 159 | 
            +
                  resource_policy = policy(resource)
         | 
| 160 | 
            +
                  status = resource_status(resource_policy)
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                  resource_response(
         | 
| 163 | 
            +
                    iri,
         | 
| 164 | 
            +
                    body: response_from_resource_body(include, iri, resource, status),
         | 
| 165 | 
            +
                    cache: resource_cache_control(resource.try(:cacheable?), status, resource_policy),
         | 
| 166 | 
            +
                    language: I18n.locale,
         | 
| 167 | 
            +
                    status: status
         | 
| 168 | 
            +
                  )
         | 
| 169 | 
            +
                end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                def response_from_resource_body(include, _iri, resource, status)
         | 
| 172 | 
            +
                  include && status == 200 ? resource_body(resource) : nil
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
             | 
| 142 175 | 
             
                def term_from_vocab(iri)
         | 
| 143 176 | 
             
                  vocab = Vocab.for(iri)
         | 
| 144 177 | 
             
                  tag = iri.to_s.split(vocab.to_s).last
         | 
| @@ -5,15 +5,11 @@ module LinkedRails | |
| 5 5 | 
             
                include ActiveModel::Model
         | 
| 6 6 | 
             
                include LinkedRails::Model
         | 
| 7 7 |  | 
| 8 | 
            -
                MANIFEST_KEY = 'cache:Manifest'
         | 
| 9 | 
            -
                CACHE_DB = ENV.fetch('PERSISTENT_REDIS_DATABASE', '6')
         | 
| 10 | 
            -
             | 
| 11 8 | 
             
                def save
         | 
| 12 | 
            -
                   | 
| 13 | 
            -
                     | 
| 14 | 
            -
                     | 
| 15 | 
            -
             | 
| 16 | 
            -
                    }
         | 
| 9 | 
            +
                  Storage.hset(
         | 
| 10 | 
            +
                    :persistent,
         | 
| 11 | 
            +
                    :manifest,
         | 
| 12 | 
            +
                    LinkedRails.iri.to_s => web_manifest.to_json
         | 
| 17 13 | 
             
                  )
         | 
| 18 14 | 
             
                end
         | 
| 19 15 |  | 
| @@ -162,5 +158,25 @@ module LinkedRails | |
| 162 158 | 
             
                def tracking
         | 
| 163 159 | 
             
                  []
         | 
| 164 160 | 
             
                end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                class << self
         | 
| 163 | 
            +
                  def destroy(iri)
         | 
| 164 | 
            +
                    Storage.hdel(:persistent, :manifest, iri)
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                  def move(from, to)
         | 
| 168 | 
            +
                    Storage.hset(
         | 
| 169 | 
            +
                      :persistent,
         | 
| 170 | 
            +
                      :redirect_prefix,
         | 
| 171 | 
            +
                      from => to
         | 
| 172 | 
            +
                    )
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                    data = Storage.hget(:persistent, :manifest, from)
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                    Storage.hset(:persistent, :manifest, to, data) if data
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                    destroy(from)
         | 
| 179 | 
            +
                  end
         | 
| 180 | 
            +
                end
         | 
| 165 181 | 
             
              end
         | 
| 166 182 | 
             
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module LinkedRails
         | 
| 4 | 
            +
              class InvalidationStreamWorker < ActiveJob::Base
         | 
| 5 | 
            +
                def perform(type, iri, resource_type)
         | 
| 6 | 
            +
                  entry = {
         | 
| 7 | 
            +
                    type: type,
         | 
| 8 | 
            +
                    resource: iri,
         | 
| 9 | 
            +
                    resourceType: resource_type
         | 
| 10 | 
            +
                  }
         | 
| 11 | 
            +
                  id = Storage.xadd(:stream, LinkedRails.cache_stream, entry)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  raise('No message id returned, implies failure') if id.blank?
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -6,6 +6,10 @@ module LinkedRails | |
| 6 6 | 
             
                  extend ActiveSupport::Concern
         | 
| 7 7 | 
             
                  include ActiveSupport::Rescuable
         | 
| 8 8 |  | 
| 9 | 
            +
                  included do
         | 
| 10 | 
            +
                    rescue_from LinkedRails::Errors::Forbidden, with: :handle_error
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 9 13 | 
             
                  private
         | 
| 10 14 |  | 
| 11 15 | 
             
                  def add_error_snackbar(error)
         | 
| @@ -69,6 +73,7 @@ module LinkedRails | |
| 69 73 | 
             
                        'Doorkeeper::Errors::InvalidGrantReuse' => 422,
         | 
| 70 74 | 
             
                        'LinkedRails::Auth::Errors::Expired' => 410,
         | 
| 71 75 | 
             
                        'LinkedRails::Auth::Errors::Unauthorized' => 401,
         | 
| 76 | 
            +
                        'LinkedRails::Errors::Forbidden' => 403,
         | 
| 72 77 | 
             
                        'Pundit::NotAuthorizedError' => 403
         | 
| 73 78 | 
             
                      }
         | 
| 74 79 | 
             
                    end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module LinkedRails
         | 
| 4 | 
            +
              module Errors
         | 
| 5 | 
            +
                class Forbidden < StandardError
         | 
| 6 | 
            +
                  attr_reader :query, :record, :policy, :action
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  # @param [Hash] options
         | 
| 9 | 
            +
                  # @option options [String] query The action of the request
         | 
| 10 | 
            +
                  # @option options [ActiveRecord::Base] record The record that was requested
         | 
| 11 | 
            +
                  # @option options [Policy] policy The policy that raised the exception
         | 
| 12 | 
            +
                  # @option options [String] message Override the default error message
         | 
| 13 | 
            +
                  # @return [String] the message
         | 
| 14 | 
            +
                  def initialize(**options)
         | 
| 15 | 
            +
                    @query  = options.fetch(:query).to_s
         | 
| 16 | 
            +
                    @record = options[:record]
         | 
| 17 | 
            +
                    @policy = options[:policy]
         | 
| 18 | 
            +
                    @action = @query[-1] == '?' ? @query[0..-2] : @query
         | 
| 19 | 
            +
                    @message = options[:message]
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    raise StandardError if @query.blank? && @message.blank?
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    super(@message || default_message)
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def default_message
         | 
| 29 | 
            +
                    I18n.t(
         | 
| 30 | 
            +
                      "pundit.#{@policy.class.to_s.underscore}.#{@query}",
         | 
| 31 | 
            +
                      action: @action,
         | 
| 32 | 
            +
                      default: I18n.t('errors.access_denied')
         | 
| 33 | 
            +
                    )
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -46,6 +46,13 @@ module LinkedRails | |
| 46 46 |  | 
| 47 47 | 
             
                  private
         | 
| 48 48 |  | 
| 49 | 
            +
                  def request_path_to_url(path)
         | 
| 50 | 
            +
                    return path unless path.present? && URI(path).relative?
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    port = [80, 443].include?(request.port) ? nil : request.port
         | 
| 53 | 
            +
                    URI::Generic.new(request.scheme, nil, request.host, port, nil, path, nil, nil, nil).to_s
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 49 56 | 
             
                  def build_new_resource
         | 
| 50 57 | 
             
                    controller_class.build_new(user_context: user_context)
         | 
| 51 58 | 
             
                  end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module LinkedRails
         | 
| 4 | 
            +
              module Model
         | 
| 5 | 
            +
                module Cacheable
         | 
| 6 | 
            +
                  extend ActiveSupport::Concern
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  included do
         | 
| 9 | 
            +
                    if respond_to?(:after_commit)
         | 
| 10 | 
            +
                      after_commit :publish_create, on: :create, if: :should_publish_changes
         | 
| 11 | 
            +
                      after_commit :publish_update, on: :update, if: :should_publish_changes
         | 
| 12 | 
            +
                      after_commit :publish_delete, on: :destroy, if: :should_publish_changes
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def cacheable?
         | 
| 17 | 
            +
                    true
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def publish_create
         | 
| 21 | 
            +
                    publish_message('io.ontola.transactions.Created')
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def publish_update
         | 
| 25 | 
            +
                    publish_message('io.ontola.transactions.Updated')
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def publish_delete
         | 
| 29 | 
            +
                    publish_message('io.ontola.transactions.Deleted')
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  private
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def publish_message(type)
         | 
| 35 | 
            +
                    LinkedRails::InvalidationStreamWorker.perform_now(type, iri.to_s, self.class.iri.to_s)
         | 
| 36 | 
            +
                  rescue StandardError
         | 
| 37 | 
            +
                    LinkedRails::InvalidationStreamWorker.perform_later(type, iri.to_s, self.class.iri.to_s)
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def should_publish_changes
         | 
| 41 | 
            +
                    cacheable? && !Rails.env.test?
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
    
        data/lib/linked_rails/model.rb
    CHANGED
    
    
    
        data/lib/linked_rails/policy.rb
    CHANGED
    
    
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'redis'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module LinkedRails
         | 
| 6 | 
            +
              class Storage
         | 
| 7 | 
            +
                REDIS_DB = {
         | 
| 8 | 
            +
                  cache: LinkedRails.cache_redis_database,
         | 
| 9 | 
            +
                  persistent: LinkedRails.persistent_redis_database,
         | 
| 10 | 
            +
                  stream: LinkedRails.stream_redis_database
         | 
| 11 | 
            +
                }.freeze
         | 
| 12 | 
            +
                KEYS = {
         | 
| 13 | 
            +
                  manifest: 'cache:Manifest',
         | 
| 14 | 
            +
                  redirect_exact: 'cache:Redirect:Exact',
         | 
| 15 | 
            +
                  redirect_prefix: 'cache:Redirect:Prefix'
         | 
| 16 | 
            +
                }.freeze
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                class << self
         | 
| 19 | 
            +
                  %i[xadd].each do |method|
         | 
| 20 | 
            +
                    define_method(method) do |db, *args|
         | 
| 21 | 
            +
                      Redis.new(db: REDIS_DB.fetch(db)).send(method, *args)
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  %i[hset hdel hget].each do |method|
         | 
| 26 | 
            +
                    define_method(method) do |db, key, *args|
         | 
| 27 | 
            +
                      Redis.new(db: REDIS_DB.fetch(db)).send(method, KEYS.fetch(key), *args)
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/linked_rails.rb
    CHANGED
    
    | @@ -22,6 +22,10 @@ module LinkedRails | |
| 22 22 |  | 
| 23 23 | 
             
              mattr_accessor :whitelisted_spi_ips
         | 
| 24 24 | 
             
              mattr_writer :host, :scheme
         | 
| 25 | 
            +
              mattr_accessor :persistent_redis_database, default: ENV['PERSISTENT_REDIS_DATABASE'].presence || 6
         | 
| 26 | 
            +
              mattr_accessor :stream_redis_database, default: ENV['STREAM_REDIS_DATABASE'].presence || 7
         | 
| 27 | 
            +
              mattr_accessor :cache_redis_database, default: ENV['CACHE_REDIS_DATABASE'].presence || 8
         | 
| 28 | 
            +
              mattr_accessor :cache_stream, default: ENV['CACHE_STREAM'].presence || 'transactions'
         | 
| 25 29 |  | 
| 26 30 | 
             
              def self.configurable_class(parent, klass, default: nil, reader: nil) # rubocop:disable Metrics/AbcSize
         | 
| 27 31 | 
             
                method = :"#{[parent, klass.to_s.downcase].compact.join('_')}_class"
         | 
| @@ -84,6 +88,7 @@ ActiveSupport::Inflector.inflections do |inflect| | |
| 84 88 | 
             
              inflect.acronym 'SHACL'
         | 
| 85 89 | 
             
            end
         | 
| 86 90 |  | 
| 91 | 
            +
            require 'linked_rails/errors'
         | 
| 87 92 | 
             
            require 'linked_rails/uri_template'
         | 
| 88 93 | 
             
            require 'linked_rails/vocab'
         | 
| 89 94 | 
             
            require 'linked_rails/cache'
         | 
| @@ -101,3 +106,4 @@ require 'linked_rails/routes' | |
| 101 106 | 
             
            require 'linked_rails/serializer'
         | 
| 102 107 | 
             
            require 'linked_rails/translate'
         | 
| 103 108 | 
             
            require 'linked_rails/railtie'
         | 
| 109 | 
            +
            require 'linked_rails/storage'
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: linked_rails
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0.4.pre. | 
| 4 | 
            +
              version: 0.0.4.pre.g72bb595fe
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Arthur Dingemans
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022-08- | 
| 11 | 
            +
            date: 2022-08-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: active_response
         | 
| @@ -299,8 +299,10 @@ files: | |
| 299 299 | 
             
            - app/policies/linked_rails/collection/view_policy.rb
         | 
| 300 300 | 
             
            - app/policies/linked_rails/collection_policy.rb
         | 
| 301 301 | 
             
            - app/policies/linked_rails/enum_value_policy.rb
         | 
| 302 | 
            +
            - app/policies/linked_rails/form_policy.rb
         | 
| 302 303 | 
             
            - app/policies/linked_rails/menus/item_policy.rb
         | 
| 303 304 | 
             
            - app/policies/linked_rails/menus/list_policy.rb
         | 
| 305 | 
            +
            - app/policies/linked_rails/ontology_policy.rb
         | 
| 304 306 | 
             
            - app/policies/linked_rails/sequence_policy.rb
         | 
| 305 307 | 
             
            - app/serializers/linked_rails/actions/item_serializer.rb
         | 
| 306 308 | 
             
            - app/serializers/linked_rails/actions/object_serializer.rb
         | 
| @@ -338,6 +340,7 @@ files: | |
| 338 340 | 
             
            - app/serializers/linked_rails/web_page_serializer.rb
         | 
| 339 341 | 
             
            - app/serializers/linked_rails/web_site_serializer.rb
         | 
| 340 342 | 
             
            - app/serializers/linked_rails/widget_serializer.rb
         | 
| 343 | 
            +
            - app/workers/linked_rails/invalidation_stream_worker.rb
         | 
| 341 344 | 
             
            - config/initializers/inflections.rb
         | 
| 342 345 | 
             
            - lib/generators/linked_rails/install/install_generator.rb
         | 
| 343 346 | 
             
            - lib/generators/linked_rails/install/templates/README
         | 
| @@ -387,6 +390,8 @@ files: | |
| 387 390 | 
             
            - lib/linked_rails/enhancements/destroyable/controller.rb
         | 
| 388 391 | 
             
            - lib/linked_rails/enhancements/updatable/controller.rb
         | 
| 389 392 | 
             
            - lib/linked_rails/enhancements/updatable/serializer.rb
         | 
| 393 | 
            +
            - lib/linked_rails/errors.rb
         | 
| 394 | 
            +
            - lib/linked_rails/errors/forbidden.rb
         | 
| 390 395 | 
             
            - lib/linked_rails/helpers/delta_helper.rb
         | 
| 391 396 | 
             
            - lib/linked_rails/helpers/ontola_actions_helper.rb
         | 
| 392 397 | 
             
            - lib/linked_rails/helpers/resource_helper.rb
         | 
| @@ -395,6 +400,7 @@ files: | |
| 395 400 | 
             
            - lib/linked_rails/middleware/linked_data_params.rb
         | 
| 396 401 | 
             
            - lib/linked_rails/model.rb
         | 
| 397 402 | 
             
            - lib/linked_rails/model/actionable.rb
         | 
| 403 | 
            +
            - lib/linked_rails/model/cacheable.rb
         | 
| 398 404 | 
             
            - lib/linked_rails/model/collections.rb
         | 
| 399 405 | 
             
            - lib/linked_rails/model/dirty.rb
         | 
| 400 406 | 
             
            - lib/linked_rails/model/enhancements.rb
         | 
| @@ -418,6 +424,7 @@ files: | |
| 418 424 | 
             
            - lib/linked_rails/serializer/actionable.rb
         | 
| 419 425 | 
             
            - lib/linked_rails/serializer/menuable.rb
         | 
| 420 426 | 
             
            - lib/linked_rails/serializer/singularable.rb
         | 
| 427 | 
            +
            - lib/linked_rails/storage.rb
         | 
| 421 428 | 
             
            - lib/linked_rails/test_methods.rb
         | 
| 422 429 | 
             
            - lib/linked_rails/translate.rb
         | 
| 423 430 | 
             
            - lib/linked_rails/types/iri_type.rb
         |