cloudwow-not_relational 0.1.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.
Files changed (78) hide show
  1. data/README.rdoc +7 -0
  2. data/VERSION.yml +4 -0
  3. data/lib/not_relational/acts_as_not_relational_application.rb +11 -0
  4. data/lib/not_relational/and_condition.rb +10 -0
  5. data/lib/not_relational/attribute_range.rb +57 -0
  6. data/lib/not_relational/berkeley_repository.rb +48 -0
  7. data/lib/not_relational/configuration.rb +111 -0
  8. data/lib/not_relational/crypto.rb +58 -0
  9. data/lib/not_relational/domain_model.rb +855 -0
  10. data/lib/not_relational/domain_model_cache_item.rb +14 -0
  11. data/lib/not_relational/equals_condition.rb +18 -0
  12. data/lib/not_relational/geo.rb +188 -0
  13. data/lib/not_relational/index_description.rb +41 -0
  14. data/lib/not_relational/is_null_transform.rb +16 -0
  15. data/lib/not_relational/lazy_loading_text.rb +29 -0
  16. data/lib/not_relational/local_storage.rb +38 -0
  17. data/lib/not_relational/memcache_repository.rb +91 -0
  18. data/lib/not_relational/memory_repository.rb +273 -0
  19. data/lib/not_relational/memory_storage.rb +33 -0
  20. data/lib/not_relational/or_condition.rb +53 -0
  21. data/lib/not_relational/property_description.rb +102 -0
  22. data/lib/not_relational/query_string_auth_generator.rb +166 -0
  23. data/lib/not_relational/reference.rb +28 -0
  24. data/lib/not_relational/repository.rb +419 -0
  25. data/lib/not_relational/repository_factory.rb +67 -0
  26. data/lib/not_relational/repository_interface.rb +48 -0
  27. data/lib/not_relational/s3.rb +581 -0
  28. data/lib/not_relational/sdb_formatter.rb +119 -0
  29. data/lib/not_relational/sdb_monkey_patch.rb +47 -0
  30. data/lib/not_relational/starts_with_condition.rb +21 -0
  31. data/lib/not_relational/storage.rb +223 -0
  32. data/lib/not_relational/tag_cloud.rb +56 -0
  33. data/lib/not_relational/tracker_description.rb +26 -0
  34. data/lib/not_relational/uuid.rb +285 -0
  35. data/lib/not_relational.rb +17 -0
  36. data/test/models/album.rb +206 -0
  37. data/test/models/blurb.rb +65 -0
  38. data/test/models/blurb_wording.rb +18 -0
  39. data/test/models/comment.rb +27 -0
  40. data/test/models/error.rb +14 -0
  41. data/test/models/friend.rb +27 -0
  42. data/test/models/friend_request.rb +34 -0
  43. data/test/models/geo.rb +186 -0
  44. data/test/models/group.rb +283 -0
  45. data/test/models/language.rb +16 -0
  46. data/test/models/media_file.rb +32 -0
  47. data/test/models/media_item.rb +258 -0
  48. data/test/models/message.rb +26 -0
  49. data/test/models/node.rb +282 -0
  50. data/test/models/outgoing_email.rb +26 -0
  51. data/test/models/page_view_detail.rb +15 -0
  52. data/test/models/page_view_summary.rb +15 -0
  53. data/test/models/place.rb +103 -0
  54. data/test/models/rating.rb +21 -0
  55. data/test/models/tag.rb +89 -0
  56. data/test/models/user.rb +289 -0
  57. data/test/models/user_event.rb +67 -0
  58. data/test/models/weblab.rb +17 -0
  59. data/test/unit_tests/album_test.rb +181 -0
  60. data/test/unit_tests/bdb_test.rb +34 -0
  61. data/test/unit_tests/blurb_test.rb +110 -0
  62. data/test/unit_tests/comment_test.rb +42 -0
  63. data/test/unit_tests/composite_key_test.rb +75 -0
  64. data/test/unit_tests/enum_test.rb +32 -0
  65. data/test/unit_tests/group_test.rb +214 -0
  66. data/test/unit_tests/mediaitem_test.rb +412 -0
  67. data/test/unit_tests/memcache_repository_test.rb +40 -0
  68. data/test/unit_tests/memory_repository_test.rb +69 -0
  69. data/test/unit_tests/node_test.rb +490 -0
  70. data/test/unit_tests/place_test.rb +219 -0
  71. data/test/unit_tests/reference_set_test.rb +66 -0
  72. data/test/unit_tests/repository_factory_test.rb +16 -0
  73. data/test/unit_tests/tag_test.rb +86 -0
  74. data/test/unit_tests/user_test.rb +102 -0
  75. data/test/unit_tests/uuid.state +3 -0
  76. data/test/utils/create_sdb_domains.rb +44 -0
  77. data/test/utils/whack_domains.rb +32 -0
  78. metadata +134 -0
