nosql-tutorial 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|