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_field_value ⇒ 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.
29 30 31 32 33 34 35 |
# File 'lib/jsonapi/basic_resource.rb', line 29 def initialize(model, context) @model = model @context = context @reload_needed = false @changing = false @save_needed = false end |
Class Attribute Details
._allowed_filters ⇒ Object
902 903 904 |
# File 'lib/jsonapi/basic_resource.rb', line 902 def _allowed_filters defined?(@_allowed_filters) ? @_allowed_filters : { id: {} } end |
._allowed_sort ⇒ Object
906 907 908 |
# File 'lib/jsonapi/basic_resource.rb', line 906 def _allowed_sort @_allowed_sort ||= {} end |
._attributes ⇒ Object
Returns the value of attribute _attributes.
514 515 516 |
# File 'lib/jsonapi/basic_resource.rb', line 514 def _attributes @_attributes end |
._model_hints ⇒ Object
Returns the value of attribute _model_hints.
514 515 516 |
# File 'lib/jsonapi/basic_resource.rb', line 514 def _model_hints @_model_hints end |
._paginator ⇒ Object
910 911 912 |
# File 'lib/jsonapi/basic_resource.rb', line 910 def _paginator @_paginator || JSONAPI.configuration.default_paginator end |
._relationships ⇒ Object
Returns the value of attribute _relationships.
514 515 516 |
# File 'lib/jsonapi/basic_resource.rb', line 514 def _relationships @_relationships end |
._routed ⇒ Object
Returns the value of attribute _routed.
514 515 516 |
# File 'lib/jsonapi/basic_resource.rb', line 514 def _routed @_routed end |
._type ⇒ Object
Returns the value of attribute _type.
514 515 516 |
# File 'lib/jsonapi/basic_resource.rb', line 514 def _type @_type end |
._warned_missing_route ⇒ Object
Returns the value of attribute _warned_missing_route.
514 515 516 |
# File 'lib/jsonapi/basic_resource.rb', line 514 def _warned_missing_route @_warned_missing_route end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
14 15 16 |
# File 'lib/jsonapi/basic_resource.rb', line 14 def context @context end |
Class Method Details
._abstract ⇒ Object
960 961 962 |
# File 'lib/jsonapi/basic_resource.rb', line 960 def _abstract @abstract end |
._add_relationship(klass, *attrs) ⇒ Object
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
# File 'lib/jsonapi/basic_resource.rb', line 1073 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
1042 1043 1044 |
# File 'lib/jsonapi/basic_resource.rb', line 1042 def _allowed_filter?(filter) !_allowed_filters[filter].nil? end |
._as_parent_key ⇒ Object
898 899 900 |
# File 'lib/jsonapi/basic_resource.rb', line 898 def _as_parent_key @_as_parent_key ||= "#{_type.to_s.singularize}_id" end |
._attribute_delegated_name(attr) ⇒ Object
840 841 842 |
# File 'lib/jsonapi/basic_resource.rb', line 840 def _attribute_delegated_name(attr) @_attributes.fetch(attr.to_sym, {}).fetch(:delegate, attr) end |
._attribute_options(attr) ⇒ Object
quasi private class methods
836 837 838 |
# File 'lib/jsonapi/basic_resource.rb', line 836 def (attr) @_cached_attribute_options[attr] ||= .merge(@_attributes[attr]) end |
._cache_field ⇒ Object
890 891 892 |
# File 'lib/jsonapi/basic_resource.rb', line 890 def _cache_field @_cache_field || JSONAPI.configuration.default_resource_cache_field end |
._caching ⇒ Object
1005 1006 1007 |
# File 'lib/jsonapi/basic_resource.rb', line 1005 def _caching @caching end |
._clear_cached_attribute_options ⇒ Object
1120 1121 1122 |
# File 'lib/jsonapi/basic_resource.rb', line 1120 def @_cached_attribute_options = {} end |
._clear_fields_cache ⇒ Object
1124 1125 1126 |
# File 'lib/jsonapi/basic_resource.rb', line 1124 def _clear_fields_cache @_fields_cache = nil end |
._default_primary_key ⇒ Object
886 887 888 |
# File 'lib/jsonapi/basic_resource.rb', line 886 def _default_primary_key @_default_primary_key ||=_model_class.respond_to?(:primary_key) ? _model_class.primary_key : :id end |
._exclude_links ⇒ Object
993 994 995 |
# File 'lib/jsonapi/basic_resource.rb', line 993 def _exclude_links @_exclude_links ||= parse_exclude_links(JSONAPI.configuration.default_exclude_links) end |
._has_attribute?(attr) ⇒ Boolean
844 845 846 |
# File 'lib/jsonapi/basic_resource.rb', line 844 def _has_attribute?(attr) @_attributes.keys.include?(attr.to_sym) end |
._has_sort?(sorting) ⇒ Boolean
1046 1047 1048 |
# File 'lib/jsonapi/basic_resource.rb', line 1046 def _has_sort?(sorting) !_allowed_sort[sorting.to_sym].nil? end |
._immutable ⇒ Object
968 969 970 |
# File 'lib/jsonapi/basic_resource.rb', line 968 def _immutable @immutable end |
._model_class ⇒ Object
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
# File 'lib/jsonapi/basic_resource.rb', line 1026 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
862 863 864 865 866 867 868 869 870 871 872 |
# File 'lib/jsonapi/basic_resource.rb', line 862 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
918 919 920 |
# File 'lib/jsonapi/basic_resource.rb', line 918 def _polymorphic @_polymorphic end |
._polymorphic_name ⇒ Object
874 875 876 877 878 879 880 |
# File 'lib/jsonapi/basic_resource.rb', line 874 def _polymorphic_name if !_polymorphic '' else @_polymorphic_name ||= _model_name.to_s.downcase end end |
._polymorphic_resource_klasses ⇒ Object
940 941 942 943 944 |
# File 'lib/jsonapi/basic_resource.rb', line 940 def _polymorphic_resource_klasses @_polymorphic_resource_klasses ||= _polymorphic_types.collect do |type| resource_klass_for(type) end end |
._polymorphic_types ⇒ Object
926 927 928 929 930 931 932 933 934 935 936 937 938 |
# File 'lib/jsonapi/basic_resource.rb', line 926 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.downcase end end end end @poly_hash[_polymorphic_name.to_sym] end |
._primary_key ⇒ Object
882 883 884 |
# File 'lib/jsonapi/basic_resource.rb', line 882 def _primary_key @_primary_key ||= _default_primary_key end |
._relationship(type) ⇒ Object
856 857 858 859 860 |
# File 'lib/jsonapi/basic_resource.rb', line 856 def _relationship(type) return nil unless type type = type.to_sym @_relationships[type] end |
._resource_name_from_type(type) ⇒ Object
501 502 503 |
# File 'lib/jsonapi/basic_resource.rb', line 501 def _resource_name_from_type(type) "#{type.to_s.underscore.singularize}_resource".camelize end |
._singleton_options ⇒ Object
651 652 653 |
# File 'lib/jsonapi/basic_resource.rb', line 651 def @_singleton_options ||= {} end |
._table_name ⇒ Object
894 895 896 |
# File 'lib/jsonapi/basic_resource.rb', line 894 def _table_name @_table_name ||= _model_class.respond_to?(:table_name) ? _model_class.table_name : _model_name.tableize end |
._updatable_attributes ⇒ Object
848 849 850 |
# File 'lib/jsonapi/basic_resource.rb', line 848 def _updatable_attributes _attributes.map { |key, | key unless [:readonly] }.compact end |
._updatable_relationships ⇒ Object
852 853 854 |
# File 'lib/jsonapi/basic_resource.rb', line 852 def _updatable_relationships @_relationships.map { |key, relationship| key unless relationship.readonly? }.compact end |
.abstract(val = true) ⇒ Object
956 957 958 |
# File 'lib/jsonapi/basic_resource.rb', line 956 def abstract(val = true) @abstract = val end |
.attribute(attribute_name, options = {}) ⇒ Object
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
# File 'lib/jsonapi/basic_resource.rb', line 541 def attribute(attribute_name, = {}) _clear_fields_cache attr = attribute_name.to_sym check_reserved_attribute_name(attr) if (attr == :id) && ([:format].nil?) JSONAPI::CompatibilityHelper.deprecation_warn('Id without format is deprecated. Please specify a format for the id attribute.') 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
1017 1018 1019 |
# File 'lib/jsonapi/basic_resource.rb', line 1017 def attribute_caching_context(_context) nil end |
.attribute_to_model_field(attribute) ⇒ Object
570 571 572 573 574 575 576 577 578 579 580 581 582 |
# File 'lib/jsonapi/basic_resource.rb', line 570 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 { name: field_name, type: _model_class.attribute_types[field_name.to_s]} end |
.attributes(*attrs) ⇒ Object
Methods used in defining a resource class
534 535 536 537 538 539 |
# File 'lib/jsonapi/basic_resource.rb', line 534 def attributes(*attrs) = attrs..dup attrs.each do |attr| attribute(attr, ) end end |
.belongs_to(*attrs) ⇒ Object
611 612 613 614 615 616 617 618 619 |
# File 'lib/jsonapi/basic_resource.rb', line 611 def belongs_to(*attrs) JSONAPI::CompatibilityHelper.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
680 681 682 |
# File 'lib/jsonapi/basic_resource.rb', line 680 def cache_field(field) @_cache_field = field.to_sym end |
.caching(val = true) ⇒ Object
1001 1002 1003 |
# File 'lib/jsonapi/basic_resource.rb', line 1001 def caching(val = true) @caching = val end |
.caching? ⇒ Boolean
1009 1010 1011 1012 1013 1014 1015 |
# File 'lib/jsonapi/basic_resource.rb', line 1009 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
755 756 757 758 759 760 761 |
# File 'lib/jsonapi/basic_resource.rb', line 755 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
584 585 586 |
# File 'lib/jsonapi/basic_resource.rb', line 584 def cast_to_attribute_type(value, type) type.cast(value) end |
.construct_order_options(sort_params) ⇒ Object
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 |
# File 'lib/jsonapi/basic_resource.rb', line 1062 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
690 691 692 |
# File 'lib/jsonapi/basic_resource.rb', line 690 def creatable_fields(_context = nil) _updatable_relationships | _updatable_attributes end |
.create(context) ⇒ Object
517 518 519 |
# File 'lib/jsonapi/basic_resource.rb', line 517 def create(context) new(create_model, context) end |
.create_model ⇒ Object
521 522 523 |
# File 'lib/jsonapi/basic_resource.rb', line 521 def create_model _model_class.new end |
.default_attribute_options ⇒ Object
588 589 590 |
# File 'lib/jsonapi/basic_resource.rb', line 588 def { format: :default } end |
.default_sort ⇒ Object
1058 1059 1060 |
# File 'lib/jsonapi/basic_resource.rb', line 1058 def default_sort [{field: 'id', direction: :asc}] end |
.define_foreign_key_setter(relationship) ⇒ Object
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 |
# File 'lib/jsonapi/basic_resource.rb', line 1098 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
1111 1112 1113 1114 |
# File 'lib/jsonapi/basic_resource.rb', line 1111 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
1089 1090 1091 1092 1093 1094 1095 1096 |
# File 'lib/jsonapi/basic_resource.rb', line 1089 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
997 998 999 |
# File 'lib/jsonapi/basic_resource.rb', line 997 def exclude_link?(link) _exclude_links.include?(link.to_sym) end |
.exclude_links(exclude) ⇒ Object
989 990 991 |
# File 'lib/jsonapi/basic_resource.rb', line 989 def exclude_links(exclude) @_exclude_links = parse_exclude_links(exclude) end |
.fields ⇒ Object
703 704 705 |
# File 'lib/jsonapi/basic_resource.rb', line 703 def fields @_fields_cache ||= _relationships.keys | _attributes.keys end |
.filter(attr, *args) ⇒ Object
663 664 665 |
# File 'lib/jsonapi/basic_resource.rb', line 663 def filter(attr, *args) @_allowed_filters[attr.to_sym] = args. end |
.filters(*attrs) ⇒ Object
659 660 661 |
# File 'lib/jsonapi/basic_resource.rb', line 659 def filters(*attrs) @_allowed_filters.merge!(attrs.inject({}) { |h, attr| h[attr] = {}; h }) end |
.has_many(*attrs) ⇒ Object
621 622 623 |
# File 'lib/jsonapi/basic_resource.rb', line 621 def has_many(*attrs) _add_relationship(Relationship::ToMany, *attrs) end |
.has_one(*attrs) ⇒ Object
607 608 609 |
# File 'lib/jsonapi/basic_resource.rb', line 607 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
1022 1023 1024 |
# File 'lib/jsonapi/basic_resource.rb', line 1022 def hash_cache_field(value) value.hash end |
.immutable(val = true) ⇒ Object
964 965 966 |
# File 'lib/jsonapi/basic_resource.rb', line 964 def immutable(val = true) @immutable = val end |
.inherited(subclass) ⇒ Object
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 460 461 462 463 464 465 466 467 468 |
# File 'lib/jsonapi/basic_resource.rb', line 429 def inherited(subclass) super 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
727 728 729 |
# File 'lib/jsonapi/basic_resource.rb', line 727 def is_filter_relationship?(filter) filter == _type || _relationships.include?(filter) end |
.key_type(key_type) ⇒ Object
763 764 765 |
# File 'lib/jsonapi/basic_resource.rb', line 763 def key_type(key_type) @_resource_key_type = key_type end |
.model_hint(model: _model_name, resource: _type) ⇒ Object
640 641 642 643 644 |
# File 'lib/jsonapi/basic_resource.rb', line 640 def model_hint(model: _model_name, resource: _type) resource_type = ((resource.is_a?(Class)) && (resource < JSONAPI::BasicResource)) ? 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.
631 632 633 634 635 636 637 638 |
# File 'lib/jsonapi/basic_resource.rb', line 631 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
1050 1051 1052 1053 1054 1055 1056 |
# File 'lib/jsonapi/basic_resource.rb', line 1050 def module_path if name == 'JSONAPI::Resource' '' else name =~ /::[^:]+\Z/ ? ($`.freeze.gsub('::', '/') + '/').underscore : '' end end |
.mutable? ⇒ Boolean
972 973 974 |
# File 'lib/jsonapi/basic_resource.rb', line 972 def mutable? !@immutable end |
.paginator(paginator) ⇒ Object
914 915 916 |
# File 'lib/jsonapi/basic_resource.rb', line 914 def paginator(paginator) @_paginator = paginator end |
.parse_exclude_links(exclude) ⇒ Object
976 977 978 979 980 981 982 983 984 985 986 987 |
# File 'lib/jsonapi/basic_resource.rb', line 976 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
922 923 924 |
# File 'lib/jsonapi/basic_resource.rb', line 922 def polymorphic(polymorphic = true) @_polymorphic = polymorphic end |
.primary_key(key) ⇒ Object
676 677 678 |
# File 'lib/jsonapi/basic_resource.rb', line 676 def primary_key(key) @_primary_key = key.to_sym end |
.rebuild_relationships(relationships) ⇒ Object
470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/jsonapi/basic_resource.rb', line 470 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
1116 1117 1118 |
# File 'lib/jsonapi/basic_resource.rb', line 1116 def register_relationship(name, relationship_object) @_relationships[name] = relationship_object end |
.relationship(*attrs) ⇒ Object
592 593 594 595 596 597 598 599 600 601 602 603 604 605 |
# File 'lib/jsonapi/basic_resource.rb', line 592 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
713 714 715 716 |
# File 'lib/jsonapi/basic_resource.rb', line 713 def resource_for(model_record, context) resource_klass = resource_klass_for_model(model_record) resource_klass.new(model_record, context) end |
.resource_key_type ⇒ Object
767 768 769 |
# File 'lib/jsonapi/basic_resource.rb', line 767 def resource_key_type @_resource_key_type || JSONAPI.configuration.resource_key_type end |
.resource_klass_for(type) ⇒ Object
485 486 487 488 489 490 491 492 493 494 495 |
# File 'lib/jsonapi/basic_resource.rb', line 485 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
497 498 499 |
# File 'lib/jsonapi/basic_resource.rb', line 497 def resource_klass_for_model(model) resource_klass_for(resource_type_for(model)) end |
.resource_type_for(model) ⇒ Object
505 506 507 508 509 510 511 512 |
# File 'lib/jsonapi/basic_resource.rb', line 505 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
707 708 709 710 711 |
# File 'lib/jsonapi/basic_resource.rb', line 707 def resources_for(records, context) records.collect do |record| resource_for(record, context) end end |
.root? ⇒ Boolean
952 953 954 |
# File 'lib/jsonapi/basic_resource.rb', line 952 def root? @root end |
.root_resource ⇒ Object
946 947 948 949 950 |
# File 'lib/jsonapi/basic_resource.rb', line 946 def root_resource @abstract = true @immutable = true @root = true end |
.routing_options(options) ⇒ Object
525 526 527 |
# File 'lib/jsonapi/basic_resource.rb', line 525 def () @_routing_resource_options = end |
.routing_resource_options ⇒ Object
529 530 531 |
# File 'lib/jsonapi/basic_resource.rb', line 529 def @_routing_resource_options ||= {} end |
.singleton(*attrs) ⇒ Object
646 647 648 649 |
# File 'lib/jsonapi/basic_resource.rb', line 646 def singleton(*attrs) @_singleton = (!!attrs[0] == attrs[0]) ? attrs[0] : true @_singleton_options = attrs. end |
.singleton? ⇒ Boolean
655 656 657 |
# File 'lib/jsonapi/basic_resource.rb', line 655 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`
774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
# File 'lib/jsonapi/basic_resource.rb', line 774 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
667 668 669 |
# File 'lib/jsonapi/basic_resource.rb', line 667 def sort(sorting, = {}) self._allowed_sort[sorting.to_sym] = end |
.sortable_field?(key, context = nil) ⇒ Boolean
699 700 701 |
# File 'lib/jsonapi/basic_resource.rb', line 699 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
695 696 697 |
# File 'lib/jsonapi/basic_resource.rb', line 695 def sortable_fields(_context = nil) _allowed_sort.keys end |
.sorts(*args) ⇒ Object
671 672 673 674 |
# File 'lib/jsonapi/basic_resource.rb', line 671 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
685 686 687 |
# File 'lib/jsonapi/basic_resource.rb', line 685 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
825 826 827 |
# File 'lib/jsonapi/basic_resource.rb', line 825 def verify_custom_filter(filter, value, _context = nil) [filter, value] end |
.verify_filter(filter, raw, context = nil) ⇒ Object
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
# File 'lib/jsonapi/basic_resource.rb', line 731 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
718 719 720 721 722 723 724 725 |
# File 'lib/jsonapi/basic_resource.rb', line 718 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
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 814 815 |
# File 'lib/jsonapi/basic_resource.rb', line 789 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
818 819 820 821 822 |
# File 'lib/jsonapi/basic_resource.rb', line 818 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
831 832 833 |
# File 'lib/jsonapi/basic_resource.rb', line 831 def verify_relationship_filter(filter, raw, _context = nil) [filter, raw] end |
Instance Method Details
#_model ⇒ Object
37 38 39 |
# File 'lib/jsonapi/basic_resource.rb', line 37 def _model @model end |
#cache_field_value ⇒ Object
49 50 51 |
# File 'lib/jsonapi/basic_resource.rb', line 49 def cache_field_value _model.public_send(self.class._cache_field) end |
#cache_id ⇒ Object
53 54 55 |
# File 'lib/jsonapi/basic_resource.rb', line 53 def cache_id [id, self.class.hash_cache_field(cache_field_value)] end |
#change(callback) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/jsonapi/basic_resource.rb', line 61 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
88 89 90 91 92 |
# File 'lib/jsonapi/basic_resource.rb', line 88 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
176 177 178 |
# File 'lib/jsonapi/basic_resource.rb', line 176 def custom_links() {} end |
#fetchable_fields ⇒ Object
Override this on a resource instance to override the fetchable keys
131 132 133 |
# File 'lib/jsonapi/basic_resource.rb', line 131 def fetchable_fields self.class.fields end |
#id ⇒ Object
41 42 43 |
# File 'lib/jsonapi/basic_resource.rb', line 41 def id _model.public_send(self.class._primary_key) end |
#identity ⇒ Object
45 46 47 |
# File 'lib/jsonapi/basic_resource.rb', line 45 def identity JSONAPI::ResourceIdentity.new(self.class, id) end |
#is_new? ⇒ Boolean
57 58 59 |
# File 'lib/jsonapi/basic_resource.rb', line 57 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
167 168 169 |
# File 'lib/jsonapi/basic_resource.rb', line 167 def () {} end |
#model_error_messages ⇒ Object
135 136 137 |
# File 'lib/jsonapi/basic_resource.rb', line 135 def _model.errors. end |
#remove ⇒ Object
82 83 84 85 86 |
# File 'lib/jsonapi/basic_resource.rb', line 82 def remove run_callbacks :remove do _remove end end |
#remove_to_many_link(relationship_type, key, options = {}) ⇒ Object
112 113 114 115 116 |
# File 'lib/jsonapi/basic_resource.rb', line 112 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
118 119 120 121 122 |
# File 'lib/jsonapi/basic_resource.rb', line 118 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
124 125 126 127 128 |
# File 'lib/jsonapi/basic_resource.rb', line 124 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
106 107 108 109 110 |
# File 'lib/jsonapi/basic_resource.rb', line 106 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
94 95 96 97 98 |
# File 'lib/jsonapi/basic_resource.rb', line 94 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
100 101 102 103 104 |
# File 'lib/jsonapi/basic_resource.rb', line 100 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.
158 159 160 |
# File 'lib/jsonapi/basic_resource.rb', line 158 def {} end |