tagcrumbs 0.3.1
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.
- data/History.txt +9 -0
- data/License.txt +22 -0
- data/Manifest.txt +177 -0
- data/PostInstall.txt +2 -0
- data/README.rdoc +45 -0
- data/Rakefile +35 -0
- data/TODO.txt +17 -0
- data/bin/tagcrumbs +5 -0
- data/examples/address_update.rb +15 -0
- data/examples/comment_new.rb +19 -0
- data/examples/favorite_new.rb +17 -0
- data/examples/filter_new.rb +15 -0
- data/examples/friendship_create.rb +19 -0
- data/examples/link_new.rb +16 -0
- data/examples/location_update.rb +16 -0
- data/examples/picture_update.rb +16 -0
- data/examples/placemark_new_simple.rb +24 -0
- data/examples/placemark_new_suggestions.rb +24 -0
- data/examples/profile_link_new.rb +14 -0
- data/examples/profile_update.rb +12 -0
- data/examples/request_authorization.rb +25 -0
- data/examples/settings_update.rb +12 -0
- data/examples/subscription_new.rb +15 -0
- data/examples/tagcrumbs_find.rb +25 -0
- data/examples/tagcrumbs_search.rb +7 -0
- data/examples/user.rb +28 -0
- data/examples/user_recommendation_new.rb +15 -0
- data/lib/tagcrumbs/builders/builder.rb +45 -0
- data/lib/tagcrumbs/builders/json_builder.rb +38 -0
- data/lib/tagcrumbs/builders/xml_builder.rb +30 -0
- data/lib/tagcrumbs/cli.rb +268 -0
- data/lib/tagcrumbs/config_store.rb +35 -0
- data/lib/tagcrumbs/exceptions.rb +13 -0
- data/lib/tagcrumbs/node.rb +43 -0
- data/lib/tagcrumbs/parsers/json_parser.rb +79 -0
- data/lib/tagcrumbs/parsers/parser.rb +24 -0
- data/lib/tagcrumbs/parsers/xml_parser.rb +54 -0
- data/lib/tagcrumbs/proxy.rb +32 -0
- data/lib/tagcrumbs/requestor.rb +140 -0
- data/lib/tagcrumbs/resources/array.rb +108 -0
- data/lib/tagcrumbs/resources/models/accessors.rb +252 -0
- data/lib/tagcrumbs/resources/models/activity.rb +19 -0
- data/lib/tagcrumbs/resources/models/address.rb +16 -0
- data/lib/tagcrumbs/resources/models/city.rb +13 -0
- data/lib/tagcrumbs/resources/models/comment.rb +12 -0
- data/lib/tagcrumbs/resources/models/country.rb +15 -0
- data/lib/tagcrumbs/resources/models/fanship.rb +12 -0
- data/lib/tagcrumbs/resources/models/favorite.rb +22 -0
- data/lib/tagcrumbs/resources/models/filter.rb +32 -0
- data/lib/tagcrumbs/resources/models/flag.rb +10 -0
- data/lib/tagcrumbs/resources/models/friendship.rb +12 -0
- data/lib/tagcrumbs/resources/models/geoname.rb +8 -0
- data/lib/tagcrumbs/resources/models/link.rb +13 -0
- data/lib/tagcrumbs/resources/models/location.rb +13 -0
- data/lib/tagcrumbs/resources/models/model.rb +148 -0
- data/lib/tagcrumbs/resources/models/picture.rb +28 -0
- data/lib/tagcrumbs/resources/models/place.rb +17 -0
- data/lib/tagcrumbs/resources/models/placemark.rb +30 -0
- data/lib/tagcrumbs/resources/models/profile.rb +16 -0
- data/lib/tagcrumbs/resources/models/profile_link.rb +12 -0
- data/lib/tagcrumbs/resources/models/root.rb +19 -0
- data/lib/tagcrumbs/resources/models/settings.rb +14 -0
- data/lib/tagcrumbs/resources/models/state.rb +14 -0
- data/lib/tagcrumbs/resources/models/subscription.rb +13 -0
- data/lib/tagcrumbs/resources/models/suggestions.rb +11 -0
- data/lib/tagcrumbs/resources/models/tag.rb +6 -0
- data/lib/tagcrumbs/resources/models/tagcrumb.rb +58 -0
- data/lib/tagcrumbs/resources/models/user.rb +101 -0
- data/lib/tagcrumbs/resources/models/user_recommendation.rb +18 -0
- data/lib/tagcrumbs/resources/resource.rb +76 -0
- data/lib/tagcrumbs/validations.rb +301 -0
- data/lib/tagcrumbs.rb +232 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/fixtures/activity.json +210 -0
- data/spec/fixtures/activity.xml +66 -0
- data/spec/fixtures/address.json +183 -0
- data/spec/fixtures/address.xml +58 -0
- data/spec/fixtures/city.json +88 -0
- data/spec/fixtures/city.xml +34 -0
- data/spec/fixtures/comment.json +286 -0
- data/spec/fixtures/comment.xml +87 -0
- data/spec/fixtures/country.json +32 -0
- data/spec/fixtures/country.xml +13 -0
- data/spec/fixtures/fanship.json +180 -0
- data/spec/fixtures/fanship.xml +54 -0
- data/spec/fixtures/favorite.json +332 -0
- data/spec/fixtures/favorite.xml +109 -0
- data/spec/fixtures/filter.json +243 -0
- data/spec/fixtures/filter.xml +80 -0
- data/spec/fixtures/friendship.json +180 -0
- data/spec/fixtures/friendship.xml +54 -0
- data/spec/fixtures/geoname.json +18 -0
- data/spec/fixtures/geoname.xml +6 -0
- data/spec/fixtures/json_parser.json +25 -0
- data/spec/fixtures/link.json +288 -0
- data/spec/fixtures/link.xml +88 -0
- data/spec/fixtures/location.json +204 -0
- data/spec/fixtures/location.xml +71 -0
- data/spec/fixtures/picture.json +154 -0
- data/spec/fixtures/picture.png +0 -0
- data/spec/fixtures/picture.xml +49 -0
- data/spec/fixtures/placemark.json +357 -0
- data/spec/fixtures/placemark.xml +58 -0
- data/spec/fixtures/placemarks.json +887 -0
- data/spec/fixtures/placemarks.xml +348 -0
- data/spec/fixtures/profile.json +282 -0
- data/spec/fixtures/profile.xml +100 -0
- data/spec/fixtures/profile_link.json +156 -0
- data/spec/fixtures/profile_link.xml +49 -0
- data/spec/fixtures/root.json +46 -0
- data/spec/fixtures/root.xml +14 -0
- data/spec/fixtures/settings.json +147 -0
- data/spec/fixtures/settings.xml +45 -0
- data/spec/fixtures/state.json +62 -0
- data/spec/fixtures/state.xml +23 -0
- data/spec/fixtures/subscription.json +283 -0
- data/spec/fixtures/subscription.xml +86 -0
- data/spec/fixtures/suggestions.json +1877 -0
- data/spec/fixtures/suggestions.xml +724 -0
- data/spec/fixtures/tag.json +9 -0
- data/spec/fixtures/tag.xml +4 -0
- data/spec/fixtures/user.json +105 -0
- data/spec/fixtures/user.xml +31 -0
- data/spec/fixtures/user_recommendation.json +349 -0
- data/spec/fixtures/user_recommendation.xml +106 -0
- data/spec/fixtures/validation_errors.json +5 -0
- data/spec/fixtures/validation_errors.xml +5 -0
- data/spec/fixtures/xml_parser.xml +13 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +75 -0
- data/spec/tagcrumbs/builders/builder_spec.rb +57 -0
- data/spec/tagcrumbs/builders/json_builder_spec.rb +47 -0
- data/spec/tagcrumbs/builders/xml_builder_spec.rb +34 -0
- data/spec/tagcrumbs/exceptions_spec.rb +16 -0
- data/spec/tagcrumbs/node_spec.rb +42 -0
- data/spec/tagcrumbs/parsers/json_parser_spec.rb +117 -0
- data/spec/tagcrumbs/parsers/parser_spec.rb +25 -0
- data/spec/tagcrumbs/parsers/xml_parser_spec.rb +117 -0
- data/spec/tagcrumbs/proxy_spec.rb +48 -0
- data/spec/tagcrumbs/requestor_spec.rb +62 -0
- data/spec/tagcrumbs/resources/array_spec.rb +62 -0
- data/spec/tagcrumbs/resources/models/accessors_spec.rb +123 -0
- data/spec/tagcrumbs/resources/models/activity_spec.rb +33 -0
- data/spec/tagcrumbs/resources/models/address_spec.rb +24 -0
- data/spec/tagcrumbs/resources/models/city_spec.rb +33 -0
- data/spec/tagcrumbs/resources/models/comment_spec.rb +23 -0
- data/spec/tagcrumbs/resources/models/country_spec.rb +26 -0
- data/spec/tagcrumbs/resources/models/fanship_spec.rb +28 -0
- data/spec/tagcrumbs/resources/models/favorite_spec.rb +28 -0
- data/spec/tagcrumbs/resources/models/filter_spec.rb +43 -0
- data/spec/tagcrumbs/resources/models/flag_spec.rb +5 -0
- data/spec/tagcrumbs/resources/models/friendship_spec.rb +28 -0
- data/spec/tagcrumbs/resources/models/geoname_spec.rb +18 -0
- data/spec/tagcrumbs/resources/models/link_spec.rb +24 -0
- data/spec/tagcrumbs/resources/models/location_spec.rb +28 -0
- data/spec/tagcrumbs/resources/models/model_spec.rb +27 -0
- data/spec/tagcrumbs/resources/models/picture_spec.rb +42 -0
- data/spec/tagcrumbs/resources/models/place_spec.rb +12 -0
- data/spec/tagcrumbs/resources/models/placemark_spec.rb +61 -0
- data/spec/tagcrumbs/resources/models/profile_link_spec.rb +29 -0
- data/spec/tagcrumbs/resources/models/profile_spec.rb +43 -0
- data/spec/tagcrumbs/resources/models/root_spec.rb +57 -0
- data/spec/tagcrumbs/resources/models/settings_spec.rb +32 -0
- data/spec/tagcrumbs/resources/models/state_spec.rb +30 -0
- data/spec/tagcrumbs/resources/models/subscription_spec.rb +28 -0
- data/spec/tagcrumbs/resources/models/suggestions_spec.rb +33 -0
- data/spec/tagcrumbs/resources/models/tag_spec.rb +16 -0
- data/spec/tagcrumbs/resources/models/tagcrumb_spec.rb +21 -0
- data/spec/tagcrumbs/resources/models/user_recommendation_spec.rb +35 -0
- data/spec/tagcrumbs/resources/models/user_spec.rb +128 -0
- data/spec/tagcrumbs/resources/resource_spec.rb +62 -0
- data/spec/tagcrumbs/validations_spec.rb +27 -0
- data/spec/tagcrumbs_spec.rb +103 -0
- data/tagcrumbs.gemspec +59 -0
- data/tasks/rspec.rake +21 -0
- metadata +327 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# A Placemark can contain many Links.
|
|
3
|
+
class Link < Model
|
|
4
|
+
can_be :created, :updated, :destroyed
|
|
5
|
+
|
|
6
|
+
writeable_attributes :url, :link_type
|
|
7
|
+
readable_attributes :title, :created_at, :updated_at
|
|
8
|
+
|
|
9
|
+
has_one :tagcrumb, :modifiable => true
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# The current Location of the user. It can only be updated. This location is the default value for all queries that
|
|
3
|
+
# take your current location into account.
|
|
4
|
+
class Location < Model
|
|
5
|
+
can_be :updated
|
|
6
|
+
|
|
7
|
+
writeable_attributes :latitude, :longitude
|
|
8
|
+
|
|
9
|
+
has_one :user
|
|
10
|
+
has_one :city
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# The base class for all Models that can be read, created, destroyed or updated.
|
|
3
|
+
|
|
4
|
+
class Model < Resource
|
|
5
|
+
include Tagcrumbs::Accessors
|
|
6
|
+
include Validations
|
|
7
|
+
|
|
8
|
+
attr_accessor :new_record
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def initialize(attributes ={})
|
|
12
|
+
reset!
|
|
13
|
+
|
|
14
|
+
self.attributes = attributes
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Reset the object to a blank state
|
|
18
|
+
def reset!
|
|
19
|
+
super
|
|
20
|
+
self.new_record = true
|
|
21
|
+
@nodes = @nodes_updates = {}
|
|
22
|
+
@errors = Errors.new(self) # reset errors from server
|
|
23
|
+
restore!
|
|
24
|
+
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Is this a new record or was it loaded from the web service
|
|
29
|
+
def new_record?
|
|
30
|
+
self.new_record ? true : false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Save the object
|
|
34
|
+
def save
|
|
35
|
+
new_record? ? create : update
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Create a new object by posting a representation of the resource to the create_url
|
|
39
|
+
def create
|
|
40
|
+
raise CreateImpossible unless can_be?(:created)
|
|
41
|
+
raise CreateURLMissing unless create_url.present?
|
|
42
|
+
return false unless new_record?
|
|
43
|
+
requestor.post(create_url, to_format)
|
|
44
|
+
handle_save_response
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Update an existing object by puting a representation of the resource to the resource_url
|
|
48
|
+
def update
|
|
49
|
+
raise UpdateImpossible unless can_be?(:updated)
|
|
50
|
+
raise ResourceURLMissing unless resource_url.present?
|
|
51
|
+
return false if new_record?
|
|
52
|
+
requestor.put(resource_url, to_format)
|
|
53
|
+
handle_save_response
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Remove an existing object from the server by sending a delete request to the server
|
|
57
|
+
def destroy
|
|
58
|
+
raise DestroyImpossible unless can_be?(:destroyed)
|
|
59
|
+
return false if new_record?
|
|
60
|
+
|
|
61
|
+
requestor.delete(resource_url)
|
|
62
|
+
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Output the resource in the current active format
|
|
67
|
+
def to_format(format = Tagcrumbs.options[:format], options={})
|
|
68
|
+
case format
|
|
69
|
+
when :xml: to_xml(options)
|
|
70
|
+
when :json: to_json(options)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Return the object in a XML representation
|
|
75
|
+
def to_xml(options = {})
|
|
76
|
+
options.reverse_merge!(:modifiable_only => true)
|
|
77
|
+
Tagcrumbs::XmlBuilder.new(self).build(options)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Return the object in a JSON representation
|
|
81
|
+
def to_json(options = {})
|
|
82
|
+
options.reverse_merge!(:modifiable_only => true, :badgerfish => false)
|
|
83
|
+
Tagcrumbs::JsonBuilder.new(self).build(options)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Load the attributes and has_one and has_many associations.
|
|
89
|
+
# The Resource attributes are loaded in the superclass.
|
|
90
|
+
def initialize_from_document(parser, format = Tagcrumbs.options[:format])
|
|
91
|
+
parser = super
|
|
92
|
+
|
|
93
|
+
self.new_record = false
|
|
94
|
+
|
|
95
|
+
if self.loaded? # only if there actually is content
|
|
96
|
+
self.class.attributes.each do |name| # load all attributes
|
|
97
|
+
node = parser.get_node(name)
|
|
98
|
+
|
|
99
|
+
if node
|
|
100
|
+
node_parser = Parser.new_for_format(parser.get_node(name), parser.format)
|
|
101
|
+
self.nodes[name] = Node.new(name, node_parser.get_value, node_parser.get_attributes)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
self.class.has_one_associations_options.keys.each do |name| # load all has_one associations
|
|
106
|
+
has_one_element = parser.get_node(self.class.has_one_associations_options[name][:node_name])
|
|
107
|
+
|
|
108
|
+
if has_one_element
|
|
109
|
+
has_one_parser = Parser.new_for_format(has_one_element, parser.format)
|
|
110
|
+
|
|
111
|
+
self.has_one_associations[name] = Tagcrumbs.class_by_type(has_one_parser.get_attribute('type')).new_from_document(has_one_element, parser.format)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
self.class.has_many_associations_options.keys.each do |name| # load all has_many associations
|
|
116
|
+
has_many_element = parser.get_node(self.class.has_many_associations_options[name][:node_name])
|
|
117
|
+
|
|
118
|
+
if has_many_element
|
|
119
|
+
self.has_many_associations[name] = Tagcrumbs::Array.new_from_document(has_many_element, parser.format)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
parser
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Just like new, but directly save the object to the webservice
|
|
128
|
+
def self.create(args={})
|
|
129
|
+
# TODO_SK: test this
|
|
130
|
+
model = new(args)
|
|
131
|
+
model.create
|
|
132
|
+
model
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
# Handle the response after a create or update and set the errors if needed.
|
|
137
|
+
def handle_save_response
|
|
138
|
+
if requestor.response.code == '422'
|
|
139
|
+
errors.from_format(requestor.response.body, requestor.response_format)
|
|
140
|
+
false
|
|
141
|
+
else
|
|
142
|
+
initialize_from_document(requestor.response.body)
|
|
143
|
+
true
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# Each User has a Picture associated with him/her.
|
|
3
|
+
# There is a default Picture for every user that can only be updated and not destroyed.
|
|
4
|
+
# However, an uploaded Picture of a User can be destroyed which will set the Picture
|
|
5
|
+
# to the default Picture again.
|
|
6
|
+
class Picture < Model
|
|
7
|
+
can_be :updated, :destroyed
|
|
8
|
+
|
|
9
|
+
writeable_attributes :picture_file
|
|
10
|
+
readable_attributes :url, :small_thumbnail_url, :medium_thumbnail_url, :content_type, :created_at, :updated_at
|
|
11
|
+
|
|
12
|
+
has_one :profile
|
|
13
|
+
|
|
14
|
+
# Load a file from the local filesystem and set the attributes.
|
|
15
|
+
# Save the object to upload a new profile picture to the server.
|
|
16
|
+
def get_file(filename)
|
|
17
|
+
return if filename.blank?
|
|
18
|
+
|
|
19
|
+
self.picture_file = {
|
|
20
|
+
:filename => File.basename(filename),
|
|
21
|
+
:mime_type => MIME::Types.type_for(filename).first.content_type,
|
|
22
|
+
:content => Base64.encode64(File.read(filename))
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# The superclass for City, State and Country
|
|
3
|
+
# All of them contain a name and a permalink.
|
|
4
|
+
# The name is automatically translated into the locale that was set by the user
|
|
5
|
+
# in the settings.
|
|
6
|
+
class Place < Model
|
|
7
|
+
readable_attributes :name, :permalink
|
|
8
|
+
|
|
9
|
+
has_one :geoname
|
|
10
|
+
|
|
11
|
+
def self.search(q, args={})
|
|
12
|
+
args.assert_valid_keys(:page, :per_page, :for)
|
|
13
|
+
|
|
14
|
+
Array.load(Tagcrumbs.root.place_search_url, args.merge(:q => q))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# The main object in the webservice. A Placemark describes a place on earth.
|
|
3
|
+
# It has many link, comments and can be recommended to your friends.
|
|
4
|
+
class Placemark < Tagcrumb
|
|
5
|
+
can_be :created, :updated, :destroyed
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
writeable_attributes :name, :notes, :private, :latitude, :longitude, :tag_list, :guess_city, :address_attributes
|
|
9
|
+
readable_attributes :created_at, :updated_at, :short_url, :permalink, :favorites_count
|
|
10
|
+
|
|
11
|
+
has_one :user
|
|
12
|
+
has_one :city, :modifiable => true
|
|
13
|
+
has_one :address
|
|
14
|
+
|
|
15
|
+
has_many :links
|
|
16
|
+
has_many :comments
|
|
17
|
+
has_many :recommendations
|
|
18
|
+
|
|
19
|
+
# Find Placemarks by specifying find criteria.
|
|
20
|
+
def self.find(args={})
|
|
21
|
+
super(args.merge(:tagcrumb_type => :placemark))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Load suggested names, cities and tags that can be shown to the user on the creation of a new Placemark
|
|
25
|
+
def suggestions
|
|
26
|
+
Suggestions.load(Tagcrumbs.current_user.suggestions_url, {:latitude => self.latitude, :longitude => self.longitude}) if self.latitude.present? && self.longitude.present?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# Each User has Profile. A Profile can only be updated, it is created automatically with a User and destroyed if the User
|
|
3
|
+
# decides to leave Tagcrumbs.
|
|
4
|
+
class Profile < Model
|
|
5
|
+
can_be :updated
|
|
6
|
+
|
|
7
|
+
writeable_attributes :fullname, :about, :description
|
|
8
|
+
readable_attributes :created_at, :updated_at
|
|
9
|
+
|
|
10
|
+
has_one :user
|
|
11
|
+
has_one :city, :modifiable => true
|
|
12
|
+
has_one :picture
|
|
13
|
+
|
|
14
|
+
has_many :profile_links
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# Each User can set multiple ProfileLinks
|
|
3
|
+
# e.g. his Facebook account, blog, website etc.
|
|
4
|
+
class ProfileLink < Model
|
|
5
|
+
can_be :created, :updated, :destroyed
|
|
6
|
+
|
|
7
|
+
writeable_attributes :url, :link_type
|
|
8
|
+
readable_attributes :created_at, :updated_at
|
|
9
|
+
|
|
10
|
+
has_one :profile
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# The Root Object that contains links to all other resources on tagcrumbs.com.
|
|
3
|
+
# It is used as the starting point for many other queries.
|
|
4
|
+
class Root < Model
|
|
5
|
+
has_one :you
|
|
6
|
+
has_one :location
|
|
7
|
+
|
|
8
|
+
has_many :tagcrumbs
|
|
9
|
+
has_many :nearby_tagcrumbs
|
|
10
|
+
has_many :countries
|
|
11
|
+
|
|
12
|
+
has_many :popular_countries
|
|
13
|
+
has_many :tags
|
|
14
|
+
has_many :users
|
|
15
|
+
|
|
16
|
+
has_many :search
|
|
17
|
+
has_many :place_search
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# Each user has a Settings object that can be updated
|
|
3
|
+
class Settings < Model
|
|
4
|
+
can_be :updated
|
|
5
|
+
|
|
6
|
+
readable_attributes :created_at, :updated_at
|
|
7
|
+
writeable_attributes :locale, :unit_system, :notification_fan, :notification_recommendation, :newsletter, :facebook_new_placemark_feed,
|
|
8
|
+
:facebook_new_favorite_feed, :facebook_new_comment_feed
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
has_one :user
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# A State is a Place and connects Countries and Cities.
|
|
3
|
+
class State < Place
|
|
4
|
+
|
|
5
|
+
has_one :country
|
|
6
|
+
has_many :cities
|
|
7
|
+
|
|
8
|
+
# Search a State by name
|
|
9
|
+
def self.search(q, args={})
|
|
10
|
+
super(q, args.merge(:for => :state))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# A Subscription is used to get updates of Placemarks
|
|
3
|
+
class Subscription < Model
|
|
4
|
+
can_be :created, :updated, :destroyed
|
|
5
|
+
|
|
6
|
+
readable_attributes :created_at, :updated_at
|
|
7
|
+
|
|
8
|
+
has_one :user
|
|
9
|
+
has_one :tagcrumb, :modifiable => true
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# Tagcrumb is the superclass for Placemark and Favorite, they are both a "Tagcrumb" as well
|
|
3
|
+
class Tagcrumb < Model
|
|
4
|
+
# Find Tagcrumbs by specifying filter criteria.
|
|
5
|
+
def self.find(args={})
|
|
6
|
+
args.assert_valid_keys(
|
|
7
|
+
:from, # from: you, friends, fans, recommendations, everybody, user
|
|
8
|
+
:username, # name of the user
|
|
9
|
+
:tags, # comma separates tag list
|
|
10
|
+
:tagcrumb_type, # Placemarks, Favorite or both?
|
|
11
|
+
:city, :state, :country, :middle_of_nowhere, # filter by the place hierarchy
|
|
12
|
+
:within, # within a certain radius
|
|
13
|
+
:latitude, :longitude, # per default within is the current location, can be overwritten with latitude and longitude
|
|
14
|
+
:bbox, # everything between a bounding box
|
|
15
|
+
:since, :until, # filter by time
|
|
16
|
+
:per_page, :page, :sort, :order # filter options
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
Array.load(Tagcrumbs.root.tagcrumbs_url, typecast_and_validate_query_parameters(args))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Use a fulltext search to find Tagcrumbs.
|
|
23
|
+
# This is different from "finding" by filter criteria
|
|
24
|
+
def self.search(args={})
|
|
25
|
+
args.assert_valid_keys(:q, :from, :l, :w, :page, :per_page)
|
|
26
|
+
|
|
27
|
+
Array.load(Tagcrumbs.root.search_url, typecast_and_validate_query_parameters(args))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def self.typecast_and_validate_query_parameters(args)
|
|
32
|
+
query_args = {}
|
|
33
|
+
|
|
34
|
+
args.each do |key, value|
|
|
35
|
+
query_args[key] = case key
|
|
36
|
+
when :from, :w: value.to_sym
|
|
37
|
+
when :tagcrumb_type: value.to_s.capitalize
|
|
38
|
+
when :since, :until: value.iso8601
|
|
39
|
+
else
|
|
40
|
+
value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Tagcrumbs.validate(key, query_args[key])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
query_args
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# The main actor in the webservice.
|
|
3
|
+
class User < Model
|
|
4
|
+
readable_attributes :username, :created_at, :updated_at
|
|
5
|
+
|
|
6
|
+
has_one :profile
|
|
7
|
+
has_one :picture
|
|
8
|
+
has_one :settings
|
|
9
|
+
has_one :location
|
|
10
|
+
has_one :suggestions
|
|
11
|
+
|
|
12
|
+
has_many :tagcrumbs
|
|
13
|
+
has_many :placemarks
|
|
14
|
+
has_many :favorites
|
|
15
|
+
|
|
16
|
+
has_many :profile_links
|
|
17
|
+
|
|
18
|
+
has_many :fanships
|
|
19
|
+
has_many :friendships
|
|
20
|
+
|
|
21
|
+
has_many :recommendations
|
|
22
|
+
has_many :received_recommendations
|
|
23
|
+
|
|
24
|
+
has_many :filters
|
|
25
|
+
|
|
26
|
+
has_many :comments
|
|
27
|
+
has_many :links
|
|
28
|
+
has_many :subscriptions
|
|
29
|
+
|
|
30
|
+
has_many :tags
|
|
31
|
+
has_many :places
|
|
32
|
+
|
|
33
|
+
has_many :activities
|
|
34
|
+
|
|
35
|
+
has_many :tagcrumbs_friends
|
|
36
|
+
has_many :tagcrumbs_fans
|
|
37
|
+
|
|
38
|
+
# An array of all friends of a User (people the user is following)
|
|
39
|
+
def friends
|
|
40
|
+
array = []
|
|
41
|
+
|
|
42
|
+
friendships.each_page do |page|
|
|
43
|
+
array += page.map{|f| f.friend}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
array
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# An array of all fans of a User (people that follow this user)
|
|
50
|
+
def fans
|
|
51
|
+
array = []
|
|
52
|
+
|
|
53
|
+
fanships.each_page do |page|
|
|
54
|
+
array += page.map{|f| f.fan}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
array
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The friendship with a specific user
|
|
61
|
+
def friendship_with(user)
|
|
62
|
+
f = Friendship.new
|
|
63
|
+
f.reload("/#{self.username}/friends/#{user}")
|
|
64
|
+
rescue Net::HTTPServerException => error
|
|
65
|
+
f.requestor.response.code == '404' ? nil : (raise error) # not found
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Is this user friend with user?
|
|
69
|
+
def friend_with?(user)
|
|
70
|
+
friendship_with(user) ? true : false
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# The fanship with a specific user
|
|
74
|
+
def fanship_with(user)
|
|
75
|
+
Fanship.load("/#{self.username}/fans/#{user}")
|
|
76
|
+
rescue Net::HTTPServerException => error
|
|
77
|
+
self.requestor.response.code == '404' ? nil : (raise error) # not found
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Is this user a fan of user?
|
|
81
|
+
def fan_of?(user)
|
|
82
|
+
fanship_with(user) ? true : false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# Search a User by name or email
|
|
87
|
+
def self.search(q, args={})
|
|
88
|
+
Array.load(Tagcrumbs.root.users_url, args.merge(:u => q))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Load a User by its username
|
|
92
|
+
def self.find_by_username(username)
|
|
93
|
+
User.load("/#{username}")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def to_s
|
|
97
|
+
self.username
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# A Recommendation of a Placemark between two Users
|
|
3
|
+
class UserRecommendation < Model
|
|
4
|
+
can_be :created
|
|
5
|
+
|
|
6
|
+
readable_attributes :created_at, :updated_at
|
|
7
|
+
writeable_attributes :message
|
|
8
|
+
|
|
9
|
+
has_one :user
|
|
10
|
+
has_one :tagcrumb, :modifiable => true
|
|
11
|
+
has_one :recommended_user, :modifiable => true
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_url
|
|
15
|
+
Tagcrumbs.current_user.recommendations_url # has to be overwritten
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Tagcrumbs
|
|
2
|
+
# Superclass for all other Resources
|
|
3
|
+
class Resource
|
|
4
|
+
attr_accessor :resource_url, :loaded
|
|
5
|
+
attr_writer :requestor
|
|
6
|
+
attr_reader :properties
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
reset!
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Clean up the state of the model and make it blank again
|
|
13
|
+
def reset!
|
|
14
|
+
self.resource_url = nil
|
|
15
|
+
self.loaded = false
|
|
16
|
+
self.properties = {}
|
|
17
|
+
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Is the Resource loaded or is it just a stub and the attributes still need to be loaded from the web?
|
|
22
|
+
def loaded?
|
|
23
|
+
self.loaded ? true : false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# A requestor that is auto-generated if needed to make requests to the webservice
|
|
27
|
+
def requestor
|
|
28
|
+
@requestor ||= Requestor.new
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Reset the Resource, reload the data from the web and initialize it again from the document
|
|
32
|
+
def reload(url = nil)
|
|
33
|
+
self.requestor.get(url || resource_url)
|
|
34
|
+
initialize_from_document(requestor.response.body, requestor.response_format)
|
|
35
|
+
true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Set the properties and automatically set the resource_url
|
|
39
|
+
def properties=(properties)
|
|
40
|
+
self.resource_url = properties['xlink:href'] if properties['xlink:href']
|
|
41
|
+
@properties = properties.with_indifferent_access
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Load a Resource from a URL with optional query parameters
|
|
45
|
+
# The correct Resource class is automatically determined.
|
|
46
|
+
def self.load(path, query_string = {}, requestor_options={})
|
|
47
|
+
requestor = Requestor.new(requestor_options)
|
|
48
|
+
requestor.get(path, query_string)
|
|
49
|
+
|
|
50
|
+
resource = new_from_document(requestor.response.body, requestor.response_format)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Create a new Resource from a document.
|
|
54
|
+
# The correct Resource class is automatically determined.
|
|
55
|
+
def self.new_from_document(document, format = Tagcrumbs.options[:format])
|
|
56
|
+
parser = Parser.new_for_format(document, format)
|
|
57
|
+
|
|
58
|
+
resource = Tagcrumbs.class_by_type(parser.get_attribute('type')).new
|
|
59
|
+
resource.initialize_from_document(parser, format)
|
|
60
|
+
|
|
61
|
+
resource
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Initialize the object with data from the document
|
|
65
|
+
def initialize_from_document(document, format = Tagcrumbs.options[:format])
|
|
66
|
+
parser = Parser.new_for_format(document, format)
|
|
67
|
+
reset!
|
|
68
|
+
|
|
69
|
+
self.loaded = parser.node_loaded?
|
|
70
|
+
self.properties = parser.get_attributes || {}
|
|
71
|
+
|
|
72
|
+
parser
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|