nosql-tutorial 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.
- data/README.markdown +20 -0
- data/Rakefile +34 -0
- data/VERSION.yml +5 -0
- data/lib/config.ru +12 -0
- data/lib/nosql.rb +64 -0
- data/lib/public/doc/mail/body.txt +1 -0
- data/lib/public/doc/mail/mail-00.rb +31 -0
- data/lib/public/doc/mail/mail-01.rb +29 -0
- data/lib/public/doc/mail/mail-10.rb +24 -0
- data/lib/public/doc/mail/motylek.jpeg +0 -0
- data/lib/public/doc/plain-text-files/contacts.yaml +11 -0
- data/lib/public/doc/plain-text-files/contacts_g.rb +105 -0
- data/lib/public/doc/plain-text-files/contacts_g_test.rb +51 -0
- data/lib/public/doc/plain-text-files/contacts_y.rb +57 -0
- data/lib/public/doc/plain-text-files/contacts_y_test.rb +39 -0
- data/lib/public/doc/plain-text-files/gdbm-example.rb +22 -0
- data/lib/public/doc/using-plain-text-files-for-data-persistence.pdf +0 -0
- data/lib/public/favicon.ico +0 -0
- data/lib/public/images/conan_doyle.jpg +0 -0
- data/lib/public/images/datamapper.png +0 -0
- data/lib/public/images/datamapper.svg +95 -0
- data/lib/public/stylesheets/fonts/Cyklop-Italic.otf +0 -0
- data/lib/public/stylesheets/icons/cross.png +0 -0
- data/lib/public/stylesheets/icons/doc.png +0 -0
- data/lib/public/stylesheets/icons/email.png +0 -0
- data/lib/public/stylesheets/icons/external.png +0 -0
- data/lib/public/stylesheets/icons/feed.png +0 -0
- data/lib/public/stylesheets/icons/im.png +0 -0
- data/lib/public/stylesheets/icons/key.png +0 -0
- data/lib/public/stylesheets/icons/pdf.png +0 -0
- data/lib/public/stylesheets/icons/tick.png +0 -0
- data/lib/public/stylesheets/icons/visited.png +0 -0
- data/lib/public/stylesheets/icons/xls.png +0 -0
- data/lib/public/stylesheets/ie.css +27 -0
- data/lib/public/stylesheets/nosql.css +166 -0
- data/lib/public/stylesheets/print.css +30 -0
- data/lib/public/stylesheets/screen.css +249 -0
- data/lib/public/stylesheets/src/body.png +0 -0
- data/lib/public/stylesheets/src/grid.png +0 -0
- data/lib/public/stylesheets/src/make_background_images.sh +11 -0
- data/lib/public/stylesheets/src/shattered_mirror.png +0 -0
- data/lib/public/stylesheets/uv.css +121 -0
- data/lib/views/ar.rdiscount +5 -0
- data/lib/views/datamapper.rdiscount +43 -0
- data/lib/views/layout.rdiscount +38 -0
- data/lib/views/main.rdiscount +47 -0
- data/lib/views/mongodb.rdiscount +41 -0
- data/lib/views/redis.rdiscount +20 -0
- data/lib/views/ruby-intro.rdiscount +37 -0
- data/lib/views/serializacja-danych.rdiscount +75 -0
- data/lib/views/skel.rdiscount +3 -0
- data/lib/views/summary.rdiscount +32 -0
- metadata +175 -0
data/README.markdown
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Not Only SQL — Data Persistence with Ruby
|
2
|
+
|
3
|
+
## TODO list
|
4
|
+
|
5
|
+
### Jakieś aplikacje:
|
6
|
+
|
7
|
+
1. [pastie](http://www.dzone.com/links/datamapper_sinatra_tutorial.html),
|
8
|
+
[pastie2](http://blog.zerosum.org/2008/7/2/clone-pastie-with-sinatra-datamapper-redux).
|
9
|
+
2. [apps written in sinatra, uses datamapper](http://github.com/zapnap/mogo/)
|
10
|
+
3. [A simple Twitter application template, built in Ruby with
|
11
|
+
Sinatra and DataMapper](http://github.com/zapnap/retweet/)
|
12
|
+
|
13
|
+
### Data persistence
|
14
|
+
|
15
|
+
1. [using plain-text files for data persistence](/doc/using-plain-text-files-for-data-persistence.pdf)
|
16
|
+
1. Datamapper adapter for Redis:
|
17
|
+
[DataMapper loves Redis](http://whoahbot.com/2009/05/27/redis-and-datamapper.html)
|
18
|
+
\([source, example](http://github.com/whoahbot/dm-redis-adapter/)\).
|
19
|
+
|
20
|
+
1. redis.spec for Fedora rpm?
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "nosql-tutorial"
|
9
|
+
s.summary = "Notatki do wykladu Utrwalanie Danych"
|
10
|
+
s.author = "Wlodek Bzyl"
|
11
|
+
s.email = "matwb@univ.gda.pl"
|
12
|
+
s.homepage = "http://github.com/wbzyl/nosql"
|
13
|
+
|
14
|
+
s.description = <<-EOF
|
15
|
+
Notatki do wykładu Utrwalanie Danych.
|
16
|
+
EOF
|
17
|
+
|
18
|
+
s.files = %w[Rakefile README.markdown VERSION.yml] + FileList["lib/**/*"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'rack'
|
21
|
+
s.add_runtime_dependency 'sinatra'
|
22
|
+
s.add_runtime_dependency 'rdiscount'
|
23
|
+
s.add_runtime_dependency 'ultraviolet'
|
24
|
+
s.add_runtime_dependency 'rack-codehighlighter'
|
25
|
+
s.add_runtime_dependency 'sinatra-rdiscount'
|
26
|
+
s.add_runtime_dependency 'sinatra-static-assets'
|
27
|
+
|
28
|
+
s.rubyforge_project = 'nosql'
|
29
|
+
end
|
30
|
+
Jeweler::GemcutterTasks.new
|
31
|
+
rescue LoadError
|
32
|
+
puts "Jeweler not available. Install it with:"
|
33
|
+
puts " sudo gem install jeweler"
|
34
|
+
end
|
data/VERSION.yml
ADDED
data/lib/config.ru
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'nosql'
|
2
|
+
|
3
|
+
gem 'rack-codehighlighter'
|
4
|
+
require 'rack/codehighlighter'
|
5
|
+
|
6
|
+
gem 'ultraviolet'
|
7
|
+
require 'uv'
|
8
|
+
|
9
|
+
use Rack::ShowExceptions
|
10
|
+
use Rack::Lint
|
11
|
+
use Rack::Codehighlighter, :ultraviolet, :element => '//pre/code', :markdown => true
|
12
|
+
run WB::NoSQL.new
|
data/lib/nosql.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# Zobacz przykład: http://gist.github.com/38605
|
4
|
+
|
5
|
+
require 'rdiscount'
|
6
|
+
require 'sinatra/base'
|
7
|
+
require 'sinatra/rdiscount'
|
8
|
+
|
9
|
+
require 'sinatra/url_for'
|
10
|
+
require 'sinatra/static_assets'
|
11
|
+
|
12
|
+
module WB
|
13
|
+
class NoSQL < Sinatra::Base
|
14
|
+
helpers Sinatra::UrlForHelper
|
15
|
+
register Sinatra::StaticAssets
|
16
|
+
|
17
|
+
# disable overriding public and views dirs
|
18
|
+
set :app_file, __FILE__
|
19
|
+
set :static, true
|
20
|
+
|
21
|
+
# the middleware stack can be used internally as well. I'm using it for
|
22
|
+
# sessions, logging, and methodoverride. This lets us move stuff out of
|
23
|
+
# Sinatra if it's better handled by a middleware component.
|
24
|
+
set :logging, true # use Rack::CommonLogger
|
25
|
+
|
26
|
+
helpers Sinatra::RDiscount
|
27
|
+
|
28
|
+
# configure blocks:
|
29
|
+
# configure :production do
|
30
|
+
# end
|
31
|
+
|
32
|
+
#before do
|
33
|
+
# mime :sql, 'text/plain; charset="UTF-8"' # when served by Sinatra itself
|
34
|
+
#end
|
35
|
+
|
36
|
+
# helper methods
|
37
|
+
|
38
|
+
def page_title
|
39
|
+
@title || ""
|
40
|
+
end
|
41
|
+
|
42
|
+
# def title=(name)... does not work, bug?
|
43
|
+
def title(name)
|
44
|
+
@title = " | #{name}"
|
45
|
+
end
|
46
|
+
|
47
|
+
get '/' do
|
48
|
+
rdiscount :main
|
49
|
+
end
|
50
|
+
|
51
|
+
get '/:section' do
|
52
|
+
rdiscount :"#{params[:section]}"
|
53
|
+
end
|
54
|
+
|
55
|
+
error do
|
56
|
+
e = request.env['sinatra.error']
|
57
|
+
Kernel.puts e.backtrace.join("\n")
|
58
|
+
'Application error'
|
59
|
+
end
|
60
|
+
|
61
|
+
# each Sinatra::Base subclass has its own private middleware stack:
|
62
|
+
use Rack::Lint
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
This is a test message: ĄĆĘŁŃÓŚŹŻ ąćęłńóśźż.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
# utwórz wiadomość
|
6
|
+
|
7
|
+
require 'mail'
|
8
|
+
mail = Mail.new do
|
9
|
+
from 'wbzyl@inf.ug.edu.pl'
|
10
|
+
to 'matwb@ug.edu.pl'
|
11
|
+
content_type 'text/plain; charset=UTF-8'
|
12
|
+
content_transfer_encoding '8bit'
|
13
|
+
mime_version '1.0'
|
14
|
+
|
15
|
+
subject 'This is a test email: #100'
|
16
|
+
|
17
|
+
body File.read('body.txt')
|
18
|
+
end
|
19
|
+
|
20
|
+
puts mail.to_s
|
21
|
+
|
22
|
+
# wyślij ją
|
23
|
+
|
24
|
+
require 'net/smtp'
|
25
|
+
|
26
|
+
login = 'wbzyl'
|
27
|
+
password = 'alamakota'
|
28
|
+
|
29
|
+
Net::SMTP.start('inf.ug.edu.pl', 25, 'inf.ug.edu.pl', login, password, :login) do |smtp|
|
30
|
+
smtp.send_message mail.to_s, mail.from, mail.to
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'mail'
|
5
|
+
|
6
|
+
login = 'wbzyl'
|
7
|
+
password = 'alamakota'
|
8
|
+
|
9
|
+
Mail.defaults do
|
10
|
+
smtp 'inf.ug.edu.pl', 25 do
|
11
|
+
user login
|
12
|
+
pass password
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
mail = Mail.deliver do
|
17
|
+
from 'wbzyl@inf.ug.edu.pl'
|
18
|
+
to 'matwb@ug.edu.pl'
|
19
|
+
content_type 'text/plain; charset=UTF-8'
|
20
|
+
|
21
|
+
subject 'This is a test email: 30'
|
22
|
+
body File.read('body.txt')
|
23
|
+
|
24
|
+
# add_file 'motylek.jpeg'
|
25
|
+
# albo tak
|
26
|
+
# add_file :filename => 'motylek.jpeg',
|
27
|
+
# :data => File.read('motylek.jpeg'),
|
28
|
+
# :content_transfer_encoding => 'base64'
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'mail'
|
5
|
+
|
6
|
+
login = 'matwb'
|
7
|
+
password = 'alamakota'
|
8
|
+
|
9
|
+
Mail.defaults do
|
10
|
+
pop3 'julia.univ.gda.pl', 110 do
|
11
|
+
user login
|
12
|
+
pass password
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
emails = Mail.first(:count => 4, :order => :asc) do |email|
|
17
|
+
puts email.date.to_s
|
18
|
+
puts email.from
|
19
|
+
puts email.subject.to_s
|
20
|
+
# puts email.body.to_s[0..40]
|
21
|
+
# puts email.message_id
|
22
|
+
# puts email.to
|
23
|
+
# puts email.cc
|
24
|
+
end
|
Binary file
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'gdbm'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class ContactList
|
5
|
+
|
6
|
+
attr_reader :contact_cache
|
7
|
+
|
8
|
+
def initialize(dir)
|
9
|
+
@dir = dir
|
10
|
+
@contact_cache = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](name)
|
14
|
+
contact = @contact_cache.find {|c| c.name == name }
|
15
|
+
return contact if contact
|
16
|
+
contact = Contact.new(name)
|
17
|
+
Dir.chdir(@dir) do
|
18
|
+
if File.directory?(contact.dirname)
|
19
|
+
populate_contact(contact)
|
20
|
+
@contact_cache << contact
|
21
|
+
else
|
22
|
+
contact = nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
contact
|
26
|
+
end
|
27
|
+
|
28
|
+
def populate_contact(contact)
|
29
|
+
Dir.chdir(contact.dirname) do
|
30
|
+
contact.open
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def <<(contact)
|
35
|
+
Dir.chdir(@dir) do
|
36
|
+
Dir.mkdir(contact.dirname) unless File.exists?(contact.dirname)
|
37
|
+
populate_contact(contact)
|
38
|
+
end
|
39
|
+
@contact_cache << contact
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(name)
|
43
|
+
contact = self[name]
|
44
|
+
return false unless contact
|
45
|
+
contact.close
|
46
|
+
Dir.chdir(@dir) do
|
47
|
+
FileUtils.rm_rf(contact.dirname)
|
48
|
+
end
|
49
|
+
contact_cache.delete_if {|c| c.name == name }
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def directory_names
|
54
|
+
Dir["#{@dir}/*"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def size
|
58
|
+
directory_names.size
|
59
|
+
end
|
60
|
+
|
61
|
+
def empty?
|
62
|
+
directory_names.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
class Contact
|
69
|
+
|
70
|
+
COMPONENTS = ["home", "extras", "work"]
|
71
|
+
|
72
|
+
attr_accessor :name, *COMPONENTS
|
73
|
+
|
74
|
+
attr_reader :dirname
|
75
|
+
|
76
|
+
def initialize(name)
|
77
|
+
@name = name
|
78
|
+
@dirname = @name.gsub(" ", "_")
|
79
|
+
end
|
80
|
+
|
81
|
+
def components
|
82
|
+
COMPONENTS.map {|comp_name| self.send(comp_name) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def open
|
86
|
+
COMPONENTS.each do |component|
|
87
|
+
self.send(component + "=", GDBM.new(component))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def close
|
92
|
+
components.each do |component|
|
93
|
+
component.close unless component.closed?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def email
|
98
|
+
extras["email"]
|
99
|
+
end
|
100
|
+
|
101
|
+
def email=(e)
|
102
|
+
extras["email"] = e
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'contacts_g'
|
3
|
+
|
4
|
+
Dir.mkdir("gdbm_contacts") unless File.exist?("gdbm_contacts")
|
5
|
+
|
6
|
+
class GDBMTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@list = ContactList.new("gdbm_contacts")
|
10
|
+
@contact = Contact.new("Joe Smith")
|
11
|
+
|
12
|
+
@list << @contact
|
13
|
+
|
14
|
+
@contact.home["street1"] = "123 Main Street"
|
15
|
+
@contact.home["city"] = "Somewhere"
|
16
|
+
@contact.work["phone"] = "(000) 123-4567"
|
17
|
+
@contact.extras["instrument"] = "Cello"
|
18
|
+
@contact.email = "joe@somewhere.abc"
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
@list.delete("Joe Smith") if @list["Joe Smith"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_retrieving_a_contact_from_list
|
26
|
+
contact = @list["Joe Smith"]
|
27
|
+
assert_equal("Joe Smith", contact.name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_delete_a_contact_from_list
|
31
|
+
assert(!@list.empty?)
|
32
|
+
@list.delete("Joe Smith")
|
33
|
+
assert(@list.empty?)
|
34
|
+
assert(@list.contact_cache.empty?)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_home
|
38
|
+
contact = @list["Joe Smith"]
|
39
|
+
assert_equal("123 Main Street", contact.home["street1"])
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_email
|
43
|
+
contact = @list["Joe Smith"]
|
44
|
+
assert_equal("joe@somewhere.abc", contact.email)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_non_existent_contact_is_nil
|
48
|
+
assert_equal(nil, @list["Some Person"])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
class ContactList
|
4
|
+
attr_accessor :contacts
|
5
|
+
|
6
|
+
def initialize(file)
|
7
|
+
@file = file
|
8
|
+
@contacts = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(contact)
|
12
|
+
@contacts << contact
|
13
|
+
end
|
14
|
+
|
15
|
+
def delete(name)
|
16
|
+
@contacts.delete_if {|c| c.name == name }
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty?
|
20
|
+
@contacts.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def size
|
24
|
+
@contacts.size
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](name)
|
28
|
+
@contacts.find {|c| c.name == name }
|
29
|
+
end
|
30
|
+
|
31
|
+
def save
|
32
|
+
File.open(@file, "w") do |fh|
|
33
|
+
fh.puts(@contacts.to_yaml)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.load(file)
|
38
|
+
list = new(file)
|
39
|
+
list.contacts = YAML.load(File.read(file))
|
40
|
+
list
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class Contact
|
47
|
+
attr_reader :name, :email, :home, :work, :extras
|
48
|
+
attr_writer :name, :email
|
49
|
+
|
50
|
+
def initialize(name)
|
51
|
+
@name = name
|
52
|
+
@home = {}
|
53
|
+
@work = {}
|
54
|
+
@extras = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|