parse-stack-next 4.5.0
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 +7 -0
- data/.bundle/config +2 -0
- data/.env.sample +112 -0
- data/.env.test +10 -0
- data/.github/workflows/ruby.yml +36 -0
- data/.gitignore +49 -0
- data/.ruby-version +1 -0
- data/.solargraph.yml +22 -0
- data/CHANGELOG.md +5816 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +175 -0
- data/LICENSE.txt +23 -0
- data/Makefile +63 -0
- data/README.md +5655 -0
- data/Rakefile +573 -0
- data/bin/console +38 -0
- data/bin/parse-console +136 -0
- data/bin/server +17 -0
- data/bin/setup +7 -0
- data/config/parse-config.json +12 -0
- data/docs/TEST_SERVER.md +271 -0
- data/docs/_config.yml +1 -0
- data/docs/mcp_guide.md +3484 -0
- data/docs/mongodb_direct_guide.md +1348 -0
- data/docs/mongodb_index_optimization_guide.md +631 -0
- data/examples/transaction_example.rb +219 -0
- data/lib/parse/acl_scope.rb +728 -0
- data/lib/parse/agent/cancellation_token.rb +80 -0
- data/lib/parse/agent/constraint_translator.rb +480 -0
- data/lib/parse/agent/describe.rb +420 -0
- data/lib/parse/agent/errors.rb +133 -0
- data/lib/parse/agent/mcp_client.rb +557 -0
- data/lib/parse/agent/mcp_dispatcher.rb +1023 -0
- data/lib/parse/agent/mcp_rack_app.rb +1143 -0
- data/lib/parse/agent/mcp_server.rb +376 -0
- data/lib/parse/agent/metadata_audit.rb +259 -0
- data/lib/parse/agent/metadata_dsl.rb +733 -0
- data/lib/parse/agent/metadata_registry.rb +794 -0
- data/lib/parse/agent/pipeline_validator.rb +82 -0
- data/lib/parse/agent/prompts.rb +351 -0
- data/lib/parse/agent/rate_limiter.rb +158 -0
- data/lib/parse/agent/relation_graph.rb +162 -0
- data/lib/parse/agent/result_formatter.rb +453 -0
- data/lib/parse/agent/tools.rb +5489 -0
- data/lib/parse/agent.rb +3249 -0
- data/lib/parse/api/aggregate.rb +79 -0
- data/lib/parse/api/all.rb +26 -0
- data/lib/parse/api/analytics.rb +18 -0
- data/lib/parse/api/batch.rb +33 -0
- data/lib/parse/api/cloud_functions.rb +58 -0
- data/lib/parse/api/config.rb +125 -0
- data/lib/parse/api/files.rb +29 -0
- data/lib/parse/api/hooks.rb +117 -0
- data/lib/parse/api/objects.rb +146 -0
- data/lib/parse/api/path_segment.rb +75 -0
- data/lib/parse/api/push.rb +20 -0
- data/lib/parse/api/schema.rb +49 -0
- data/lib/parse/api/server.rb +50 -0
- data/lib/parse/api/sessions.rb +24 -0
- data/lib/parse/api/users.rb +250 -0
- data/lib/parse/atlas_search/index_manager.rb +353 -0
- data/lib/parse/atlas_search/result.rb +204 -0
- data/lib/parse/atlas_search/search_builder.rb +604 -0
- data/lib/parse/atlas_search/session.rb +253 -0
- data/lib/parse/atlas_search.rb +995 -0
- data/lib/parse/client/authentication.rb +97 -0
- data/lib/parse/client/batch.rb +234 -0
- data/lib/parse/client/body_builder.rb +240 -0
- data/lib/parse/client/caching.rb +203 -0
- data/lib/parse/client/logging.rb +293 -0
- data/lib/parse/client/profiling.rb +181 -0
- data/lib/parse/client/protocol.rb +91 -0
- data/lib/parse/client/request.rb +233 -0
- data/lib/parse/client/response.rb +208 -0
- data/lib/parse/client.rb +1104 -0
- data/lib/parse/clp_scope.rb +361 -0
- data/lib/parse/live_query/circuit_breaker.rb +256 -0
- data/lib/parse/live_query/client.rb +1001 -0
- data/lib/parse/live_query/configuration.rb +224 -0
- data/lib/parse/live_query/event.rb +115 -0
- data/lib/parse/live_query/event_queue.rb +272 -0
- data/lib/parse/live_query/health_monitor.rb +214 -0
- data/lib/parse/live_query/logging.rb +149 -0
- data/lib/parse/live_query/subscription.rb +294 -0
- data/lib/parse/live_query.rb +163 -0
- data/lib/parse/lookup_rewriter.rb +445 -0
- data/lib/parse/model/acl.rb +968 -0
- data/lib/parse/model/associations/belongs_to.rb +275 -0
- data/lib/parse/model/associations/collection_proxy.rb +435 -0
- data/lib/parse/model/associations/has_many.rb +597 -0
- data/lib/parse/model/associations/has_one.rb +158 -0
- data/lib/parse/model/associations/pointer_collection_proxy.rb +134 -0
- data/lib/parse/model/associations/relation_collection_proxy.rb +177 -0
- data/lib/parse/model/bytes.rb +62 -0
- data/lib/parse/model/classes/audience.rb +262 -0
- data/lib/parse/model/classes/installation.rb +363 -0
- data/lib/parse/model/classes/job_schedule.rb +153 -0
- data/lib/parse/model/classes/job_status.rb +264 -0
- data/lib/parse/model/classes/product.rb +75 -0
- data/lib/parse/model/classes/push_status.rb +263 -0
- data/lib/parse/model/classes/role.rb +751 -0
- data/lib/parse/model/classes/session.rb +201 -0
- data/lib/parse/model/classes/user.rb +943 -0
- data/lib/parse/model/clp.rb +544 -0
- data/lib/parse/model/core/actions.rb +1268 -0
- data/lib/parse/model/core/builder.rb +139 -0
- data/lib/parse/model/core/create_lock.rb +386 -0
- data/lib/parse/model/core/describe.rb +382 -0
- data/lib/parse/model/core/enhanced_change_tracking.rb +159 -0
- data/lib/parse/model/core/errors.rb +38 -0
- data/lib/parse/model/core/fetching.rb +566 -0
- data/lib/parse/model/core/field_guards.rb +220 -0
- data/lib/parse/model/core/indexing.rb +382 -0
- data/lib/parse/model/core/parse_reference.rb +407 -0
- data/lib/parse/model/core/properties.rb +809 -0
- data/lib/parse/model/core/querying.rb +491 -0
- data/lib/parse/model/core/schema.rb +202 -0
- data/lib/parse/model/core/search_indexing.rb +174 -0
- data/lib/parse/model/date.rb +88 -0
- data/lib/parse/model/email.rb +213 -0
- data/lib/parse/model/file.rb +527 -0
- data/lib/parse/model/geojson.rb +271 -0
- data/lib/parse/model/geopoint.rb +261 -0
- data/lib/parse/model/model.rb +260 -0
- data/lib/parse/model/object.rb +2068 -0
- data/lib/parse/model/phone.rb +520 -0
- data/lib/parse/model/pointer.rb +443 -0
- data/lib/parse/model/polygon.rb +406 -0
- data/lib/parse/model/push.rb +975 -0
- data/lib/parse/model/shortnames.rb +8 -0
- data/lib/parse/model/time_zone.rb +141 -0
- data/lib/parse/model/validations/uniqueness_validator.rb +97 -0
- data/lib/parse/model/validations.rb +96 -0
- data/lib/parse/mongodb.rb +2300 -0
- data/lib/parse/pipeline_security.rb +554 -0
- data/lib/parse/query/constraint.rb +198 -0
- data/lib/parse/query/constraints.rb +3279 -0
- data/lib/parse/query/cursor.rb +434 -0
- data/lib/parse/query/n_plus_one_detector.rb +445 -0
- data/lib/parse/query/operation.rb +104 -0
- data/lib/parse/query/ordering.rb +66 -0
- data/lib/parse/query.rb +7028 -0
- data/lib/parse/schema/index_migrator.rb +291 -0
- data/lib/parse/schema/search_index_migrator.rb +289 -0
- data/lib/parse/schema.rb +494 -0
- data/lib/parse/stack/generators/rails.rb +40 -0
- data/lib/parse/stack/generators/templates/model.erb +51 -0
- data/lib/parse/stack/generators/templates/model_installation.rb +4 -0
- data/lib/parse/stack/generators/templates/model_role.rb +4 -0
- data/lib/parse/stack/generators/templates/model_session.rb +4 -0
- data/lib/parse/stack/generators/templates/model_user.rb +11 -0
- data/lib/parse/stack/generators/templates/parse.rb +12 -0
- data/lib/parse/stack/generators/templates/webhooks.rb +10 -0
- data/lib/parse/stack/railtie.rb +18 -0
- data/lib/parse/stack/tasks.rb +563 -0
- data/lib/parse/stack/version.rb +11 -0
- data/lib/parse/stack.rb +455 -0
- data/lib/parse/two_factor_auth/user_extension.rb +449 -0
- data/lib/parse/two_factor_auth.rb +310 -0
- data/lib/parse/webhooks/payload.rb +360 -0
- data/lib/parse/webhooks/registration.rb +199 -0
- data/lib/parse/webhooks/replay_protection.rb +189 -0
- data/lib/parse/webhooks.rb +510 -0
- data/lib/parse-stack-next.rb +5 -0
- data/lib/parse-stack.rb +5 -0
- data/parse-stack-next.gemspec +82 -0
- data/parse-stack.png +0 -0
- data/scripts/debug-ips.js +35 -0
- data/scripts/docker/Dockerfile.parse +13 -0
- data/scripts/docker/atlas-init.js +284 -0
- data/scripts/docker/docker-compose.atlas.yml +76 -0
- data/scripts/docker/docker-compose.test.yml +106 -0
- data/scripts/docker/mongo-init.js +21 -0
- data/scripts/eval_mcp_with_lm_studio.rb +274 -0
- data/scripts/start-parse.sh +90 -0
- data/scripts/start_mcp_server.rb +78 -0
- data/scripts/test_server_connection.rb +82 -0
- metadata +377 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "active_model"
|
|
5
|
+
require "active_support"
|
|
6
|
+
require "active_support/inflector"
|
|
7
|
+
require "active_support/core_ext/object"
|
|
8
|
+
require "active_model/serializers/json"
|
|
9
|
+
require_relative "../client"
|
|
10
|
+
|
|
11
|
+
module Parse
|
|
12
|
+
# Find a corresponding Parse::Object subclass for this string or symbol
|
|
13
|
+
# @param className [String] The name of the Parse class as string (ex. "_User")
|
|
14
|
+
# @return [Class] The proper subclass matching the className.
|
|
15
|
+
def self.classify(className)
|
|
16
|
+
Parse::Model.find_class className.to_parse_class
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The core model of all Parse-Stack classes. This class works by providing a
|
|
20
|
+
# baseline for all subclass objects to support ActiveModel features such as
|
|
21
|
+
# serialization, dirty tracking, callbacks, etc.
|
|
22
|
+
# @see ActiveModel
|
|
23
|
+
class Model
|
|
24
|
+
include Client::Connectable # allows easy default Parse::Client access
|
|
25
|
+
include ::ActiveModel::Model
|
|
26
|
+
include ::ActiveModel::Serializers::JSON # support for JSON Serializers
|
|
27
|
+
include ::ActiveModel::Dirty # adds dirty tracking support
|
|
28
|
+
include ::ActiveModel::Conversion
|
|
29
|
+
extend ::ActiveModel::Callbacks # callback support on save, update, delete, etc.
|
|
30
|
+
extend ::ActiveModel::Naming # provides the methods for getting class names from Model classes
|
|
31
|
+
|
|
32
|
+
# Add dirty? methods as aliases for changed? methods
|
|
33
|
+
# These provide compatibility with expected API
|
|
34
|
+
def dirty?(field = nil)
|
|
35
|
+
if field.nil?
|
|
36
|
+
changed?
|
|
37
|
+
else
|
|
38
|
+
field_changed = "#{field}_changed?"
|
|
39
|
+
respond_to?(field_changed) ? send(field_changed) : false
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The name of the field in a hash that contains information about the type
|
|
44
|
+
# of data the hash represents.
|
|
45
|
+
TYPE_FIELD = "__type".freeze
|
|
46
|
+
|
|
47
|
+
# The objectId field in Parse Objects.
|
|
48
|
+
OBJECT_ID = "objectId".freeze
|
|
49
|
+
# @see OBJECT_ID
|
|
50
|
+
ID = "id".freeze
|
|
51
|
+
|
|
52
|
+
# The key field for getting class information.
|
|
53
|
+
KEY_CLASS_NAME = "className".freeze
|
|
54
|
+
# @deprecated Use OBJECT_ID instead.
|
|
55
|
+
KEY_OBJECT_ID = "objectId".freeze
|
|
56
|
+
# The key field for getting the created at date of an object hash.
|
|
57
|
+
KEY_CREATED_AT = "createdAt"
|
|
58
|
+
# The key field for getting the updated at date of an object hash.
|
|
59
|
+
KEY_UPDATED_AT = "updatedAt"
|
|
60
|
+
# The collection for Users in Parse. Used by Parse::User.
|
|
61
|
+
CLASS_USER = "_User"
|
|
62
|
+
# The collection for Installations in Parse. Used by Parse::Installation.
|
|
63
|
+
CLASS_INSTALLATION = "_Installation"
|
|
64
|
+
# The collection for revocable Sessions in Parse. Used by Parse::Session.
|
|
65
|
+
CLASS_SESSION = "_Session"
|
|
66
|
+
# The collection for Roles in Parse. Used by Parse::Role.
|
|
67
|
+
CLASS_ROLE = "_Role"
|
|
68
|
+
# The collection for to store Products (in-App purchases) in Parse. Used by Parse::Product.
|
|
69
|
+
CLASS_PRODUCT = "_Product"
|
|
70
|
+
# The collection for Audiences in Parse. Used by Parse::Audience.
|
|
71
|
+
CLASS_AUDIENCE = "_Audience"
|
|
72
|
+
# The collection for Push Status in Parse. Used by Parse::PushStatus.
|
|
73
|
+
CLASS_PUSH_STATUS = "_PushStatus"
|
|
74
|
+
# The collection for background job status in Parse. Used by Parse::JobStatus.
|
|
75
|
+
CLASS_JOB_STATUS = "_JobStatus"
|
|
76
|
+
# The collection for scheduled background jobs in Parse. Used by Parse::JobSchedule.
|
|
77
|
+
CLASS_JOB_SCHEDULE = "_JobSchedule"
|
|
78
|
+
# The internal schema collection in Parse. Managed by Parse Server.
|
|
79
|
+
CLASS_SCHEMA = "_SCHEMA"
|
|
80
|
+
# The type label for hashes containing file data. Used by Parse::File.
|
|
81
|
+
TYPE_FILE = "File"
|
|
82
|
+
# The type label for hashes containing geopoints. Used by Parse::GeoPoint.
|
|
83
|
+
TYPE_GEOPOINT = "GeoPoint"
|
|
84
|
+
# The type label for hashes containing polygons. Used by Parse::Polygon.
|
|
85
|
+
TYPE_POLYGON = "Polygon"
|
|
86
|
+
# The type label for hashes containing a Parse object. Used by Parse::Object and subclasses.
|
|
87
|
+
TYPE_OBJECT = "Object"
|
|
88
|
+
# The type label for hashes containing a Parse date object. Used by Parse::Date.
|
|
89
|
+
TYPE_DATE = "Date"
|
|
90
|
+
# The type label for hashes containing 'byte' data. Used by Parse::Bytes.
|
|
91
|
+
TYPE_BYTES = "Bytes"
|
|
92
|
+
# The type label for hashes containing ACL data. Used by Parse::ACL
|
|
93
|
+
TYPE_ACL = "ACL"
|
|
94
|
+
# The type label for hashes storing numeric data.
|
|
95
|
+
TYPE_NUMBER = "Number"
|
|
96
|
+
# The type label for hashes containing a Parse pointer.
|
|
97
|
+
TYPE_POINTER = "Pointer"
|
|
98
|
+
# The type label for hashes representing relational data.
|
|
99
|
+
TYPE_RELATION = "Relation"
|
|
100
|
+
|
|
101
|
+
# To support being able to have different ruby class names from the 'table'
|
|
102
|
+
# names used in Parse, we will need to have a dynamic lookup system where
|
|
103
|
+
# when a parse class name received, we go through all of our subclasses to determine
|
|
104
|
+
# which Parse::Object subclass is responsible for handling this Parse table class.
|
|
105
|
+
# we use @@model_cache to cache the results of the algorithm since we do this frequently
|
|
106
|
+
# when encoding and decoding objects.
|
|
107
|
+
# @!visibility private
|
|
108
|
+
@@model_cache = {}
|
|
109
|
+
|
|
110
|
+
class << self
|
|
111
|
+
# @!attribute self.raise_on_save_failure
|
|
112
|
+
# By default, we return `true` or `false` for save and destroy operations.
|
|
113
|
+
# If you prefer to have `Parse::Object` raise an exception instead, you
|
|
114
|
+
# can tell to do so either globally or on a per-model basis. When a save
|
|
115
|
+
# fails, it will raise a `Parse::RecordNotSaved`.
|
|
116
|
+
#
|
|
117
|
+
# @example
|
|
118
|
+
# Parse::Model.raise_on_save_failure = true # globally across all models
|
|
119
|
+
# Song.raise_on_save_failure = true # per-model
|
|
120
|
+
#
|
|
121
|
+
# # or per-instance raise on failure
|
|
122
|
+
# song.save!
|
|
123
|
+
#
|
|
124
|
+
# When enabled, if an error is returned by Parse due to saving or
|
|
125
|
+
# destroying a record, due to your `before_save` or `before_delete`
|
|
126
|
+
# validation cloud code triggers, `Parse::Object` will return the a
|
|
127
|
+
# `Parse::RecordNotSaved` exception type. This exception has an
|
|
128
|
+
# instance method of `#object` which contains the object that failed to save.
|
|
129
|
+
#
|
|
130
|
+
# @return [Boolean]
|
|
131
|
+
|
|
132
|
+
def raise_on_save_failure
|
|
133
|
+
@global_raise_on_save_failure ||= false
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def raise_on_save_failure=(bool)
|
|
137
|
+
@global_raise_on_save_failure = bool
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Find a Parse::Model subclass matching this type or Pares collection name.
|
|
142
|
+
# This helper method is useful to find the corresponding class ruby Parse::Object subclass that handles
|
|
143
|
+
# the provided parse class.
|
|
144
|
+
#
|
|
145
|
+
# @example
|
|
146
|
+
# Parse::Model.find_class('_User') # => Parse::User
|
|
147
|
+
# Parse::Model.find_class('_Date') # => Parse::Date
|
|
148
|
+
# Parse::Model.find_class('Installation') # => Parse::Installation
|
|
149
|
+
#
|
|
150
|
+
# class Artist < Parse::Object
|
|
151
|
+
# parse_class "Musician"
|
|
152
|
+
# end
|
|
153
|
+
#
|
|
154
|
+
# Parse::Model.find_class("Musician") # => Artist
|
|
155
|
+
#
|
|
156
|
+
# @param str [String] the class name
|
|
157
|
+
# @return [Parse::Object] a Parse::Object subclass or a specific Parse type.
|
|
158
|
+
def self.find_class(str)
|
|
159
|
+
return Parse::File if str == TYPE_FILE
|
|
160
|
+
return Parse::GeoPoint if str == TYPE_GEOPOINT
|
|
161
|
+
return Parse::Polygon if str == TYPE_POLYGON
|
|
162
|
+
return Parse::Date if str == TYPE_DATE
|
|
163
|
+
return Parse::Bytes if str == TYPE_BYTES
|
|
164
|
+
# return Parse::User if str == "User"
|
|
165
|
+
# return Parse::Installation if str == "Installation"
|
|
166
|
+
|
|
167
|
+
str = str.to_s
|
|
168
|
+
# Basically go through all Parse::Object subclasses and see who is has a parse_class
|
|
169
|
+
# set to this string. We will cache the results for future use.
|
|
170
|
+
#
|
|
171
|
+
# Anonymous descendants (`Class.new(Parse::Object)` without an
|
|
172
|
+
# assigned constant) have `model_name.name == nil`, and the default
|
|
173
|
+
# `parse_class` implementation calls `model_name.name` and raises
|
|
174
|
+
# `ActiveModel::Name: Class name cannot be blank`. An unrescued
|
|
175
|
+
# raise here poisons every subsequent `find_class` call (cf.
|
|
176
|
+
# canonical-filter lookups, hidden-class registry, ACLScope role
|
|
177
|
+
# expansion). Some tests, however, override `parse_class` on an
|
|
178
|
+
# anonymous subclass to return a literal String — those are still
|
|
179
|
+
# legitimate findables. Rescue per-descendant so the iteration
|
|
180
|
+
# continues past the unnamed-and-default-parse_class case while
|
|
181
|
+
# still considering anonymous-but-overridden ones.
|
|
182
|
+
@@model_cache[str] ||= Parse::Object.descendants.find do |f|
|
|
183
|
+
begin
|
|
184
|
+
cls = f.parse_class
|
|
185
|
+
rescue StandardError
|
|
186
|
+
next false
|
|
187
|
+
end
|
|
188
|
+
cls == str || cls == "_#{str}"
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Add extensions to the String class.
|
|
195
|
+
class String
|
|
196
|
+
# This method returns a camel-cased version of the string with the first letter
|
|
197
|
+
# of the string in lower case. This is the standard naming convention for Parse columns
|
|
198
|
+
# and property fields. This has special exception to the string "id", which returns
|
|
199
|
+
# "objectId". This is the default name filtering method for all defined properties and
|
|
200
|
+
# query keys in Parse::Query.
|
|
201
|
+
#
|
|
202
|
+
# @example
|
|
203
|
+
# "my_field".columnize # => "myField"
|
|
204
|
+
# "MyDataColumn".columnize # => "myDataColumn"
|
|
205
|
+
# "id".columnize # => "objectId" (special)
|
|
206
|
+
#
|
|
207
|
+
# @return [String]
|
|
208
|
+
# @see Parse::Query.field_formatter
|
|
209
|
+
def columnize
|
|
210
|
+
return Parse::Model::OBJECT_ID if self == Parse::Model::ID
|
|
211
|
+
u = "_".freeze
|
|
212
|
+
(first == u ? sub(u, "") : self).camelize(:lower)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Convert a string to a Parse class name. This method tries to find a
|
|
216
|
+
# responsible Parse::Object subclass that potentially matches the given string.
|
|
217
|
+
# If no match is found, it returns the camelized version of the string. This method
|
|
218
|
+
# is used internally for matching association attributes to registered
|
|
219
|
+
# Parse::Object subclasses. The method can also singularize the name before
|
|
220
|
+
# performing conversion.
|
|
221
|
+
#
|
|
222
|
+
# @example
|
|
223
|
+
# "users".to_parse_class(singularize: true) # => "_User"
|
|
224
|
+
# "users".to_parse_class # => "Users"
|
|
225
|
+
# "song_data".to_parse_class # => "SongData"
|
|
226
|
+
#
|
|
227
|
+
# @param singularize [Boolean] whether the string should be singularized first before performing conversion.
|
|
228
|
+
# @return [String] the matching Parse class for this string.
|
|
229
|
+
def to_parse_class(singularize: false)
|
|
230
|
+
final_class = singularize ? self.singularize.camelize : self.camelize
|
|
231
|
+
klass = Parse::Model.find_class(final_class) || Parse::Model.find_class(self)
|
|
232
|
+
#handles the case that a class has a custom parse table
|
|
233
|
+
final_class = klass.parse_class if klass.present?
|
|
234
|
+
final_class
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Add extensions to the Symbol class.
|
|
239
|
+
class Symbol
|
|
240
|
+
# @return [String] a lower-first-camelcased version of the symbol
|
|
241
|
+
# @see String#columnize
|
|
242
|
+
def columnize
|
|
243
|
+
to_s.columnize.to_sym
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# @see String#singularize
|
|
247
|
+
def singularize
|
|
248
|
+
to_s.singularize
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# @see String#camelize
|
|
252
|
+
def camelize
|
|
253
|
+
to_s.camelize
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# @see String#to_parse_class
|
|
257
|
+
def to_parse_class(singularize: false)
|
|
258
|
+
to_s.to_parse_class(singularize: singularize)
|
|
259
|
+
end
|
|
260
|
+
end
|