active_remote 5.1.1 → 5.2.0.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/active_remote.gemspec +2 -2
- data/bin/benchmark +12 -5
- data/lib/active_remote/association.rb +7 -9
- data/lib/active_remote/attribute_methods.rb +51 -0
- data/lib/active_remote/base.rb +64 -14
- data/lib/active_remote/dirty.rb +4 -7
- data/lib/active_remote/integration.rb +112 -26
- data/lib/active_remote/persistence.rb +1 -1
- data/lib/active_remote/primary_key.rb +18 -0
- data/lib/active_remote/rpc.rb +3 -4
- data/lib/active_remote/search.rb +2 -1
- data/lib/active_remote/version.rb +1 -1
- data/spec/lib/active_remote/association_spec.rb +0 -16
- data/spec/lib/active_remote/dirty_spec.rb +14 -29
- data/spec/lib/active_remote/integration_spec.rb +80 -12
- data/spec/lib/active_remote/query_attribute_spec.rb +8 -17
- data/spec/lib/active_remote/rpc_spec.rb +5 -1
- data/spec/lib/active_remote/search_spec.rb +4 -3
- data/spec/support/models.rb +0 -1
- data/spec/support/models/author.rb +10 -6
- data/spec/support/models/category.rb +3 -3
- data/spec/support/models/default_author.rb +2 -2
- data/spec/support/models/post.rb +5 -5
- data/spec/support/models/tag.rb +4 -4
- metadata +10 -16
- data/lib/active_remote/attribute_definition.rb +0 -114
- data/lib/active_remote/attributes.rb +0 -204
- data/spec/lib/active_remote/attributes_spec.rb +0 -223
- data/spec/support/models/typecasted_author.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d8212d6102d24ca632d2f76449826bf4593b2a76a0d27269866a0d3533b4813
|
4
|
+
data.tar.gz: e648845212e9756304427bccfc60da60d2aaf2325e309639905cfeb163e234bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89eed8d66c19ddc8daecd21db103ff91d29a5d2b779770163e7962a85a33c32c4c2d41f64ae8e27d950e87ddfa563350058a3478aa56e4b6ce50618405b1582f
|
7
|
+
data.tar.gz: d137fab5f02b7f753be9122f6aabe18c9593456a740384e1da0b80aca8ac1d9eaaaf6e8c8ca5c7d5cd2dae58c971ac04e0f5c274301d90a71f3ae1f3215502f9
|
data/active_remote.gemspec
CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |s|
|
|
20
20
|
##
|
21
21
|
# Dependencies
|
22
22
|
#
|
23
|
-
s.add_dependency "activemodel", "~> 5.
|
24
|
-
s.add_dependency "activesupport", "~> 5.
|
23
|
+
s.add_dependency "activemodel", "~> 5.2"
|
24
|
+
s.add_dependency "activesupport", "~> 5.2"
|
25
25
|
s.add_dependency "protobuf", ">= 3.0"
|
26
26
|
|
27
27
|
##
|
data/bin/benchmark
CHANGED
@@ -5,7 +5,14 @@ require "bundler/setup"
|
|
5
5
|
require "active_remote"
|
6
6
|
require "benchmark/ips"
|
7
7
|
|
8
|
-
|
8
|
+
class Author < ::ActiveRemote::Base
|
9
|
+
attribute :guid, :string
|
10
|
+
attribute :name, :string
|
11
|
+
attribute :age, :integer
|
12
|
+
attribute :birthday, :datetime
|
13
|
+
attribute :writes_fiction, :boolean
|
14
|
+
attribute :net_sales, :float
|
15
|
+
end
|
9
16
|
|
10
17
|
ATTRIBUTES = {
|
11
18
|
:guid => "0c030733-3b78-4587-b94b-5e0cf26497c5",
|
@@ -19,18 +26,18 @@ ATTRIBUTES = {
|
|
19
26
|
::Benchmark.ips do |x|
|
20
27
|
x.config(:time => 20, :warmup => 10)
|
21
28
|
x.report("initialize") do
|
22
|
-
::
|
29
|
+
::Author.new(ATTRIBUTES)
|
23
30
|
end
|
24
31
|
|
25
32
|
x.report("instantiate") do
|
26
|
-
::
|
33
|
+
::Author.instantiate(ATTRIBUTES)
|
27
34
|
end
|
28
35
|
|
29
36
|
x.report("init attributes") do
|
30
|
-
::
|
37
|
+
::Author.new(ATTRIBUTES).attributes
|
31
38
|
end
|
32
39
|
|
33
40
|
x.report("inst attributes") do
|
34
|
-
::
|
41
|
+
::Author.instantiate(ATTRIBUTES).attributes
|
35
42
|
end
|
36
43
|
end
|
@@ -8,8 +8,7 @@ module ActiveRemote
|
|
8
8
|
# class must be loaded into memory already. A method will be defined
|
9
9
|
# with the same name as the association. When invoked, the associated
|
10
10
|
# remote model will issue a `search` for the :guid with the associated
|
11
|
-
# guid
|
12
|
-
# remote object from the result, or nil.
|
11
|
+
# guid attribute and return the first remote object from the result, or nil.
|
13
12
|
#
|
14
13
|
# A `belongs_to` association should be used when the associating remote
|
15
14
|
# contains the guid to the associated model. For example, if a User model
|
@@ -37,8 +36,8 @@ module ActiveRemote
|
|
37
36
|
perform_association(belongs_to_klass, options) do |klass, object|
|
38
37
|
foreign_key = options.fetch(:foreign_key) { :"#{klass.name.demodulize.underscore}_guid" }
|
39
38
|
search_hash = {}
|
40
|
-
search_hash[:guid] = object.
|
41
|
-
search_hash[options[:scope]] = object.
|
39
|
+
search_hash[:guid] = object.send(foreign_key)
|
40
|
+
search_hash[options[:scope]] = object.send(options[:scope]) if options.key?(:scope)
|
42
41
|
|
43
42
|
search_hash.values.any?(&:nil?) ? nil : klass.search(search_hash).first
|
44
43
|
end
|
@@ -49,7 +48,7 @@ module ActiveRemote
|
|
49
48
|
# class must be loaded into memory already. A method will be defined
|
50
49
|
# with the same plural name as the association. When invoked, the associated
|
51
50
|
# remote model will issue a `search` for the :guid with the associated
|
52
|
-
# guid
|
51
|
+
# guid attribute.
|
53
52
|
#
|
54
53
|
# A `has_many` association should be used when the associated model has
|
55
54
|
# a field to identify the associating model, and there can be multiple
|
@@ -79,7 +78,7 @@ module ActiveRemote
|
|
79
78
|
foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" }
|
80
79
|
search_hash = {}
|
81
80
|
search_hash[foreign_key] = object.guid
|
82
|
-
search_hash[options[:scope]] = object.
|
81
|
+
search_hash[options[:scope]] = object.send(options[:scope]) if options.key?(:scope)
|
83
82
|
|
84
83
|
search_hash.values.any?(&:nil?) ? [] : klass.search(search_hash)
|
85
84
|
end
|
@@ -93,8 +92,7 @@ module ActiveRemote
|
|
93
92
|
# class must be loaded into memory already. A method will be defined
|
94
93
|
# with the same name as the association. When invoked, the associated
|
95
94
|
# remote model will issue a `search` for the :guid with the associated
|
96
|
-
# guid
|
97
|
-
# remote object in the result, or nil.
|
95
|
+
# guid attribute and return the first remote object in the result, or nil.
|
98
96
|
#
|
99
97
|
# A `has_one` association should be used when the associated remote
|
100
98
|
# contains the guid from the associating model. For example, if a User model
|
@@ -120,7 +118,7 @@ module ActiveRemote
|
|
120
118
|
foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" }
|
121
119
|
search_hash = {}
|
122
120
|
search_hash[foreign_key] = object.guid
|
123
|
-
search_hash[options[:scope]] = object.
|
121
|
+
search_hash[options[:scope]] = object.send(options[:scope]) if options.key?(:scope)
|
124
122
|
|
125
123
|
search_hash.values.any?(&:nil?) ? nil : klass.search(search_hash).first
|
126
124
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActiveRemote
|
2
|
+
module AttributeMethods
|
3
|
+
extend ::ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def attribute_names
|
7
|
+
@attribute_names ||= attribute_types.keys
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](name)
|
12
|
+
attribute(name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(name, value)
|
16
|
+
write_attribute(name, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an <tt>#inspect</tt>-like string for the value of the
|
20
|
+
# attribute +attr_name+. String attributes are truncated up to 50
|
21
|
+
# characters, Date and Time attributes are returned in the
|
22
|
+
# <tt>:db</tt> format. Other attributes return the value of
|
23
|
+
# <tt>#inspect</tt> without modification.
|
24
|
+
#
|
25
|
+
# person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
|
26
|
+
#
|
27
|
+
# person.attribute_for_inspect(:name)
|
28
|
+
# # => "\"David Heinemeier Hansson David Heinemeier Hansson ...\""
|
29
|
+
#
|
30
|
+
# person.attribute_for_inspect(:created_at)
|
31
|
+
# # => "\"2012-10-22 00:15:07\""
|
32
|
+
#
|
33
|
+
# person.attribute_for_inspect(:tag_ids)
|
34
|
+
# # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
|
35
|
+
def attribute_for_inspect(attr_name)
|
36
|
+
value = attribute(attr_name)
|
37
|
+
|
38
|
+
if value.is_a?(String) && value.length > 50
|
39
|
+
"#{value[0, 50]}...".inspect
|
40
|
+
elsif value.is_a?(Date) || value.is_a?(Time)
|
41
|
+
%("#{value.to_s(:db)}")
|
42
|
+
else
|
43
|
+
value.inspect
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def attribute_names
|
48
|
+
@attributes.keys
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/active_remote/base.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require "active_model/callbacks"
|
2
2
|
|
3
3
|
require "active_remote/association"
|
4
|
-
require "active_remote/
|
5
|
-
require "active_remote/attributes"
|
4
|
+
require "active_remote/attribute_methods"
|
6
5
|
require "active_remote/config"
|
7
6
|
require "active_remote/dirty"
|
8
7
|
require "active_remote/dsl"
|
@@ -21,14 +20,16 @@ module ActiveRemote
|
|
21
20
|
extend ::ActiveModel::Callbacks
|
22
21
|
|
23
22
|
include ::ActiveModel::Model
|
23
|
+
include ::ActiveModel::Attributes
|
24
24
|
|
25
25
|
include ::ActiveRemote::Association
|
26
|
-
include ::ActiveRemote::
|
26
|
+
include ::ActiveRemote::AttributeMethods
|
27
27
|
include ::ActiveRemote::DSL
|
28
28
|
include ::ActiveRemote::Integration
|
29
|
+
include ::ActiveRemote::QueryAttributes
|
29
30
|
include ::ActiveRemote::Persistence
|
30
31
|
include ::ActiveRemote::PrimaryKey
|
31
|
-
|
32
|
+
|
32
33
|
include ::ActiveRemote::RPC
|
33
34
|
include ::ActiveRemote::ScopeKeys
|
34
35
|
include ::ActiveRemote::Search
|
@@ -45,10 +46,7 @@ module ActiveRemote
|
|
45
46
|
define_model_callbacks :initialize, :only => :after
|
46
47
|
|
47
48
|
def initialize(attributes = {})
|
48
|
-
|
49
|
-
|
50
|
-
assign_attributes(attributes) if attributes
|
51
|
-
|
49
|
+
super
|
52
50
|
@new_record = true
|
53
51
|
|
54
52
|
skip_dirty_tracking do
|
@@ -58,6 +56,41 @@ module ActiveRemote
|
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
59
|
+
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
60
|
+
# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
|
61
|
+
#
|
62
|
+
# Note that new records are different from any other record by definition, unless the
|
63
|
+
# other record is the receiver itself. Besides, if you fetch existing records with
|
64
|
+
# +select+ and leave the ID out, you're on your own, this predicate will return false.
|
65
|
+
#
|
66
|
+
# Note also that destroying a record preserves its ID in the model instance, so deleted
|
67
|
+
# models are still comparable.
|
68
|
+
def ==(other)
|
69
|
+
super ||
|
70
|
+
other.instance_of?(self.class) &&
|
71
|
+
!send(primary_key).nil? &&
|
72
|
+
other.send(primary_key) == send(primary_key)
|
73
|
+
end
|
74
|
+
alias_method :eql?, :==
|
75
|
+
|
76
|
+
# Allows sort on objects
|
77
|
+
def <=>(other)
|
78
|
+
if other.is_a?(self.class)
|
79
|
+
to_key <=> other.to_key
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def freeze
|
86
|
+
@attributes.freeze
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def frozen?
|
91
|
+
@attributes.frozen?
|
92
|
+
end
|
93
|
+
|
61
94
|
# Initialize an object with the attributes hash directly
|
62
95
|
# When used with allocate, bypasses initialize
|
63
96
|
def init_with(attributes)
|
@@ -69,15 +102,32 @@ module ActiveRemote
|
|
69
102
|
self
|
70
103
|
end
|
71
104
|
|
72
|
-
|
73
|
-
|
74
|
-
|
105
|
+
# Returns the contents of the record as a nicely formatted string.
|
106
|
+
def inspect
|
107
|
+
# We check defined?(@attributes) not to issue warnings if the object is
|
108
|
+
# allocated but not initialized.
|
109
|
+
inspection = if defined?(@attributes) && @attributes
|
110
|
+
attribute_names.collect do |name, _|
|
111
|
+
if attribute?(name)
|
112
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
113
|
+
else
|
114
|
+
name
|
115
|
+
end
|
116
|
+
end.compact.join(", ")
|
117
|
+
else
|
118
|
+
"not initialized"
|
119
|
+
end
|
120
|
+
|
121
|
+
"#<#{self.class} #{inspection}>"
|
75
122
|
end
|
76
123
|
|
77
|
-
|
78
|
-
|
124
|
+
# Returns a hash of the given methods with their names as keys and returned values as values.
|
125
|
+
def slice(*methods)
|
126
|
+
Hash[methods.flatten.map! { |method| [method, public_send(method)] }].with_indifferent_access
|
79
127
|
end
|
80
128
|
end
|
81
129
|
|
82
|
-
|
130
|
+
::ActiveModel::Type.register(:value, ::ActiveModel::Type::Value)
|
131
|
+
|
132
|
+
::ActiveSupport.run_load_hooks(:active_remote, Base)
|
83
133
|
end
|
data/lib/active_remote/dirty.rb
CHANGED
@@ -24,8 +24,7 @@ module ActiveRemote
|
|
24
24
|
#
|
25
25
|
def reload(*)
|
26
26
|
super.tap do
|
27
|
-
|
28
|
-
changed_attributes.clear
|
27
|
+
clear_changes_information
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
@@ -41,8 +40,7 @@ module ActiveRemote
|
|
41
40
|
#
|
42
41
|
def save(*)
|
43
42
|
if (status = super)
|
44
|
-
|
45
|
-
changed_attributes.clear
|
43
|
+
changes_applied
|
46
44
|
end
|
47
45
|
|
48
46
|
status
|
@@ -52,8 +50,7 @@ module ActiveRemote
|
|
52
50
|
#
|
53
51
|
def save!(*)
|
54
52
|
super.tap do
|
55
|
-
|
56
|
-
changed_attributes.clear
|
53
|
+
changes_applied
|
57
54
|
end
|
58
55
|
end
|
59
56
|
|
@@ -77,7 +74,7 @@ module ActiveRemote
|
|
77
74
|
# ActiveModel::Dirty.
|
78
75
|
#
|
79
76
|
def attribute=(name, value)
|
80
|
-
|
77
|
+
send("#{name}_will_change!") if _active_remote_track_changes? && value != self[name]
|
81
78
|
super
|
82
79
|
end
|
83
80
|
|
@@ -3,48 +3,134 @@ module ActiveRemote
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
##
|
7
|
+
# :singleton-method:
|
8
|
+
# Indicates the format used to generate the timestamp in the cache key, if
|
9
|
+
# versioning is off. Accepts any of the symbols in <tt>Time::DATE_FORMATS</tt>.
|
10
|
+
#
|
11
|
+
# This is +:usec+, by default.
|
12
|
+
class_attribute :cache_timestamp_format, :instance_writer => false, :default => :usec
|
13
|
+
|
14
|
+
##
|
15
|
+
# :singleton-method:
|
16
|
+
# Indicates whether to use a stable #cache_key method that is accompanied
|
17
|
+
# by a changing version in the #cache_version method.
|
18
|
+
#
|
19
|
+
# This is +false+, by default until Rails 6.0.
|
20
|
+
class_attribute :cache_versioning, :instance_writer => false, :default => false
|
16
21
|
end
|
17
22
|
|
18
|
-
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
23
|
+
# Returns a +String+, which Action Pack uses for constructing a URL to this
|
24
|
+
# object. The default implementation returns this record's id as a +String+,
|
25
|
+
# or +nil+ if this record's unsaved.
|
26
|
+
#
|
27
|
+
# For example, suppose that you have a User model, and that you have a
|
28
|
+
# <tt>resources :users</tt> route. Normally, +user_path+ will
|
29
|
+
# construct a path with the user object's 'id' in it:
|
30
|
+
#
|
31
|
+
# user = User.find_by(name: 'Phusion')
|
32
|
+
# user_path(user) # => "/users/1"
|
33
|
+
#
|
34
|
+
# You can override +to_param+ in your model to make +user_path+ construct
|
35
|
+
# a path using the user's name instead of the user's id:
|
22
36
|
#
|
23
|
-
#
|
24
|
-
#
|
37
|
+
# class User < ActiveRecord::Base
|
38
|
+
# def to_param # overridden
|
39
|
+
# name
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# user = User.find_by(name: 'Phusion')
|
44
|
+
# user_path(user) # => "/users/Phusion"
|
25
45
|
#
|
26
46
|
def to_param
|
27
|
-
|
47
|
+
key = send(primary_key)
|
48
|
+
key&.to_s
|
28
49
|
end
|
29
50
|
|
30
|
-
|
31
|
-
# Returns a cache key that can be used to identify this record.
|
32
|
-
#
|
33
|
-
# ==== Examples
|
51
|
+
# Returns a stable cache key that can be used to identify this record.
|
34
52
|
#
|
35
53
|
# Product.new.cache_key # => "products/new"
|
36
|
-
#
|
37
|
-
#
|
54
|
+
# Product.find(5).cache_key # => "products/5"
|
55
|
+
#
|
56
|
+
# If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier,
|
57
|
+
# the cache key will also include a version.
|
58
|
+
#
|
59
|
+
# Product.cache_versioning = false
|
60
|
+
# Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
|
38
61
|
#
|
39
62
|
def cache_key
|
40
63
|
case
|
41
64
|
when new_record? then
|
42
|
-
"#{
|
65
|
+
"#{model_name.cache_key}/new"
|
43
66
|
when ::ActiveRemote.config.default_cache_key_updated_at? && (timestamp = self[:updated_at]) then
|
44
67
|
timestamp = timestamp.utc.to_s(self.class.cache_timestamp_format)
|
45
|
-
"#{
|
68
|
+
"#{model_name.cache_key}/#{send(primary_key)}-#{timestamp}"
|
69
|
+
else
|
70
|
+
"#{model_name.cache_key}/#{send(primary_key)}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a cache key along with the version.
|
75
|
+
def cache_key_with_version
|
76
|
+
if (version = cache_version)
|
77
|
+
"#{cache_key}-#{version}"
|
46
78
|
else
|
47
|
-
|
79
|
+
cache_key
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns a cache version that can be used together with the cache key to form
|
84
|
+
# a recyclable caching scheme. By default, the #updated_at column is used for the
|
85
|
+
# cache_version, but this method can be overwritten to return something else.
|
86
|
+
#
|
87
|
+
# Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to
|
88
|
+
# +false+ (which it is by default until Rails 6.0).
|
89
|
+
def cache_version
|
90
|
+
if cache_versioning && (timestamp = try(:updated_at))
|
91
|
+
timestamp.utc.to_s(:usec)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module ClassMethods
|
96
|
+
# Defines your model's +to_param+ method to generate "pretty" URLs
|
97
|
+
# using +method_name+, which can be any attribute or method that
|
98
|
+
# responds to +to_s+.
|
99
|
+
#
|
100
|
+
# class User < ActiveRecord::Base
|
101
|
+
# to_param :name
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# user = User.find_by(name: 'Fancy Pants')
|
105
|
+
# user.id # => 123
|
106
|
+
# user_path(user) # => "/users/123-fancy-pants"
|
107
|
+
#
|
108
|
+
# Values longer than 20 characters will be truncated. The value
|
109
|
+
# is truncated word by word.
|
110
|
+
#
|
111
|
+
# user = User.find_by(name: 'David Heinemeier Hansson')
|
112
|
+
# user.id # => 125
|
113
|
+
# user_path(user) # => "/users/125-david-heinemeier"
|
114
|
+
#
|
115
|
+
# Because the generated param begins with the record's +id+, it is
|
116
|
+
# suitable for passing to +find+. In a controller, for example:
|
117
|
+
#
|
118
|
+
# params[:id] # => "123-fancy-pants"
|
119
|
+
# User.find(params[:id]).id # => 123
|
120
|
+
def to_param(method_name = nil)
|
121
|
+
if method_name.nil?
|
122
|
+
super()
|
123
|
+
else
|
124
|
+
define_method :to_param do
|
125
|
+
if (default = super()) &&
|
126
|
+
(result = send(method_name).to_s).present? &&
|
127
|
+
(param = result.squish.parameterize.truncate(20, :separator => /-/, :omission => "")).present?
|
128
|
+
"#{default}-#{param}"
|
129
|
+
else
|
130
|
+
default
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
48
134
|
end
|
49
135
|
end
|
50
136
|
end
|