module Protip::Resource::ClassMethods
Constants
- VALID_ACTIONS
Attributes
base_path[W]
belongs_to_associations[R]
belongs_to_polymorphic_associations[R]
client[RW]
message[R]
nested_resources[R]
transformer[W]
Public Class Methods
new(resource_class)
click to toggle source
# File lib/protip/resource.rb, line 250 def initialize(resource_class) @resource_class = resource_class @associations = [] end
Public Instance Methods
base_path()
click to toggle source
# File lib/protip/resource.rb, line 71 def base_path if @base_path == nil raise(RuntimeError.new 'Base path not yet set') else @base_path.gsub(/\/$/, '') end end
transformer()
click to toggle source
# File lib/protip/resource.rb, line 79 def transformer defined?(@transformer) ? @transformer : ::Protip.default_transformer end
Private Instance Methods
belongs_to(association_name, options = {})
click to toggle source
# File lib/protip/resource.rb, line 237 def belongs_to(association_name, options = {}) association = ::Protip::Resource::Associations::BelongsToAssociation.new(self, association_name, **options) association.define_accessors! @belongs_to_associations.add association association end
belongs_to_polymorphic(association_name, options = {}, &block)
click to toggle source
# File lib/protip/resource.rb, line 244 def belongs_to_polymorphic(association_name, options = {}, &block) # We evaluate the block in the context of a wrapper that # stores simple belongs-to associations as they're being # created. nested_association_creator = Class.new do attr_reader :associations def initialize(resource_class) @resource_class = resource_class @associations = [] end def belongs_to(*args) # Just forward the belongs_to call and store the result so we can pass it to the polymorphic association @associations << @resource_class.send(:belongs_to, *args) end end.new(self) nested_association_creator.instance_eval(&block) association = ::Protip::Resource::Associations::BelongsToPolymorphicAssociation.new self, association_name, nested_association_creator.associations, **options association.define_accessors! @belongs_to_polymorphic_associations.add association association end
collection(action:, method:, request: nil, response: nil)
click to toggle source
# File lib/protip/resource.rb, line 216 def collection(action:, method:, request: nil, response: nil) if request define_singleton_method action do |request_params = {}| message = nil if request_params.is_a?(request) # Message provided directly message = request_params else # Parameters provided by hash decorator = ::Protip::Decorator.new(request.new, transformer) decorator.assign_attributes request_params message = decorator.message end ::Protip::Resource::ExtraMethods.collection self, action, method, message, response end else define_singleton_method action do ::Protip::Resource::ExtraMethods.collection self, action, method, nil, response end end end
define_attribute_accessors(message)
click to toggle source
Define attribute readers/writers
# File lib/protip/resource.rb, line 129 def define_attribute_accessors(message) message.descriptor.each do |field| def_delegator :@decorator, :"#{field.name}" def_delegator :@decorator, :"#{field.name}?" define_method "#{field.name}=" do |new_value| old_value = self.message[field.name] # Only compare the raw values @decorator.send("#{field.name}=", new_value) new_value = self.message[field.name] # Need to check that types are the same first, otherwise protobuf gets mad comparing # messages with non-messages send("#{field.name}_will_change!") unless new_value.class == old_value.class && new_value == old_value end # needed for ActiveModel::Dirty define_attribute_method field.name end end
define_oneof_group_methods(message)
click to toggle source
Allow calls to oneof groups to get the set oneof field
# File lib/protip/resource.rb, line 122 def define_oneof_group_methods(message) message.descriptor.each_oneof do |oneof_field| def_delegator :@decorator, :"#{oneof_field.name}" end end
define_resource_query_methods(query, actions)
click to toggle source
For index/show, we want a different number of method arguments depending on whether a query message was provided.
# File lib/protip/resource.rb, line 151 def define_resource_query_methods(query, actions) if query if actions.include?(:show) define_singleton_method :find do |id, query_params = {}| message = nil if query_params.is_a?(query) message = query_params else decorator = ::Protip::Decorator.new(query.new, transformer) decorator.assign_attributes query_params message = decorator.message end ::Protip::Resource::SearchMethods.show(self, id, message) end end if actions.include?(:index) define_singleton_method :all do |query_params = {}| message = nil if query_params.is_a?(query) message = query_params else decorator = ::Protip::Decorator.new(query.new, transformer) decorator.assign_attributes query_params message = decorator.message end ::Protip::Resource::SearchMethods.index(self, message) end end else if actions.include?(:show) define_singleton_method :find do |id| ::Protip::Resource::SearchMethods.show(self, id, nil) end end if actions.include?(:index) define_singleton_method :all do ::Protip::Resource::SearchMethods.index(self, nil) end end end end
member(action:, method:, request: nil, response: nil)
click to toggle source
# File lib/protip/resource.rb, line 195 def member(action:, method:, request: nil, response: nil) if request define_method action do |request_params = {}| message = nil if request_params.is_a?(request) # Message provided directly message = request_params else # Parameters provided by hash decorator = ::Protip::Decorator.new(request.new, self.class.transformer) decorator.assign_attributes request_params message = decorator.message end ::Protip::Resource::ExtraMethods.member self, action, method, message, response end else define_method action do ::Protip::Resource::ExtraMethods.member self, action, method, nil, response end end end
references_through_one_of(id_field, options = {})
click to toggle source
# File lib/protip/resource.rb, line 269 def references_through_one_of(id_field, options = {}) ::Protip::Resource::Associations::ReferencesThroughOneOfAssociation.new(self, id_field, options) .define_accessors! end
resource(actions:, message:, query: nil, nested_resources: {})
click to toggle source
Primary entry point for defining resourceful behavior.
# File lib/protip/resource.rb, line 86 def resource(actions:, message:, query: nil, nested_resources: {}) raise RuntimeError.new('Only one call to `resource` is allowed') if defined?(@message) && @message validate_actions!(actions) validate_nested_resources!(nested_resources) @message = message @nested_resources = nested_resources define_attribute_accessors(@message) define_oneof_group_methods(@message) define_resource_query_methods(query, actions) include(::Protip::Resource::Creatable) if actions.include?(:create) include(::Protip::Resource::Updatable) if actions.include?(:update) include(::Protip::Resource::Destroyable) if actions.include?(:destroy) end
validate_actions!(actions)
click to toggle source
# File lib/protip/resource.rb, line 114 def validate_actions!(actions) actions.map!{|action| action.to_sym} (actions - VALID_ACTIONS).each do |action| raise ArgumentError.new("Unrecognized action: #{action}") end end
validate_nested_resources!(nested_resources)
click to toggle source
# File lib/protip/resource.rb, line 103 def validate_nested_resources!(nested_resources) nested_resources.each do |key, resource_klass| unless key.is_a?(Symbol) raise "#{key} must be a Symbol, but is a #{key.class}" end unless resource_klass < ::Protip::Resource raise "#{resource_klass} is not a Protip::Resource" end end end