Class: JSONAPI::BasicResource
- Inherits:
-
Object
- Object
- JSONAPI::BasicResource
- Includes:
- Callbacks
- Defined in:
- lib/jsonapi/basic_resource.rb
Direct Known Subclasses
Class Attribute Summary collapse
- ._allowed_filters ⇒ Object
- ._allowed_sort ⇒ Object
-
._attributes ⇒ Object
Returns the value of attribute _attributes.
-
._model_hints ⇒ Object
Returns the value of attribute _model_hints.
- ._paginator ⇒ Object
-
._relationships ⇒ Object
Returns the value of attribute _relationships.
-
._routed ⇒ Object
Returns the value of attribute _routed.
-
._type ⇒ Object
Returns the value of attribute _type.
-
._warned_missing_route ⇒ Object
Returns the value of attribute _warned_missing_route.
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Class Method Summary collapse
- ._abstract ⇒ Object
- ._add_relationship(klass, *attrs) ⇒ Object
- ._allowed_filter?(filter) ⇒ Boolean
- ._as_parent_key ⇒ Object
- ._attribute_delegated_name(attr) ⇒ Object
-
._attribute_options(attr) ⇒ Object
quasi private class methods.
- ._cache_field ⇒ Object
- ._caching ⇒ Object
- ._clear_cached_attribute_options ⇒ Object
- ._clear_fields_cache ⇒ Object
- ._default_primary_key ⇒ Object
- ._exclude_links ⇒ Object
- ._has_attribute?(attr) ⇒ Boolean
- ._has_sort?(sorting) ⇒ Boolean
- ._immutable ⇒ Object
- ._model_class ⇒ Object
- ._model_name ⇒ Object
- ._polymorphic ⇒ Object
- ._polymorphic_name ⇒ Object
- ._polymorphic_resource_klasses ⇒ Object
- ._polymorphic_types ⇒ Object
- ._primary_key ⇒ Object
- ._relationship(type) ⇒ Object
- ._resource_name_from_type(type) ⇒ Object
- ._singleton_options ⇒ Object
- ._table_name ⇒ Object
- ._updatable_attributes ⇒ Object
- ._updatable_relationships ⇒ Object
- .abstract(val = true) ⇒ Object
- .attribute(attribute_name, options = {}) ⇒ Object
- .attribute_caching_context(_context) ⇒ Object
- .attribute_to_model_field(attribute) ⇒ Object
-
.attributes(*attrs) ⇒ Object
Methods used in defining a resource class.
- .belongs_to(*attrs) ⇒ Object
- .cache_field(field) ⇒ Object
- .caching(val = true) ⇒ Object
- .caching? ⇒ Boolean
- .call_method_or_proc(strategy, *args) ⇒ Object
- .cast_to_attribute_type(value, type) ⇒ Object
- .construct_order_options(sort_params) ⇒ Object
-
.creatable_fields(_context = nil) ⇒ Object
Override in your resource to filter the creatable keys.
- .create(context) ⇒ Object
- .create_model ⇒ Object
- .default_attribute_options ⇒ Object
- .default_sort ⇒ Object
- .define_foreign_key_setter(relationship) ⇒ Object
- .define_on_resource(method_name, &block) ⇒ Object
-
.define_relationship_methods(relationship_name, relationship_klass, options) ⇒ Object
ResourceBuilder methods.
- .exclude_link?(link) ⇒ Boolean
- .exclude_links(exclude) ⇒ Object
- .fields ⇒ Object
- .filter(attr, *args) ⇒ Object
- .filters(*attrs) ⇒ Object
- .has_many(*attrs) ⇒ Object
- .has_one(*attrs) ⇒ Object
-
.hash_cache_field(value) ⇒ Object
Generate a hashcode from the value to be used as part of the cache lookup.
- .immutable(val = true) ⇒ Object
- .inherited(subclass) ⇒ Object
- .is_filter_relationship?(filter) ⇒ Boolean
- .key_type(key_type) ⇒ Object
- .model_hint(model: _model_name, resource: _type) ⇒ Object
-
.model_name(model, options = {}) ⇒ Object
“‘ CarResource._model_class #=> Vehicle # it should be Car “` so in order to invoke the right class from subclasses, we should call this method to override it.
- .module_path ⇒ Object
- .mutable? ⇒ Boolean
- .paginator(paginator) ⇒ Object
- .parse_exclude_links(exclude) ⇒ Object
- .polymorphic(polymorphic = true) ⇒ Object
- .primary_key(key) ⇒ Object
- .rebuild_relationships(relationships) ⇒ Object
- .register_relationship(name, relationship_object) ⇒ Object
- .relationship(*attrs) ⇒ Object
- .resource_for(model_record, context) ⇒ Object
- .resource_key_type ⇒ Object
- .resource_klass_for(type) ⇒ Object
- .resource_klass_for_model(model) ⇒ Object
- .resource_type_for(model) ⇒ Object
- .resources_for(records, context) ⇒ Object
- .root? ⇒ Boolean
- .root_resource ⇒ Object
- .routing_options(options) ⇒ Object
- .routing_resource_options ⇒ Object
- .singleton(*attrs) ⇒ Object
- .singleton? ⇒ Boolean
-
.singleton_key(context) ⇒ Object
override to all resolution of masked ids to actual ids.
- .sort(sorting, options = {}) ⇒ Object
- .sortable_field?(key, context = nil) ⇒ Boolean
-
.sortable_fields(_context = nil) ⇒ Object
Override in your resource to filter the sortable keys.
- .sorts(*args) ⇒ Object
-
.updatable_fields(_context = nil) ⇒ Object
Override in your resource to filter the updatable keys.
-
.verify_custom_filter(filter, value, _context = nil) ⇒ Object
Either add a custom :verify lambda or override verify_custom_filter to allow for custom filters.
- .verify_filter(filter, raw, context = nil) ⇒ Object
- .verify_filters(filters, context = nil) ⇒ Object
- .verify_key(key, context = nil) ⇒ Object
-
.verify_keys(keys, context = nil) ⇒ Object
override to allow for key processing and checking.
-
.verify_relationship_filter(filter, raw, _context = nil) ⇒ Object
Either add a custom :verify lambda or override verify_relationship_filter to allow for custom relationship logic, such as uuids, multiple keys or permission checks on keys.
Instance Method Summary collapse
- #_model ⇒ Object
- #cache_id ⇒ Object
- #change(callback) ⇒ Object
- #create_to_many_links(relationship_type, relationship_key_values, options = {}) ⇒ Object
-
#custom_links(_options) ⇒ Object
Override this to return custom links must return a hash, which will be merged with the default { self: ‘self-url’ } links hash links keys will be not be formatted with the key formatter for the serializer by default.
-
#fetchable_fields ⇒ Object
Override this on a resource instance to override the fetchable keys.
- #id ⇒ Object
- #identity ⇒ Object
-
#initialize(model, context) ⇒ BasicResource
constructor
A new instance of BasicResource.
- #is_new? ⇒ Boolean
-
#meta(_options) ⇒ Object
Override this to return resource level meta data must return a hash, and if the hash is empty the meta section will not be serialized with the resource meta keys will be not be formatted with the key formatter for the serializer by default.
- #model_error_messages ⇒ Object
- #remove ⇒ Object
- #remove_to_many_link(relationship_type, key, options = {}) ⇒ Object
- #remove_to_one_link(relationship_type, options = {}) ⇒ Object
- #replace_fields(field_data) ⇒ Object
- #replace_polymorphic_to_one_link(relationship_type, relationship_key_value, relationship_key_type, options = {}) ⇒ Object
- #replace_to_many_links(relationship_type, relationship_key_values, options = {}) ⇒ Object
- #replace_to_one_link(relationship_type, relationship_key_value, options = {}) ⇒ Object
-
#validation_error_metadata ⇒ Object
Add metadata to validation error objects.
Methods included from Callbacks
Constructor Details
#initialize(model, context) ⇒ BasicResource
Returns a new instance of BasicResource.
27 28 29 30 31 32 33 |
# File 'lib/jsonapi/basic_resource.rb', line 27 def initialize(model, context) @model = model @context = context @reload_needed = false @changing = false @save_needed = false end |
Class Attribute Details
._allowed_filters ⇒ Object
900 901 902 |
# File 'lib/jsonapi/basic_resource.rb', line 900 def _allowed_filters defined?(@_allowed_filters) ? @_allowed_filters : { id: {} } end |
._allowed_sort ⇒ Object
904 905 906 |
# File 'lib/jsonapi/basic_resource.rb', line 904 def _allowed_sort @_allowed_sort ||= {} end |
._attributes ⇒ Object
Returns the value of attribute _attributes.
505 506 507 |
# File 'lib/jsonapi/basic_resource.rb', line 505 def _attributes @_attributes end |
._model_hints ⇒ Object
Returns the value of attribute _model_hints.
505 506 507 |
# File 'lib/jsonapi/basic_resource.rb', line 505 def _model_hints @_model_hints end |
._paginator ⇒ Object
908 909 910 |
# File 'lib/jsonapi/basic_resource.rb', line 908 def _paginator @_paginator || JSONAPI.configuration.default_paginator end |
._relationships ⇒ Object
Returns the value of attribute _relationships.
505 506 507 |
# File 'lib/jsonapi/basic_resource.rb', line 505 def _relationships @_relationships end |
._routed ⇒ Object
Returns the value of attribute _routed.
505 506 507 |
# File 'lib/jsonapi/basic_resource.rb', line 505 def _routed @_routed end |
._type ⇒ Object
Returns the value of attribute _type.
505 506 507 |
# File 'lib/jsonapi/basic_resource.rb', line 505 def _type @_type end |
._warned_missing_route ⇒ Object
Returns the value of attribute _warned_missing_route.
505 506 507 |
# File 'lib/jsonapi/basic_resource.rb', line 505 def _warned_missing_route @_warned_missing_route end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
12 13 14 |
# File 'lib/jsonapi/basic_resource.rb', line 12 def context @context end |
Class Method Details
._abstract ⇒ Object
958 959 960 |
# File 'lib/jsonapi/basic_resource.rb', line 958 def _abstract @abstract end |
._add_relationship(klass, *attrs) ⇒ Object
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 |
# File 'lib/jsonapi/basic_resource.rb', line 1071 def _add_relationship(klass, *attrs) _clear_fields_cache = attrs. [:parent_resource] = self attrs.each do |name| relationship_name = name.to_sym check_reserved_relationship_name(relationship_name) check_duplicate_relationship_name(relationship_name) define_relationship_methods(relationship_name.to_sym, klass, ) end end |
._allowed_filter?(filter) ⇒ Boolean
1040 1041 1042 |
# File 'lib/jsonapi/basic_resource.rb', line 1040 def _allowed_filter?(filter) !_allowed_filters[filter].nil? end |
._as_parent_key ⇒ Object
896 897 898 |
# File 'lib/jsonapi/basic_resource.rb', line 896 def _as_parent_key @_as_parent_key ||= "#{_type.to_s.singularize}_id" end |
._attribute_delegated_name(attr) ⇒ Object
838 839 840 |
# File 'lib/jsonapi/basic_resource.rb', line 838 def _attribute_delegated_name(attr) @_attributes.fetch(attr.to_sym, {}).fetch(:delegate, attr) end |
._attribute_options(attr) ⇒ Object
quasi private class methods
834 835 836 |
# File 'lib/jsonapi/basic_resource.rb', line 834 def (attr) @_cached_attribute_options[attr] ||= .merge(@_attributes[attr]) end |
._cache_field ⇒ Object
888 889 890 |
# File 'lib/jsonapi/basic_resource.rb', line 888 def _cache_field @_cache_field || JSONAPI.configuration.default_resource_cache_field end |
._caching ⇒ Object
1003 1004 1005 |
# File 'lib/jsonapi/basic_resource.rb', line 1003 def _caching @caching end |
._clear_cached_attribute_options ⇒ Object
1118 1119 1120 |
# File 'lib/jsonapi/basic_resource.rb', line 1118 def @_cached_attribute_options = {} end |
._clear_fields_cache ⇒ Object
1122 1123 1124 |
# File 'lib/jsonapi/basic_resource.rb', line 1122 def _clear_fields_cache @_fields_cache = nil end |
._default_primary_key ⇒ Object
884 885 886 |
# File 'lib/jsonapi/basic_resource.rb', line 884 def _default_primary_key @_default_primary_key ||=_model_class.respond_to?(:primary_key) ? _model_class.primary_key : :id end |
._exclude_links ⇒ Object
991 992 993 |
# File 'lib/jsonapi/basic_resource.rb', line 991 def _exclude_links @_exclude_links ||= parse_exclude_links(JSONAPI.configuration.default_exclude_links) end |
._has_attribute?(attr) ⇒ Boolean
842 843 844 |
# File 'lib/jsonapi/basic_resource.rb', line 842 def _has_attribute?(attr) @_attributes.keys.include?(attr.to_sym) end |
._has_sort?(sorting) ⇒ Boolean
1044 1045 1046 |
# File 'lib/jsonapi/basic_resource.rb', line 1044 def _has_sort?(sorting) !_allowed_sort[sorting.to_sym].nil? end |
._immutable ⇒ Object
966 967 968 |
# File 'lib/jsonapi/basic_resource.rb', line 966 def _immutable @immutable end |
._model_class ⇒ Object
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 |
# File 'lib/jsonapi/basic_resource.rb', line 1024 def _model_class return nil if _abstract return @model_class if @model_class model_name = _model_name return nil if model_name.to_s.blank? @model_class = model_name.to_s.safe_constantize if @model_class.nil? warn "[MODEL NOT FOUND] Model could not be found for #{self.name}. If this is a base Resource declare it as abstract." end @model_class end |
._model_name ⇒ Object
860 861 862 863 864 865 866 867 868 869 870 |
# File 'lib/jsonapi/basic_resource.rb', line 860 def _model_name if _abstract '' else return @_model_name.to_s if defined?(@_model_name) class_name = self.name return '' if class_name.nil? @_model_name = class_name.demodulize.sub(/Resource$/, '') @_model_name.to_s end end |
._polymorphic ⇒ Object
916 917 918 |
# File 'lib/jsonapi/basic_resource.rb', line 916 def _polymorphic @_polymorphic end |
._polymorphic_name ⇒ Object
872 873 874 875 876 877 878 |
# File 'lib/jsonapi/basic_resource.rb', line 872 def _polymorphic_name if !_polymorphic '' else @_polymorphic_name ||= _model_name.to_s.underscore end end |
._polymorphic_resource_klasses ⇒ Object
938 939 940 941 942 |
# File 'lib/jsonapi/basic_resource.rb', line 938 def _polymorphic_resource_klasses @_polymorphic_resource_klasses ||= _polymorphic_types.collect do |type| resource_klass_for(type) end end |
._polymorphic_types ⇒ Object
924 925 926 927 928 929 930 931 932 933 934 935 936 |
# File 'lib/jsonapi/basic_resource.rb', line 924 def _polymorphic_types @poly_hash ||= {}.tap do |hash| ObjectSpace.each_object do |klass| next unless Module === klass if klass < ActiveRecord::Base klass.reflect_on_all_associations(:has_many).select{|r| r.[:as] }.each do |reflection| (hash[reflection.[:as]] ||= []) << klass.name.underscore end end end end @poly_hash[_polymorphic_name.to_sym] end |
._primary_key ⇒ Object
880 881 882 |
# File 'lib/jsonapi/basic_resource.rb', line 880 def _primary_key @_primary_key ||= _default_primary_key end |
._relationship(type) ⇒ Object
854 855 856 857 858 |
# File 'lib/jsonapi/basic_resource.rb', line 854 def _relationship(type) return nil unless type type = type.to_sym @_relationships[type] end |
._resource_name_from_type(type) ⇒ Object
492 493 494 |
# File 'lib/jsonapi/basic_resource.rb', line 492 def _resource_name_from_type(type) "#{type.to_s.underscore.singularize}_resource".camelize end |
._singleton_options ⇒ Object
649 650 651 |
# File 'lib/jsonapi/basic_resource.rb', line 649 def @_singleton_options ||= {} end |
._table_name ⇒ Object
892 893 894 |
# File 'lib/jsonapi/basic_resource.rb', line 892 def _table_name @_table_name ||= _model_class.respond_to?(:table_name) ? _model_class.table_name : _model_name.tableize end |
._updatable_attributes ⇒ Object
846 847 848 |
# File 'lib/jsonapi/basic_resource.rb', line 846 def _updatable_attributes _attributes.map { |key, | key unless [:readonly] }.compact end |
._updatable_relationships ⇒ Object
850 851 852 |
# File 'lib/jsonapi/basic_resource.rb', line 850 def _updatable_relationships @_relationships.map { |key, relationship| key unless relationship.readonly? }.compact end |
.abstract(val = true) ⇒ Object
954 955 956 |
# File 'lib/jsonapi/basic_resource.rb', line 954 def abstract(val = true) @abstract = val end |
.attribute(attribute_name, options = {}) ⇒ Object
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 |
# File 'lib/jsonapi/basic_resource.rb', line 532 def attribute(attribute_name, = {}) _clear_fields_cache attr = attribute_name.to_sym check_reserved_attribute_name(attr) if (attr == :id) && ([:format].nil?) ActiveSupport::Deprecation.warn('Id without format is no longer supported. Please remove ids from attributes, or specify a format.') end check_duplicate_attribute_name(attr) if [:format].nil? @_attributes ||= {} @_attributes[attr] = define_method attr do @model.public_send([:delegate] ? [:delegate].to_sym : attr) end unless method_defined?(attr) define_method "#{attr}=" do |value| @model.public_send("#{[:delegate] ? [:delegate].to_sym : attr}=", value) end unless method_defined?("#{attr}=") if .fetch(:sortable, true) && !_has_sort?(attr) sort attr end end |
.attribute_caching_context(_context) ⇒ Object
1015 1016 1017 |
# File 'lib/jsonapi/basic_resource.rb', line 1015 def attribute_caching_context(_context) nil end |
.attribute_to_model_field(attribute) ⇒ Object
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 |
# File 'lib/jsonapi/basic_resource.rb', line 561 def attribute_to_model_field(attribute) field_name = if attribute == :_cache_field _cache_field else # Note: this will allow the returning of model attributes without a corresponding # resource attribute, for example a belongs_to id such as `author_id` or bypassing # the delegate. attr = @_attributes[attribute] attr && attr[:delegate] ? attr[:delegate].to_sym : attribute end if Rails::VERSION::MAJOR >= 5 attribute_type = _model_class.attribute_types[field_name.to_s] else attribute_type = _model_class.column_types[field_name.to_s] end { name: field_name, type: attribute_type} end |
.attributes(*attrs) ⇒ Object
Methods used in defining a resource class
525 526 527 528 529 530 |
# File 'lib/jsonapi/basic_resource.rb', line 525 def attributes(*attrs) = attrs..dup attrs.each do |attr| attribute(attr, ) end end |
.belongs_to(*attrs) ⇒ Object
610 611 612 613 614 615 616 617 |
# File 'lib/jsonapi/basic_resource.rb', line 610 def belongs_to(*attrs) ActiveSupport::Deprecation.warn "In #{name} you exposed a `has_one` relationship "\ " using the `belongs_to` class method. We think `has_one`" \ " is more appropriate. If you know what you're doing," \ " and don't want to see this warning again, override the" \ " `belongs_to` class method on your resource." _add_relationship(Relationship::ToOne, *attrs) end |
.cache_field(field) ⇒ Object
678 679 680 |
# File 'lib/jsonapi/basic_resource.rb', line 678 def cache_field(field) @_cache_field = field.to_sym end |
.caching(val = true) ⇒ Object
999 1000 1001 |
# File 'lib/jsonapi/basic_resource.rb', line 999 def caching(val = true) @caching = val end |
.caching? ⇒ Boolean
1007 1008 1009 1010 1011 1012 1013 |
# File 'lib/jsonapi/basic_resource.rb', line 1007 def caching? if @caching.nil? !JSONAPI.configuration.resource_cache.nil? && JSONAPI.configuration.default_caching else @caching && !JSONAPI.configuration.resource_cache.nil? end end |
.call_method_or_proc(strategy, *args) ⇒ Object
753 754 755 756 757 758 759 |
# File 'lib/jsonapi/basic_resource.rb', line 753 def call_method_or_proc(strategy, *args) if strategy.is_a?(Symbol) || strategy.is_a?(String) send(strategy, *args) else strategy.call(*args) end end |
.cast_to_attribute_type(value, type) ⇒ Object
579 580 581 582 583 584 585 |
# File 'lib/jsonapi/basic_resource.rb', line 579 def cast_to_attribute_type(value, type) if Rails::VERSION::MAJOR >= 5 return type.cast(value) else return type.type_cast_from_database(value) end end |
.construct_order_options(sort_params) ⇒ Object
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 |
# File 'lib/jsonapi/basic_resource.rb', line 1060 def (sort_params) sort_params = default_sort if sort_params.blank? return {} unless sort_params sort_params.each_with_object({}) do |sort, order_hash| field = sort[:field].to_s == 'id' ? _primary_key : sort[:field].to_s order_hash[field] = sort[:direction] end end |
.creatable_fields(_context = nil) ⇒ Object
Override in your resource to filter the creatable keys
688 689 690 |
# File 'lib/jsonapi/basic_resource.rb', line 688 def creatable_fields(_context = nil) _updatable_relationships | _updatable_attributes end |
.create(context) ⇒ Object
508 509 510 |
# File 'lib/jsonapi/basic_resource.rb', line 508 def create(context) new(create_model, context) end |
.create_model ⇒ Object
512 513 514 |
# File 'lib/jsonapi/basic_resource.rb', line 512 def create_model _model_class.new end |
.default_attribute_options ⇒ Object
587 588 589 |
# File 'lib/jsonapi/basic_resource.rb', line 587 def { format: :default } end |
.default_sort ⇒ Object
1056 1057 1058 |
# File 'lib/jsonapi/basic_resource.rb', line 1056 def default_sort [{field: 'id', direction: :asc}] end |
.define_foreign_key_setter(relationship) ⇒ Object
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 |
# File 'lib/jsonapi/basic_resource.rb', line 1096 def define_foreign_key_setter(relationship) if relationship.polymorphic? define_on_resource "#{relationship.foreign_key}=" do |v| _model.method("#{relationship.foreign_key}=").call(v[:id]) _model.public_send("#{relationship.polymorphic_type}=", v[:type]) end else define_on_resource "#{relationship.foreign_key}=" do |value| _model.method("#{relationship.foreign_key}=").call(value) end end end |
.define_on_resource(method_name, &block) ⇒ Object
1109 1110 1111 1112 |
# File 'lib/jsonapi/basic_resource.rb', line 1109 def define_on_resource(method_name, &block) return if method_defined?(method_name) define_method(method_name, block) end |
.define_relationship_methods(relationship_name, relationship_klass, options) ⇒ Object
ResourceBuilder methods
1087 1088 1089 1090 1091 1092 1093 1094 |
# File 'lib/jsonapi/basic_resource.rb', line 1087 def define_relationship_methods(relationship_name, relationship_klass, ) relationship = register_relationship( relationship_name, relationship_klass.new(relationship_name, ) ) define_foreign_key_setter(relationship) end |
.exclude_link?(link) ⇒ Boolean
995 996 997 |
# File 'lib/jsonapi/basic_resource.rb', line 995 def exclude_link?(link) _exclude_links.include?(link.to_sym) end |
.exclude_links(exclude) ⇒ Object
987 988 989 |
# File 'lib/jsonapi/basic_resource.rb', line 987 def exclude_links(exclude) @_exclude_links = parse_exclude_links(exclude) end |
.fields ⇒ Object
701 702 703 |
# File 'lib/jsonapi/basic_resource.rb', line 701 def fields @_fields_cache ||= _relationships.keys | _attributes.keys end |
.filter(attr, *args) ⇒ Object
661 662 663 |
# File 'lib/jsonapi/basic_resource.rb', line 661 def filter(attr, *args) @_allowed_filters[attr.to_sym] = args. end |
.filters(*attrs) ⇒ Object
657 658 659 |
# File 'lib/jsonapi/basic_resource.rb', line 657 def filters(*attrs) @_allowed_filters.merge!(attrs.inject({}) { |h, attr| h[attr] = {}; h }) end |
.has_many(*attrs) ⇒ Object
619 620 621 |
# File 'lib/jsonapi/basic_resource.rb', line 619 def has_many(*attrs) _add_relationship(Relationship::ToMany, *attrs) end |
.has_one(*attrs) ⇒ Object
606 607 608 |
# File 'lib/jsonapi/basic_resource.rb', line 606 def has_one(*attrs) _add_relationship(Relationship::ToOne, *attrs) end |
.hash_cache_field(value) ⇒ Object
Generate a hashcode from the value to be used as part of the cache lookup
1020 1021 1022 |
# File 'lib/jsonapi/basic_resource.rb', line 1020 def hash_cache_field(value) value.hash end |
.immutable(val = true) ⇒ Object
962 963 964 |
# File 'lib/jsonapi/basic_resource.rb', line 962 def immutable(val = true) @immutable = val end |
.inherited(subclass) ⇒ Object
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/jsonapi/basic_resource.rb', line 421 def inherited(subclass) subclass.abstract(false) subclass.immutable(false) subclass.caching(_caching) subclass.cache_field(_cache_field) if @_cache_field subclass.singleton(singleton?, (.dup || {})) subclass.exclude_links(_exclude_links) subclass.paginator(@_paginator) subclass._attributes = (_attributes || {}).dup subclass.polymorphic(false) subclass.key_type(@_resource_key_type) subclass._model_hints = (_model_hints || {}).dup unless _model_name.empty? || _immutable subclass.model_name(_model_name, add_model_hint: (_model_hints && !_model_hints[_model_name].nil?) == true) end subclass.rebuild_relationships(_relationships || {}) subclass._allowed_filters = (_allowed_filters || Set.new).dup subclass._allowed_sort = _allowed_sort.dup type = subclass.name.demodulize.sub(/Resource$/, '').underscore subclass._type = type.pluralize.to_sym unless subclass._attributes[:id] subclass.attribute :id, format: :id, readonly: true end check_reserved_resource_name(subclass._type, subclass.name) subclass._routed = false subclass._warned_missing_route = false subclass. subclass._clear_fields_cache end |
.is_filter_relationship?(filter) ⇒ Boolean
725 726 727 |
# File 'lib/jsonapi/basic_resource.rb', line 725 def is_filter_relationship?(filter) filter == _type || _relationships.include?(filter) end |
.key_type(key_type) ⇒ Object
761 762 763 |
# File 'lib/jsonapi/basic_resource.rb', line 761 def key_type(key_type) @_resource_key_type = key_type end |
.model_hint(model: _model_name, resource: _type) ⇒ Object
638 639 640 641 642 |
# File 'lib/jsonapi/basic_resource.rb', line 638 def model_hint(model: _model_name, resource: _type) resource_type = ((resource.is_a?(Class)) && (resource < JSONAPI::Resource)) ? resource._type : resource.to_s _model_hints[model.to_s.gsub('::', '/').underscore] = resource_type.to_s end |
.model_name(model, options = {}) ⇒ Object
“‘ CarResource._model_class #=> Vehicle # it should be Car “` so in order to invoke the right class from subclasses, we should call this method to override it.
629 630 631 632 633 634 635 636 |
# File 'lib/jsonapi/basic_resource.rb', line 629 def model_name(model, = {}) @model_class = nil @_model_name = model.to_sym model_hint(model: @_model_name, resource: self) unless [:add_model_hint] == false rebuild_relationships(_relationships) end |
.module_path ⇒ Object
1048 1049 1050 1051 1052 1053 1054 |
# File 'lib/jsonapi/basic_resource.rb', line 1048 def module_path if name == 'JSONAPI::Resource' '' else name =~ /::[^:]+\Z/ ? ($`.freeze.gsub('::', '/') + '/').underscore : '' end end |
.mutable? ⇒ Boolean
970 971 972 |
# File 'lib/jsonapi/basic_resource.rb', line 970 def mutable? !@immutable end |
.paginator(paginator) ⇒ Object
912 913 914 |
# File 'lib/jsonapi/basic_resource.rb', line 912 def paginator(paginator) @_paginator = paginator end |
.parse_exclude_links(exclude) ⇒ Object
974 975 976 977 978 979 980 981 982 983 984 985 |
# File 'lib/jsonapi/basic_resource.rb', line 974 def parse_exclude_links(exclude) case exclude when :default, "default" [:self] when :none, "none" [] when Array exclude.collect {|link| link.to_sym} else fail "Invalid exclude_links" end end |
.polymorphic(polymorphic = true) ⇒ Object
920 921 922 |
# File 'lib/jsonapi/basic_resource.rb', line 920 def polymorphic(polymorphic = true) @_polymorphic = polymorphic end |
.primary_key(key) ⇒ Object
674 675 676 |
# File 'lib/jsonapi/basic_resource.rb', line 674 def primary_key(key) @_primary_key = key.to_sym end |
.rebuild_relationships(relationships) ⇒ Object
461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
# File 'lib/jsonapi/basic_resource.rb', line 461 def rebuild_relationships(relationships) original_relationships = relationships.deep_dup @_relationships = {} if original_relationships.is_a?(Hash) original_relationships.each_value do |relationship| = relationship..dup [:parent_resource] = self [:inverse_relationship] = relationship.inverse_relationship _add_relationship(relationship.class, relationship.name, ) end end end |
.register_relationship(name, relationship_object) ⇒ Object
1114 1115 1116 |
# File 'lib/jsonapi/basic_resource.rb', line 1114 def register_relationship(name, relationship_object) @_relationships[name] = relationship_object end |
.relationship(*attrs) ⇒ Object
591 592 593 594 595 596 597 598 599 600 601 602 603 604 |
# File 'lib/jsonapi/basic_resource.rb', line 591 def relationship(*attrs) = attrs. klass = case [:to] when :one Relationship::ToOne when :many Relationship::ToMany else #:nocov:# fail ArgumentError.new('to: must be either :one or :many') #:nocov:# end _add_relationship(klass, *attrs, .except(:to)) end |
.resource_for(model_record, context) ⇒ Object
711 712 713 714 |
# File 'lib/jsonapi/basic_resource.rb', line 711 def resource_for(model_record, context) resource_klass = self.resource_klass_for_model(model_record) resource_klass.new(model_record, context) end |
.resource_key_type ⇒ Object
765 766 767 |
# File 'lib/jsonapi/basic_resource.rb', line 765 def resource_key_type @_resource_key_type || JSONAPI.configuration.resource_key_type end |
.resource_klass_for(type) ⇒ Object
476 477 478 479 480 481 482 483 484 485 486 |
# File 'lib/jsonapi/basic_resource.rb', line 476 def resource_klass_for(type) type = type.underscore type_with_module = type.start_with?(module_path) ? type : module_path + type resource_name = _resource_name_from_type(type_with_module) resource = resource_name.safe_constantize if resource_name if resource.nil? fail NameError, "JSONAPI: Could not find resource '#{type}'. (Class #{resource_name} not found)" end resource end |
.resource_klass_for_model(model) ⇒ Object
488 489 490 |
# File 'lib/jsonapi/basic_resource.rb', line 488 def resource_klass_for_model(model) resource_klass_for(resource_type_for(model)) end |
.resource_type_for(model) ⇒ Object
496 497 498 499 500 501 502 503 |
# File 'lib/jsonapi/basic_resource.rb', line 496 def resource_type_for(model) model_name = model.class.to_s.underscore if _model_hints[model_name] _model_hints[model_name] else model_name.rpartition('/').last end end |
.resources_for(records, context) ⇒ Object
705 706 707 708 709 |
# File 'lib/jsonapi/basic_resource.rb', line 705 def resources_for(records, context) records.collect do |record| resource_for(record, context) end end |
.root? ⇒ Boolean
950 951 952 |
# File 'lib/jsonapi/basic_resource.rb', line 950 def root? @root end |
.root_resource ⇒ Object
944 945 946 947 948 |
# File 'lib/jsonapi/basic_resource.rb', line 944 def root_resource @abstract = true @immutable = true @root = true end |
.routing_options(options) ⇒ Object
516 517 518 |
# File 'lib/jsonapi/basic_resource.rb', line 516 def () @_routing_resource_options = end |
.routing_resource_options ⇒ Object
520 521 522 |
# File 'lib/jsonapi/basic_resource.rb', line 520 def @_routing_resource_options ||= {} end |
.singleton(*attrs) ⇒ Object
644 645 646 647 |
# File 'lib/jsonapi/basic_resource.rb', line 644 def singleton(*attrs) @_singleton = (!!attrs[0] == attrs[0]) ? attrs[0] : true @_singleton_options = attrs. end |
.singleton? ⇒ Boolean
653 654 655 |
# File 'lib/jsonapi/basic_resource.rb', line 653 def singleton? @_singleton ||= false end |
.singleton_key(context) ⇒ Object
override to all resolution of masked ids to actual ids. Because singleton routes do not specify the id this will be needed to allow lookup of singleton resources. Alternately singleton resources can override ‘verify_key`
772 773 774 775 776 777 778 779 780 781 782 783 784 785 |
# File 'lib/jsonapi/basic_resource.rb', line 772 def singleton_key(context) if @_singleton_options && @_singleton_options[:singleton_key] strategy = @_singleton_options[:singleton_key] case strategy when Proc key = strategy.call(context) when Symbol, String key = send(strategy, context) else raise "singleton_key must be a proc or function name" end end key end |
.sort(sorting, options = {}) ⇒ Object
665 666 667 |
# File 'lib/jsonapi/basic_resource.rb', line 665 def sort(sorting, = {}) self._allowed_sort[sorting.to_sym] = end |
.sortable_field?(key, context = nil) ⇒ Boolean
697 698 699 |
# File 'lib/jsonapi/basic_resource.rb', line 697 def sortable_field?(key, context = nil) sortable_fields(context).include? key.to_sym end |
.sortable_fields(_context = nil) ⇒ Object
Override in your resource to filter the sortable keys
693 694 695 |
# File 'lib/jsonapi/basic_resource.rb', line 693 def sortable_fields(_context = nil) _allowed_sort.keys end |
.sorts(*args) ⇒ Object
669 670 671 672 |
# File 'lib/jsonapi/basic_resource.rb', line 669 def sorts(*args) = args. _allowed_sort.merge!(args.inject({}) { |h, sorting| h[sorting.to_sym] = .dup; h }) end |
.updatable_fields(_context = nil) ⇒ Object
Override in your resource to filter the updatable keys
683 684 685 |
# File 'lib/jsonapi/basic_resource.rb', line 683 def updatable_fields(_context = nil) _updatable_relationships | _updatable_attributes - [:id] end |
.verify_custom_filter(filter, value, _context = nil) ⇒ Object
Either add a custom :verify lambda or override verify_custom_filter to allow for custom filters
823 824 825 |
# File 'lib/jsonapi/basic_resource.rb', line 823 def verify_custom_filter(filter, value, _context = nil) [filter, value] end |
.verify_filter(filter, raw, context = nil) ⇒ Object
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 |
# File 'lib/jsonapi/basic_resource.rb', line 729 def verify_filter(filter, raw, context = nil) filter_values = [] if raw.present? begin filter_values += raw.is_a?(String) ? CSV.parse_line(raw) : [raw] rescue CSV::MalformedCSVError filter_values << raw end end strategy = _allowed_filters.fetch(filter, Hash.new)[:verify] if strategy values = call_method_or_proc(strategy, filter_values, context) [filter, values] else if is_filter_relationship?(filter) verify_relationship_filter(filter, filter_values, context) else verify_custom_filter(filter, filter_values, context) end end end |
.verify_filters(filters, context = nil) ⇒ Object
716 717 718 719 720 721 722 723 |
# File 'lib/jsonapi/basic_resource.rb', line 716 def verify_filters(filters, context = nil) verified_filters = {} filters.each do |filter, raw_value| verified_filter = verify_filter(filter, raw_value, context) verified_filters[verified_filter[0]] = verified_filter[1] end verified_filters end |
.verify_key(key, context = nil) ⇒ Object
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 |
# File 'lib/jsonapi/basic_resource.rb', line 787 def verify_key(key, context = nil) key_type = resource_key_type case key_type when :integer return if key.nil? Integer(key) when :string return if key.nil? if key.to_s.include?(',') raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) else key end when :uuid return if key.nil? if key.to_s.match(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/) key else raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) end else key_type.call(key, context) end rescue raise JSONAPI::Exceptions::InvalidFieldValue.new(:id, key) end |
.verify_keys(keys, context = nil) ⇒ Object
override to allow for key processing and checking
816 817 818 819 820 |
# File 'lib/jsonapi/basic_resource.rb', line 816 def verify_keys(keys, context = nil) return keys.collect do |key| verify_key(key, context) end end |
.verify_relationship_filter(filter, raw, _context = nil) ⇒ Object
Either add a custom :verify lambda or override verify_relationship_filter to allow for custom relationship logic, such as uuids, multiple keys or permission checks on keys
829 830 831 |
# File 'lib/jsonapi/basic_resource.rb', line 829 def verify_relationship_filter(filter, raw, _context = nil) [filter, raw] end |
Instance Method Details
#_model ⇒ Object
35 36 37 |
# File 'lib/jsonapi/basic_resource.rb', line 35 def _model @model end |
#cache_id ⇒ Object
47 48 49 |
# File 'lib/jsonapi/basic_resource.rb', line 47 def cache_id [id, self.class.hash_cache_field(_model.public_send(self.class._cache_field))] end |
#change(callback) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/jsonapi/basic_resource.rb', line 55 def change(callback) completed = false if @changing run_callbacks callback do completed = (yield == :completed) end else run_callbacks is_new? ? :create : :update do @changing = true run_callbacks callback do completed = (yield == :completed) end completed = (save == :completed) if @save_needed || is_new? end end return completed ? :completed : :accepted end |
#create_to_many_links(relationship_type, relationship_key_values, options = {}) ⇒ Object
82 83 84 85 86 |
# File 'lib/jsonapi/basic_resource.rb', line 82 def create_to_many_links(relationship_type, relationship_key_values, = {}) change :create_to_many_link do _create_to_many_links(relationship_type, relationship_key_values, ) end end |
#custom_links(_options) ⇒ Object
Override this to return custom links must return a hash, which will be merged with the default { self: ‘self-url’ } links hash links keys will be not be formatted with the key formatter for the serializer by default. They can however use the serializer’s format_key and format_value methods if desired the _options hash will contain the serializer and the serialization_options
170 171 172 |
# File 'lib/jsonapi/basic_resource.rb', line 170 def custom_links() {} end |
#fetchable_fields ⇒ Object
Override this on a resource instance to override the fetchable keys
125 126 127 |
# File 'lib/jsonapi/basic_resource.rb', line 125 def fetchable_fields self.class.fields end |
#id ⇒ Object
39 40 41 |
# File 'lib/jsonapi/basic_resource.rb', line 39 def id _model.public_send(self.class._primary_key) end |
#identity ⇒ Object
43 44 45 |
# File 'lib/jsonapi/basic_resource.rb', line 43 def identity JSONAPI::ResourceIdentity.new(self.class, id) end |
#is_new? ⇒ Boolean
51 52 53 |
# File 'lib/jsonapi/basic_resource.rb', line 51 def is_new? id.nil? end |
#meta(_options) ⇒ Object
Override this to return resource level meta data must return a hash, and if the hash is empty the meta section will not be serialized with the resource meta keys will be not be formatted with the key formatter for the serializer by default. They can however use the serializer’s format_key and format_value methods if desired the _options hash will contain the serializer and the serialization_options
161 162 163 |
# File 'lib/jsonapi/basic_resource.rb', line 161 def () {} end |
#model_error_messages ⇒ Object
129 130 131 |
# File 'lib/jsonapi/basic_resource.rb', line 129 def _model.errors. end |
#remove ⇒ Object
76 77 78 79 80 |
# File 'lib/jsonapi/basic_resource.rb', line 76 def remove run_callbacks :remove do _remove end end |
#remove_to_many_link(relationship_type, key, options = {}) ⇒ Object
106 107 108 109 110 |
# File 'lib/jsonapi/basic_resource.rb', line 106 def remove_to_many_link(relationship_type, key, = {}) change :remove_to_many_link do _remove_to_many_link(relationship_type, key, ) end end |
#remove_to_one_link(relationship_type, options = {}) ⇒ Object
112 113 114 115 116 |
# File 'lib/jsonapi/basic_resource.rb', line 112 def remove_to_one_link(relationship_type, = {}) change :remove_to_one_link do _remove_to_one_link(relationship_type, ) end end |
#replace_fields(field_data) ⇒ Object
118 119 120 121 122 |
# File 'lib/jsonapi/basic_resource.rb', line 118 def replace_fields(field_data) change :replace_fields do _replace_fields(field_data) end end |
#replace_polymorphic_to_one_link(relationship_type, relationship_key_value, relationship_key_type, options = {}) ⇒ Object
100 101 102 103 104 |
# File 'lib/jsonapi/basic_resource.rb', line 100 def replace_polymorphic_to_one_link(relationship_type, relationship_key_value, relationship_key_type, = {}) change :replace_polymorphic_to_one_link do _replace_polymorphic_to_one_link(relationship_type, relationship_key_value, relationship_key_type, ) end end |
#replace_to_many_links(relationship_type, relationship_key_values, options = {}) ⇒ Object
88 89 90 91 92 |
# File 'lib/jsonapi/basic_resource.rb', line 88 def replace_to_many_links(relationship_type, relationship_key_values, = {}) change :replace_to_many_links do _replace_to_many_links(relationship_type, relationship_key_values, ) end end |
#replace_to_one_link(relationship_type, relationship_key_value, options = {}) ⇒ Object
94 95 96 97 98 |
# File 'lib/jsonapi/basic_resource.rb', line 94 def replace_to_one_link(relationship_type, relationship_key_value, = {}) change :replace_to_one_link do _replace_to_one_link(relationship_type, relationship_key_value, ) end end |
#validation_error_metadata ⇒ Object
Add metadata to validation error objects.
Suppose ‘model_error_messages` returned the following error messages hash:
{password: ["too_short", "format"]}
Then to add data to the validation error ‘validation_error_metadata` could return:
{
password: {
"too_short": {"minimum_length" => 6},
"format": {"requirement" => "must contain letters and numbers"}
}
}
The specified metadata is then be merged into the validation error object.
152 153 154 |
# File 'lib/jsonapi/basic_resource.rb', line 152 def {} end |