@@ -0,0 +1,206 @@
1
+ require 'digest/sha1'
2
+ require "uri"
3
+
4
+ require "not_relational/domain_model.rb"
5
+ require "active_support/inflector"
6
+
7
+ class Album < NotRelational::DomainModel
8
+ property :id,:string,:is_primary_key=>true
9
+ property :guid , :string,:unique=>true
10
+ property :user_name , :string
11
+ property :title , :string
12
+ property :description , :clob
13
+ property :created_time_utc ,:date
14
+ property :last_update_time_utc ,:date
15
+ property :is_private, :boolean
16
+ property :group_id, :string
17
+
18
+ index :group_and_title ,[:group_id,:title],:unique=>true
19
+ many_to_many :Mediaitem,:AlbumMediaItem,:album_id,:mediaitem_id,:mediaitems,:order_by=>:created_time
20
+ belongs_to :Group
21
+
22
+ def Album.add_mediaitem(user_name,media_guid,album_guid,new_album_title=nil)
23
+
24
+ mediaitem=Mediaitem.find_by_guid(media_guid)
25
+ if mediaitem
26
+ album=get_or_make_album(user_name,album_guid,new_album_title)
27
+
28
+ album.add_mediaitem(mediaitem)
29
+
30
+ return album
31
+ end
32
+ return nil
33
+ end
34
+ def still_image_media
35
+ result=[]
36
+ for media_item in self.mediaitems
37
+ if !media_item.HasVideo && ! media_item.HasAudio
38
+ result<<media_item;
39
+ end
40
+ end
41
+
42
+ return result
43
+ end
44
+ def video_media
45
+ result=[]
46
+ for media_item in self.mediaitems
47
+ if media_item.HasVideo
48
+ result<<media_item;
49
+ end
50
+
51
+ end
52
+ return result
53
+ end
54
+ def audio_media
55
+ result=[]
56
+ for media_item in self.mediaitems
57
+ if media_item.HasAudio
58
+ result<<media_item;
59
+ end
60
+
61
+ end
62
+
63
+ return result
64
+ end
65
+ def Album.create_group_album(user_name,group_id,title,description,is_private)
66
+
67
+ album=Album.new
68
+ album.guid="#{NotRelational::UUID.generate.to_s}"
69
+ album.title=title
70
+ album.user_name=user_name
71
+ album.group_id=group_id
72
+ album.description=description
73
+ album.is_private=is_private
74
+ album.created_time_utc=Time.now.gmtime
75
+ album.save!
76
+
77
+
78
+ return album
79
+ end
80
+ def item_after(mediaitem)
81
+ previous=nil
82
+ for child in self.mediaitems
83
+ if previous && previous.id==mediaitem.id
84
+ return child
85
+ end
86
+ previous=child
87
+ end
88
+
89
+
90
+
91
+ return nil
92
+ end
93
+
94
+
95
+
96
+ def item_before(mediaitem)
97
+
98
+ previous=nil
99
+
100
+ self.mediaitems.each do |child|
101
+ if previous && child.id==mediaitem.id
102
+ return previous
103
+ end
104
+
105
+ previous=child
106
+ end
107
+
108
+ return nil
109
+ end
110
+ def recent(how_many=5)
111
+ result=self.mediaitems.reverse
112
+ if result.length>how_many
113
+ result=result.slice(0,how_many)
114
+ end
115
+ return result;
116
+ end
117
+
118
+ def url
119
+ if group_id
120
+ raise "can't generate group urls from this API"
121
+ end
122
+ return "album/#{guid}/show.html"
123
+ end
124
+ def create_group_url(group_name)
125
+ return "#{Group.url_from_name(group_name)}/album/#{guid}"
126
+ end
127
+ def Album.create_group_url(group_name,album_guid)
128
+ return "#{Group.url_from_name(group_name)}/album/#{album_guid}"
129
+ end
130
+
131
+ def create_group_edit_url(group_name)
132
+ return "#{create_group_url(group_name)}/edit"
133
+ end
134
+ def create_group_upload_url(group_name)
135
+ return "#{Group.url_from_name(group_name)}/album/#{guid}/upload"
136
+ end
137
+ def add_mediaitem(mediaitem)
138
+
139
+ self.last_update_time_utc=Time.now.gmtime
140
+ self.save
141
+
142
+ old_item=AlbumMediaItem.find_connection(self.id,mediaitem.id)
143
+ if !old_item
144
+ newAlbumMediaItem=AlbumMediaItem.new
145
+ newAlbumMediaItem.album_id=self.id
146
+ newAlbumMediaItem.mediaitem_id=mediaitem.id
147
+ newAlbumMediaItem.save
148
+
149
+ end
150
+
151
+ end
152
+ def Album.get_user_album(user_name,album_guid=nil)
153
+ if !album_guid
154
+ album_guid="useralbum:#{user_name}";
155
+ end
156
+ album=Album.find_by_guid(album_guid)
157
+ if !album
158
+ album=Album.new
159
+ album.guid=album_guid
160
+ album.user_name=user_name
161
+ album.created_time_utc=Time.now.gmtime
162
+ album.title="#{user_name.capitalize}'s media collection";
163
+ album.save
164
+ end
165
+ if album.user_name!=user_name and album.user_name!= h(user_name)
166
+ raise "only album owner can submit to album"
167
+ end
168
+ return album
169
+ end
170
+ def Album.get_or_make_album(user_name,album_guid,new_album_title=nil)
171
+
172
+ if album_guid
173
+ album=Album.find_by_guid(album_guid)
174
+ end
175
+ if !album
176
+ album=Album.new
177
+
178
+ if album_guid
179
+ album.guid=album_guid
180
+ else
181
+ album.guid="#{UUID.generate.to_s}"
182
+ end
183
+
184
+
185
+
186
+ album.title=HtmlUtility.sanitize_html(new_album_title || "#{user_name.Capitalize}'s Media Collection").strip
187
+ album.user_name=user_name
188
+ album.created_time_utc=Time.now.gmtime
189
+
190
+ album.save!
191
+
192
+ end
193
+ return album
194
+ end
195
+
196
+ end
197
+ class AlbumMediaItem < NotRelational::DomainModel
198
+ property :id,:string,:is_primary_key=>true
199
+ property :album_id , :string
200
+ property :mediaitem_id , :string
201
+ index :album_and_mediaitem,[:album_id,:mediaitem_id],:unique=>true
202
+ def AlbumMediaItem.find_connection(album_id,mediaitem_id)
203
+ AlbumMediaItem.find_by_album_and_mediaitem(album_id,mediaitem_id)
204
+ end
205
+
206
+ end
@@ -0,0 +1,65 @@
1
+ require 'digest/sha1'
2
+ require "uri"
3
+
4
+ require "not_relational/domain_model.rb"
5
+ class Blurb < NotRelational::DomainModel
6
+
7
+ property :namespace,:string,:is_primary_key=>true
8
+ property :name,:string,:is_primary_key=>true
9
+ property :description , :string
10
+
11
+ has_many :BlurbWording,:blurb_id
12
+
13
+ def Blurb.get(namespace,name)
14
+ Blurb.find([namespace , name])
15
+
16
+ end
17
+ def get_wording(language=$language)
18
+ wording=BlurbWording.find([self.name ,self.namespace,language])
19
+ if !wording && language!='en'
20
+
21
+ return self.get_wording('en')
22
+
23
+ end
24
+ if !wording
25
+ return self.name
26
+ end
27
+ return wording.text
28
+ end
29
+ def set_wording(language,text)
30
+ wording=BlurbWording.find([self.name ,self.namespace,language])
31
+ if !wording
32
+ wording=BlurbWording.new
33
+ wording.blurb_name=self.name
34
+ wording.blurb_namespace=self.namespace
35
+ wording.language_id=language
36
+ end
37
+ wording.text=text
38
+ wording.save
39
+ return wording
40
+
41
+ end
42
+ def Blurb.set_wording(namespace,name,language,text)
43
+ blurb=Blurb.get(namespace,name)
44
+ if !blurb
45
+ blurb=Blurb.new
46
+ blurb.name=name
47
+ blurb.namespace=namespace
48
+ blurb.save!
49
+ end
50
+ blurb.set_wording(language,text)
51
+ end
52
+
53
+ def Blurb.get_wording(namespace,name,language_id='en',default_value=nil)
54
+ result=BlurbWording.find([name ,namespace,language_id])
55
+ if result!=nil
56
+ return result.text
57
+ end
58
+ if language_id=='en'
59
+ return default_value || name
60
+ end
61
+ return Blurb.get_wording(namespace,name,'en')
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,18 @@
1
+ require 'digest/sha1'
2
+ require "uri"
3
+
4
+ require "not_relational/domain_model.rb"
5
+
6
+ class BlurbWording < NotRelational::DomainModel
7
+ property :blurb_name,:string,:is_primary_key=>true
8
+ property :blurb_namespace,:string,:is_primary_key=>true
9
+ property :language_id , :string ,:is_primary_key=>true
10
+ property :text,:clob
11
+ property :title , :string
12
+ property :version , :string
13
+ property :author , :string
14
+ property :time_utc , :date
15
+
16
+ belongs_to :Blurb,:blurb_name
17
+
18
+ end
@@ -0,0 +1,27 @@
1
+ require "uri"
2
+
3
+ require "not_relational/domain_model.rb"
4
+ class Comment < NotRelational::DomainModel
5
+
6
+ property :id,:string,:is_primary_key=>true
7
+ property :title , :string
8
+ property :content , :string
9
+ property :posted_time , :date
10
+ property :mediaitem_id , :string
11
+ property :parent_id , :string
12
+ property :user_name , :string
13
+ property :namespace , :string
14
+
15
+
16
+ belongs_to :Mediaitem
17
+
18
+ def Comment.recent
19
+ Comment.find(:all, :limit => 16 ,:order_by =>:posted_time ,:order => :descending)
20
+ end
21
+ def Comment.recent_by_user(user_name)
22
+ Comment.find(:all, :limit => 16 ,:order_by =>:posted_time ,:order => :descending,:params => {:user_name=>user_name})
23
+ end
24
+ def user_url
25
+ return "/users/#{CGI.escape self.user_name}"
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ require 'digest/sha1'
2
+ require "uri"
3
+
4
+ require "model/domain_model.rb"
5
+
6
+
7
+ class Error < DomainModel
8
+ property :id,:string,:is_primary_key=>true
9
+ property :server,:string
10
+ property :message ,:string
11
+ property :stack_trace ,:string
12
+ property :time_utc ,:date
13
+
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'digest/sha1'
2
+ require "uri"
3
+
4
+ require "model/domain_model.rb"
5
+ require "models/blurb.rb"
6
+
7
+ class Friend < DomainModel
8
+ property :id,:string,:is_primary_key=>true
9
+ property :user_name,:string
10
+ property :friend_user_name,:string
11
+ property :created_time_utc,:date
12
+ belongs_to :User,:user_name,:user
13
+ belongs_to :User,:friend_user_name,:friend
14
+ index :user_name_and_friend_name,[:user_name,:friend_user_name],:unique=>true
15
+ def Friend.make_friend(user_name,friend_name)
16
+ existing_friend=Friend.find_by_user_name_and_friend_name(user_name.capitalize ,friend_name.capitalize)
17
+ if existing_friend==nil
18
+ newFriend=Friend.new
19
+ newFriend.user_name=user_name
20
+ newFriend.friend_user_name=friend_name
21
+ newFriend.created_time_utc=Time.now.gmtime
22
+ newFriend.save
23
+ return true
24
+ end
25
+ return false
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ require 'digest/sha1'
2
+ require "uri"
3
+
4
+ require "model/domain_model.rb"
5
+ require "models/blurb.rb"
6
+
7
+ class FriendRequest < DomainModel
8
+ property :id,:string,:is_primary_key=>true
9
+ property :user_name,:string
10
+ property :friend_user_name,:string
11
+ property :message,:clob
12
+ property :answer,:boolean
13
+ property :created_time_utc,:date
14
+ belongs_to :User,:user_name,:user
15
+ belongs_to :User,:friend_user_name,:friend_user
16
+ index :user_name_friend_name_and_answer_is_null,[:user_name,:friend_user_name,IsNullTransform.new(:answer)],:unique=>true
17
+ index :user_name_and_answer_is_null,[:user_name,IsNullTransform.new(:answer)]
18
+ index :friend_name_and_answer_is_null,[:friend_user_name,IsNullTransform.new(:answer)]
19
+ def FriendRequest.request_friendship(from_user_name,to_user_name,message)
20
+ old_request= find_old_request(from_user_name,to_user_name)
21
+ return false if old_request!=nil
22
+ new_request=FriendRequest.new
23
+ new_request.user_name=from_user_name
24
+ new_request.friend_user_name=to_user_name
25
+ new_request.message=message
26
+ new_request.created_time_utc=Time.now.gmtime
27
+ new_request.save
28
+ return true
29
+ end
30
+ def FriendRequest.find_old_request(from_user_name,to_user_name)
31
+ FriendRequest.find_by_user_name_friend_name_and_answer_is_null(from_user_name,to_user_name,true)
32
+ end
33
+
34
+ end
@@ -0,0 +1,186 @@
1
+ require "not_relational/starts_with_condition.rb"
2
+ module NotRelational
3
+ module Geo
4
+
5
+ class Location
6
+
7
+
8
+ attr_accessor :latitude
9
+ attr_accessor :longitude
10
+
11
+ def initialize(lat,lon)
12
+ self.latitude=lat
13
+ self.longitude=lon
14
+ end
15
+
16
+ def to_address
17
+ if latitude==nil || longitude==nil
18
+ return nil
19
+ end
20
+ address='t'
21
+ right=0
22
+ top=0
23
+ width=180.0
24
+ height=90.0
25
+ 16.times do
26
+
27
+ if latitude>top
28
+ top=top+height/2.0
29
+ if longitude<right
30
+ right=right-width/2.0
31
+ address<<'q'
32
+ else
33
+ right=right+width/2.0
34
+ address << 'r'
35
+ end
36
+ else
37
+
38
+ top=top-height/2.0
39
+ if longitude<right
40
+ right=right-width/2.0
41
+ address<<'t'
42
+ else
43
+ right=right+width/2.0
44
+ address << 's'
45
+ end
46
+ end
47
+ width=width/2.0
48
+ height=height/2.0
49
+ # puts "#{address} w=#{width} h=#{height} r=#{right} t=#{top}"
50
+ end
51
+ return address
52
+ end
53
+ def get_nearby_addresses(zoom_level)
54
+ address=self.to_address
55
+ if address.length>(zoom_level+1)
56
+ address=address.slice(0,zoom_level+1)
57
+ end
58
+
59
+ result=[address]
60
+
61
+ tileWidth=360.0/(2**zoom_level)
62
+ tileHeight=180.0/(2**zoom_level)
63
+
64
+ other=Geo::Location.new(self.latitude+tileHeight,self.longitude+tileWidth)
65
+ result << other.to_address.slice(0,zoom_level+1)
66
+
67
+ other=Geo::Location.new(self.latitude+tileHeight,self.longitude)
68
+ result << other.to_address.slice(0,zoom_level+1)
69
+
70
+ other=Geo::Location.new(self.latitude+tileHeight,self.longitude-tileWidth)
71
+ result << other.to_address.slice(0,zoom_level+1)
72
+
73
+ other=Geo::Location.new(self.latitude-tileHeight,self.longitude+tileWidth)
74
+ result << other.to_address.slice(0,zoom_level+1)
75
+
76
+ other=Geo::Location.new(self.latitude-tileHeight,self.longitude)
77
+ result << other.to_address.slice(0,zoom_level+1)
78
+
79
+ other=Geo::Location.new(self.latitude-tileHeight,self.longitude-tileWidth)
80
+ result << other.to_address.slice(0,zoom_level+1)
81
+
82
+
83
+ other=Geo::Location.new(self.latitude,self.longitude+tileWidth)
84
+ result << other.to_address.slice(0,zoom_level+1)
85
+
86
+ other=Geo::Location.new(self.latitude,self.longitude-tileWidth)
87
+ result << other.to_address.slice(0,zoom_level+1)
88
+
89
+
90
+ end
91
+ def Location.to_location(address)
92
+ width=90.0
93
+ height=45.0
94
+
95
+ index=0
96
+ x=0
97
+ y=0
98
+ length=address.length-1
99
+ length.times do
100
+ index+=1
101
+
102
+ puts address[index].chr
103
+ case address[index].chr
104
+
105
+ when 'r'
106
+ x+=width
107
+ y+=height
108
+ when 'q'
109
+ x-=width
110
+ y+=height
111
+
112
+ when 't'
113
+ x-=width
114
+ y-=height
115
+ when 's'
116
+ x+=width
117
+ y-=height
118
+ end
119
+ width/=2
120
+ height/=2
121
+ end
122
+ loc=Location.new
123
+ loc.latitude=y
124
+ loc.longitude=x
125
+ return loc
126
+ end
127
+
128
+ def self.deg2rad(deg)
129
+ (deg * Math::PI / 180)
130
+ end
131
+
132
+ def self.rad2deg(rad)
133
+ (rad * 180 / Math::PI)
134
+ end
135
+
136
+ def self.acos(rad)
137
+ Math.atan2(Math.sqrt(1 - rad**2), rad)
138
+ end
139
+
140
+ def distance_in_miles( loc2)
141
+ lat2 = loc2.latitude
142
+ lon2 = loc2.longitude
143
+ theta = self.longitude - lon2
144
+
145
+ dist = Math.sin(self.deg2rad(self.latitude)) * Math.sin(deg2rad(lat2)) + Math.cos(self.deg2rad(self.latitude)) * Math.cos(self.deg2rad(lat2)) * Math.cos(deg2rad(theta))
146
+
147
+ dist = self.rad2deg(self.acos(dist))
148
+
149
+ (dist * 60 * 1.1515).round #distance in miles
150
+ end
151
+
152
+ end
153
+
154
+ #mixin
155
+ #locatable object must have latitude, longitude and address attributes
156
+ module Locatable
157
+ def location
158
+ return Geo::Location.new(latitude,longitude)
159
+ end
160
+ def get_nearby(zoom_level=7,order=nil)
161
+ if latitude==nil or longitude==nil
162
+ return []
163
+ end
164
+ result= self.class.find_near(self.location,zoom_level,order)
165
+ result.delete_if{|item|item.id==id}
166
+ return result
167
+ end
168
+
169
+ def find_near(loc,zoom_level=7,order_by=nil,order=:ascending)
170
+ nearby= loc.get_nearby_addresses(zoom_level)
171
+
172
+ address_params=[]
173
+ for address in nearby
174
+
175
+ address_params<<NotRelational::StartsWithCondition.new(self.AttributeDescription(:address),address)
176
+
177
+ end
178
+ orCondition=OrCondition.new(address_params)
179
+
180
+ return find(:all,:limit => 24,:order_by => order_by,:order => order,:conditions=>[orCondition])
181
+
182
+ end
183
+ end
184
+
185
+ end
186
+ end