Module: Protobuf::ActiveRecord::Scope::ClassMethods
- Defined in:
- lib/protobuf/active_record/scope.rb
Instance Method Summary collapse
-
#field_scope(field, options = {}) ⇒ Object
Define fields that should be searchable via ‘search_scope`.
- #for_upsert(proto) ⇒ Object
-
#model_scope ⇒ Object
Get an ARel relation to build off of.
-
#parse_search_values(proto, field) ⇒ Object
:noapi:.
-
#search_scope(proto) ⇒ Object
Builds and returns a Arel relation based on the fields that are present in the given protobuf message using the searchable fields to determine what scopes to use.
-
#searchable_field_parsers ⇒ Object
:noapi:.
-
#searchable_fields ⇒ Object
:noapi:.
- #upsert(proto) ⇒ Object
- #upsert!(proto) ⇒ Object
-
#upsert_key(*fields) ⇒ Object
Defines a scope that is eligible for upsert.
- #upsert_keys ⇒ Object
Instance Method Details
#field_scope(field, options = {}) ⇒ Object
Define fields that should be searchable via ‘search_scope`. Accepts a protobuf field and an already defined scope. If no scope is specified, the scope will be the field name, prefixed with `by_` (e.g. when the field is :guid, the scope will be :by_guid).
Optionally, a parser can be provided that will be called, passing the field value as an argument. This allows custom data parsers to be used so that they don’t have to be handled by scopes. Parsers can be procs, lambdas, or symbolized method names and must accept the value of the field as a parameter.
Examples:
class User < ActiveRecord::Base
scope :by_guid, lambda { |*guids| where(:guid => guids) }
scope :custom_guid_scope, lambda { |*guids| where(:guid => guids) }
# Equivalent to `field_scope :guid, :by_guid`
field_scope :guid
# With a custom scope
field_scope :guid, :scope => :custom_guid_scope
# With a custom parser that converts the value to an integer
field_scope :guid, :scope => :custom_guid_scope, :parser => lambda { |value| value.to_i }
end
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/protobuf/active_record/scope.rb', line 43 def field_scope(field, = {}) scope_name = if .include?(:scope) [:scope] else # When no scope is defined, assume the scope is the field, prefixed with `by_` :"by_#{field}" end searchable_fields[field] = scope_name searchable_field_parsers[field] = [:parser] if [:parser] end |
#for_upsert(proto) ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/protobuf/active_record/scope.rb', line 159 def for_upsert(proto) valid_upsert = upsert_keys.find do |upsert_key| upsert_key.all? do |field| proto.respond_to_and_has_and_present?(field) end end fail UpsertNotFoundError unless valid_upsert.present? upsert_scope = model_scope valid_upsert.each do |field| value = proto.__send__(field) upsert_scope = upsert_scope.__send__(searchable_fields[field], value) end upsert_scope.first_or_initialize end |
#model_scope ⇒ Object
Get an ARel relation to build off of. If we’re in Rails 4 we need to use ‘all` instead of `scoped`. :noapi:
58 59 60 |
# File 'lib/protobuf/active_record/scope.rb', line 58 def model_scope (::ActiveRecord::VERSION::MAJOR >= 4) ? all : scoped end |
#parse_search_values(proto, field) ⇒ Object
:noapi:
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/protobuf/active_record/scope.rb', line 63 def parse_search_values(proto, field) value = proto.__send__(field) if searchable_field_parsers[field] parser = searchable_field_parsers[field] value = if parser.respond_to?(:to_sym) __send__(parser.to_sym, value) else parser.call(value) end end values = [value].flatten values.map!(&:to_i) if proto.class.get_field(field, true).enum? values end |
#search_scope(proto) ⇒ Object
Builds and returns a Arel relation based on the fields that are present in the given protobuf message using the searchable fields to determine what scopes to use. Provides several aliases for variety.
Examples:
# Search starting with the default scope and searchable fields
User.search_scope(request)
User.by_fields(request)
User.scope_from_proto(request)
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/protobuf/active_record/scope.rb', line 92 def search_scope(proto) search_relation = model_scope searchable_fields.each do |field, scope_name| next unless proto.respond_to_and_has_and_present?(field) search_values = parse_search_values(proto, field) search_relation = search_relation.__send__(scope_name, *search_values) end search_relation end |
#searchable_field_parsers ⇒ Object
:noapi:
111 112 113 |
# File 'lib/protobuf/active_record/scope.rb', line 111 def searchable_field_parsers @_searchable_field_parsers ||= {} end |
#searchable_fields ⇒ Object
:noapi:
106 107 108 |
# File 'lib/protobuf/active_record/scope.rb', line 106 def searchable_fields @_searchable_fields ||= {} end |
#upsert(proto) ⇒ Object
177 178 179 180 181 182 |
# File 'lib/protobuf/active_record/scope.rb', line 177 def upsert(proto) record = for_upsert(proto) record.assign_attributes(proto) record.save record end |
#upsert!(proto) ⇒ Object
184 185 186 187 188 189 |
# File 'lib/protobuf/active_record/scope.rb', line 184 def upsert!(proto) record = for_upsert(proto) record.assign_attributes(proto) record.save! record end |
#upsert_key(*fields) ⇒ Object
Defines a scope that is eligible for upsert. The scope will be used to initialize a record with first_or_initialize. An upsert scope declariation must specify one or more fields that are required to be present on the request and also must have a field_scope defined.
If multiple upsert scopes are specified, they will be searched in the order they are declared for the first valid scope.
Examples:
class User < ActiveRecord::Base
scope :by_guid, lambda { |*guids| where(:guid => guids) }
scope :by_external_guid, lambda { |*external_guids|
where(:external_guid => exteranl_guids)
}
scope :by_client_guid, lambda { |*client_guids|
joins(:client).where(
:clients => { :guid => client_guids }
)
}
field_scope :guid
field_scope :client_guid
field_scope :external_guid
upsert_scope :external_guid, :client_guid
upsert_scope :guid
end
145 146 147 148 149 150 151 152 153 |
# File 'lib/protobuf/active_record/scope.rb', line 145 def upsert_key(*fields) fields = fields.flatten fields.each do |field| fail UpsertScopeError unless searchable_fields[field].present? end upsert_keys << fields end |
#upsert_keys ⇒ Object
155 156 157 |
# File 'lib/protobuf/active_record/scope.rb', line 155 def upsert_keys @_upsert_keys ||= [] end |