Parsecom
Yet-Another Parse.com Library written in Pure Ruby
Table of Contents generated with DocToc
- Parsecom
- Usage
- Preparing
- Declaring Parse Classes
- Objects
- Creating Objects
- Retrieving Objects
- Updating Objects
- Counters
- Arrays
- Relations
- Deleting Objects
- Batch Operations
- Queries
- Basic Queries
- Query Constraints
- Queries on Array Values
- Relational Queries
- Counting Objects
- Compound Queries
- Users
- Sign up
- Log in
- Requesting A Password Reset
- Retrieving Users
- Updating Users
- Querying
- Deleting Users
- Linking Users
- Roles
- Creating Roles
- Retrieving Roles
- Updating Roles
- Deleting Roles
- Files
- Uploading Files
- Associating with Objects
- Deleting Files
- Analytics
- App-Open Analytics
- Custom Analytics
- Installations
- Uploading Installation Data
- Retrieving Installations
- Updating Installations
- Querying Installations
- Deleting Installations
- Cloud Functions
- GeoPoints
- GeoPoint
- Geo Queries
- Security
- Debug
- Usage
Usage
Preparing
Before using the library, you should import this and set your credentials on the library.
require 'parsecom'
Parse.credentials :application_id => 'YOUR APPID', :api_key => 'YOUR APIKEY'
If you have some plan to use the master_key, please set it.
Parse.credentials :application_id => 'YOUR APPID', :api_key => 'YOUR APIKEY',
:master_key => 'YOUR MASTER KEY'
If you do not want to write your credentials on your code directly, please set environment variables:
export PARSE_APPLICATION_ID="<YOUR_APPLICATION_ID>"
export PARSE_API_KEY="<YOUR_API_KEY>"
export PARSE_MASTER_KEY="<YOUR_MASTER_KEY>"
Declaring Parse Classes
There are three ways to declare a parse class.
First, you can declare a ruby class inherited from Parse::Object. By using this way, you can add your own properties and methods to the class.
class GameScore < Parse::Object
# ..snip..
end
Secondly, you can also declare your parse class by calling the Parse::Object method.
Parse::Object(:GameScore)
It returns a parse class, so that you can call its class methods directly.
Parse::Object(:GameScore).find :limit => 3
Lastly, Parse::Object class provides create method for you to declare new class.
Parse::Object.create :GameScore
It may be suitable for writing code in declarative style.
Objects
Creating Objects
To create new parse object, just new and save the object.
game_score = GameScore.new
game_score.score = 1337
game_score.playerName = 'Sean Plott'
game_score.cheatMode = false
game_score.new? # => true
game_score.save
game_score.new? # => false
game_score.parse_object_id # => 'Ed1nuqPvcm'
Retrieving Objects
There are two ways to retrieve objects. One is using Query objects directly and another is using Parse::Object as a facade of a query object.
# useing Query object directly
query = Parse::Query.new GameScore
query.where :objectId => 'Ed1nuqPvcm'
results = query.run
# using Query object through Parse::Object
results = GameScore.find :where => {:objectId => 'Ed1nuqPvcm'}
# if you would like to find by objectId, you can easily pass it directly
result = GameScore.find_by_id 'Ed1nuqPvcm'
To fetch a child object, you can use the :include parameter.
results = GameScore.find :where => {:objectId => 'Ed1nuqPvcm'}, :include => 'game'
To know more about retrieving objects, see spec/parse_query_spec.rb
Updating Objects
To update attributes, just update the attribute and save.
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.score = 73453
game_score.save
If you want to update attributes without retrieving the object, you can use the Parse::Client object for it.
Parse::Client.default.update :GaemScore, 'Ed1nuqPvcm', :score => 73453
Counters
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.score = Parse::Op::Increment.new 1
game_score.save
Arrays
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.skils = Parse::Op::AddUnique.new 'flying', 'kungfu'
game_score.save
Relations
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.opponents = Parse::Op::AddRelation.new player.pointer
game_score.save
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.opponents = Parse::Op::RemoveRelation.new player.pointer
game_score.save
Deleting Objects
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.delete
game_score = GameScore.find_by_id 'Ed1nuqPvcm'
game_score.opponents = Parse::Op::Delete.new
game_score.save
Batch Operations
seans_score = GameScore.new 'score' => 1337, 'playerName' => 'Sean Plott'
zerocools_score = GameScore.new 'score' => 1338, 'playerName' => 'ZeroCool'
batch = Parse::Batch.new
batch.add_request do
seans_score.save
zerocools_score.save
end
result = batch.run
Or
seans_score = GameScore.new 'score' => 1337, 'playerName' => 'Sean Plott'
zerocools_score = GameScore.new 'score' => 1338, 'playerName' => 'ZeroCool'
Parse.batch do
seans_score.save
zerocools_score.save
end
Queries
Basic Queries
game_scores = GameScore.find :all
Query Constraints
game_scores = GameScore.find :where => {"playerName" => "Sean Plott", "cheatMode" => false}
game_scores = GameScore.find :where => proc {
column(:score).gte(1000).lte(3000)
}
game_scores = GameScore.find :where => proc {
column(:score).between(1000..3000)
}
game_scores = GameScore.find :where => proc {
column(:score).in(1, 3, 5, 7, 9)
}
game_scores = GameScore.find :where => proc {
column(:playerName).nin("Jonathan Walsh", "Dario Wunsch", "Shawn Simon")
}
game_scores = GameScore.find :where => proc {
column(:score).exists
}
game_scores = GameScore.find :where => proc {
column(:score).exists(false)
}
game_scores = GameScore.find :where => proc {
subquery = subquery_for :Team
subquery.where {column(:winPct).gt(0.5)}
subquery.key = 'city'
column(:hometown).select(subquery)
}
game_scores = GameScore.find :order => 'score'
game_scores = GameScore.find :order => '-score'
game_scores = GameScore.find :order_desc => 'score'
game_scores = GameScore.find :order => ['score', '-name']
game_scores = GameScore.find :limit => 200, :skip => 400
game_scores = GameScore.find :keys => ['score', 'playerName']
Queries on Array Values
game_scores = GameScore.find :where => proc {
column(:arrayKey).contains(2)
}
game_scores = GameScore.find :where => proc {
column(:arrayKey).all(2, 3, 4)
}
Relational Queries
game_scores = GameScore.find :where => proc {
post = Parse::Object(:Post).new :objectId => '8TOXdXf3tz'
column(:post).eq(post)
}
game_scores = GameScore.find :where => proc {
subquery = subquery_for :Post
subquery.where do
column(:image).exists(true)
end
column(:post).in_query(subquery)
}
game_scores = GameScore.find :where => proc {
pointer = Parse::Pointer.new('className' => 'Post', 'objectId' => '8TOXdXf3tz')
related_to :likes, pointer
}
Counting Objects
game_score_count = GameScore.count 'playerName' => 'Jonathan Walsh'
Compound Queries
game_scores = GameScore.find :where => proc {
or_condition column(:wins).gt(150), column(:wins).lt(5)
}
Users
Sign up
user = Parse::User.sign_up 'YOUR USERNAME', 'YOUR PASSWORD'
Log in
user = Parse::User.log_in 'YOUR USERNAME', 'YOUR PASSWORD'
Requesting A Password Reset
Parse::User.request_password_reset 'your@email.address'
Retrieving Users
user = Parse::User.find_by_id :g7y9tkhB7O
Updating Users
user = Parse::User.find_by_id :g7y9tkhB7O
user.phone = '415-369-6201'
user.save
Querying
users = Parse::User.find :all
Deleting Users
user = Parse::User.find_by_id :g7y9tkhB7O
user.delete
Linking Users
TBD
Roles
Creating Roles
moderator = Parse::Role.new 'name' => 'Moderators', 'ACL' => Parse::ACL::PUBLIC_READ_ONLY
moderator.save
moderator = Parse::Role.new 'name' => 'Moderators', 'ACL' => Parse::ACL::PUBLIC_READ_ONLY
moderator.roles.add Parse::Role.new('objectId' => 'Ed1nuqPvc')
moderator.users.add Parse::User.new('objectId' => '8TOXdXf3tz')
moderator.save
Retrieving Roles
role = Parse::Role.find_by_id 'mrmBZvsErB'
role.name # => 'Moderators'
role.ACL.readable? '*' # => true
role.ACL.writable? 'role:Administrators' # => true
Updating Roles
user1 = Parse::User.new 'objectId' => '8TOXdXf3tz'
user2 = Parse::User.new 'objectId' => 'g7y9tkhB7O'
role = Parse::Role.find_by_id 'mrmBZvsErB'
role.users = Parse::Op::AddRelation.new user1.pointer, user2.pointer
role.save
removed_role = Parse::Role.new 'objectId' => 'Ed1nuqPvc'
role = Parse::Role.find_by_id 'mrmBZvsErB'
role.roles = Parse::Op::RemoveRelation.new removed_role.pointer
role.save
Deleting Roles
role = Parse::Role.find_by_id 'mrmBZvsErB'
role.delete
Files
Uploading Files
file = Parse::ParseFile.new :name => 'hello.txt', :content => 'Hello, World!'
file.save
file.url # => "http://files.parse.com/7883...223/7480...b6d-hello.txt"
file = Parse::ParseFile.new :name => 'myPicture.jpg', :content => './myPicture.jpg'
file.save
file.url # => "http://files.parse.com/7883...223/81c7...bdf-myPicture.jpg"
Associating with Objects
file = Parse::ParseFile.new :name => 'profile.png', :content => './profile.png'
profile = PlayerProfile.new 'name' => 'Andrew', 'picture' => file
profile.save
Deleting Files
file.delete!
Analytics
App-Open Analytics
app_opened_event = Parse::Event::AppOpened.new :at => '2013-10-18T20:53:25Z'
app_opened_event.fire
Parse::Event::AppOpened.fire :at => '2013-10-18T20:53:25Z'
Custom Analytics
Parse::Event.create :Search
search_event = Search.new :at => '2013-10-18T20:53:25Z',
:priceRange => "1000-1500", :source => "craigslist", :dayType => "weekday"
search_event.fire
error_event = Parse::Event::Error.new :at => '2013-10-18T20:53:25Z', :code => 404
error_event.fire
Push Notifications
TBD
Installations
Uploading Installation Data
installation = Parse::Installation.new :deviceType => 'ios', :deviceToken => '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', :channels => ['']
installation.save
Retrieving Installations
installation = Parse::Installation.find_by_id :mrmBZvsErB
Updating Installations
installation = Parse::Installation.find_by_id :mrmBZvsErB
installation.channels = ['', 'foo']
installation.save
Querying Installations
installations = Parse::Installation.find! :all
Deleting Installations
installation = Parse::Installation.find_by_id :mrmBZvsErB
installation.delete!
Cloud Functions
client = Parse::Client.new
client.hello
GeoPoints
GeoPoint
geo_point = Parse::GeoPoint.new :latitude => 40.0, :longitude => -30.0
place = PlaceObject.new :location => geo_point
Geo Queries
place = PlaceObject.find :limit => 10, :where => proc {
geo_point = Parse::GeoPoint.new :latitude => 30.0, :longitude => -20.0
column(:location).near_sphere geop_point
}
places = PlaceObject.find :limit => 10, :where => proc {
geo_point = Parse::GeoPoint.new :latitude => 30.0, :longitude => -20.0
column(:location).near_sphere(geo_point).max_distance_in_miles(10.0)
}
places = PizzaPlaceObject.find :limit => 10, :where => proc {
southwest = Parse::GeoPoint.new :latitude => 37.71, :longitude => -122.53
northeast = Parse::GeoPoint.new :latitude => 30.82, :longitude => -122.37
column(:location).within(southwest, northeast)
}
Security
If you add an exclamation mark, "!" after the method name, the method is executed by using the master key.
class_a = ClassA.new :columnA => 'Hello, parse.com'
class_a.save!
If you want to use the master key for all API calls, set the use_master_key flag true so that you don't need to add "!" for all methods.
Parse.use_master_key!
Debug
To see debug output, set $DEBUG true.
$DEBUG = true
Post.find :all
You can see something like the following in $stderr.
opening connection to api.parse.com...
opened
<- "GET /1/classes/Post? HTTP/1.1\r\nX-Parse-Application-Id: abcdefghijklmnopqrstuvwxyz0123456789ABCD\r\nContent-Type: application/json\r\nAccept: application/json\r\nUser-Agent: A parse.com client for ruby\r\nX-Parse-Rest-Api-Key: abcdefghijklmnopqrstuvwxyz0123456789ABCD\r\nHost: api.parse.com\r\n\r\n"
-> "HTTP/1.1 200 OK\r\n"
-> "Access-Control-Allow-Origin: *\r\n"
-> "Access-Control-Request-Method: *\r\n"
-> "Cache-Control: max-age=0, private, must-revalidate\r\n"
-> "Content-Type: application/json; charset=utf-8\r\n"
-> "Date: Sun, 08 Dec 2013 08:14:40 GMT\r\n"
-> "ETag: \"abcdefghijklmnopqrstuvwxyz012345\"\r\n"
-> "Server: nginx/1.4.2\r\n"
-> "Set-Cookie: _parse_session=abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789; domain=.parse.com; path=/; expires=Tue, 07-Jan-2014 08:14:40 GMT; secure; HttpOnly\r\n"
-> "Status: 200 OK\r\n"
-> "X-Runtime: 0.116322\r\n"
-> "X-UA-Compatible: IE=Edge,chrome=1\r\n"
-> "Content-Length: 603\r\n"
-> "Connection: keep-alive\r\n"
-> "\r\n"
reading 603 bytes...
-> "{\"results\":[{\"author\":{\"__type\":\"Pointer\",\"className\":\"_User\",\"objectId\":\"xWJVfYPbBP\"},\"body\":\"\xE6\x9C\xAC\xE6\x96\x87\",\"title\":\"\xE3\x82\xBF\xE3\x82\xA4\xE3\x83\x88
\xE3\x83\xAB\",\"comments\":{\"__type\":\"Relation\",\"className\":\"Comment\"},\"createdAt\":\"2013-10-29T15:06:45.872Z\",\"updatedAt\":\"2013-10-29T15:09:01.111Z\",\"objectId\":\"6EyX2aypgD\"
},{\"comments\":{\"__type\":\"Relation\",\"className\":\"Comment\"},\"createdAt\":\"2013-10-30T04:38:47.068Z\",\"updatedAt\":\"2013-10-30T04:38:47.068Z\",\"objectId\":\"njvHr4aelZ\"},{\"comment
s\":{\"__type\":\"Relation\",\"className\":\"Comment\"},\"createdAt\":\"2013-10-30T04:40:37.397Z\",\"updatedAt\":\"2013-10-30T04:40:37.397Z\",\"objectId\":\"EDdGtur3vY\"}]}"
read 603 bytes
Conn keep-alive
Also you can do dry-run.
Parse.dry_run!
Post.find :all
This does not call any API and shows something like the following in $stderr.
get /1/classes/Post?
X-Parse-Application-Id: abcdefghijklmnopqrstuvwxyz0123456789ABCD
Content-Type: application/json
Accept: application/json
User-Agent: A parse.com client for ruby
X-Parse-REST-API-Key: abcdefghijklmnopqrstuvwxyz0123456789ABCD