Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/sinatra/sinatra
Browse files Browse the repository at this point in the history
  • Loading branch information
rkh committed Sep 1, 2010
2 parents 91b740a + 1187a86 commit 5556dbe
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 51 deletions.
84 changes: 42 additions & 42 deletions README.de.rdoc
Expand Up @@ -40,7 +40,7 @@ Jede Route besitzt einen Block:
Die Routen werden in der Reihenfolge angesprochen, wie sie definiert sind. Die Routen werden in der Reihenfolge angesprochen, wie sie definiert sind.
Das erste Route-Muster das mit dem Request übereinstimmt wird ausgeführt. Das erste Route-Muster das mit dem Request übereinstimmt wird ausgeführt.


Die Muster der Routen können über benannte Parameter erreicht werden mit dem Die Muster der Routen können über benannte Parameter erreicht werden mit dem
<tt>params</tt> Hash: <tt>params</tt> Hash:


get '/hallo/:name' do get '/hallo/:name' do
Expand Down Expand Up @@ -80,7 +80,7 @@ Oder mit einem Block-Parameter:
"Hallo, #{c}!" "Hallo, #{c}!"
end end


Routen können eine Vielzahl von zutreffenden Bedingungen haben, möglich wäre Routen können eine Vielzahl von zutreffenden Bedingungen haben, möglich wäre
ein User Agent: ein User Agent:


get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
Expand All @@ -94,12 +94,12 @@ ein User Agent:
== Statische Dateien == Statische Dateien


Statische Dateien werden vom Ordner <tt>./public</tt> geliefert. Es ist Statische Dateien werden vom Ordner <tt>./public</tt> geliefert. Es ist
möglich einen anderen Ort zu definieren, wenn die <tt>:public</tt> Option möglich einen anderen Ort zu definieren, wenn die <tt>:public</tt> Option
gesetzt wird: gesetzt wird:


set :public, File.dirname(__FILE__) + '/static' set :public, File.dirname(__FILE__) + '/static'


Anmerkung: Der public Ordner ist nicht über die URL aufrufbar. Die Datei Anmerkung: Der public Ordner ist nicht über die URL aufrufbar. Die Datei
<tt>./public/css/style.css</tt> wird gefunden unter <tt>./public/css/style.css</tt> wird gefunden unter
<tt>http://example.com/css/style.css</tt>. <tt>http://example.com/css/style.css</tt>.


Expand All @@ -110,7 +110,7 @@ befinden. Um einen anderen Ordner zu definieren:


set :views, File.dirname(__FILE__) + '/templates' set :views, File.dirname(__FILE__) + '/templates'


Eine wichtige Sache die man sich merken sollte, ist das man immer um auf Eine wichtige Sache die man sich merken sollte, ist das man immer um auf
Templates zu verweisen Symbole verwenden sollte, auch dann wenn sich ein Templates zu verweisen Symbole verwenden sollte, auch dann wenn sich ein
Template in einen Unterordner befindet (in diesen Fall <tt>:'subdir/template'</tt>). Template in einen Unterordner befindet (in diesen Fall <tt>:'subdir/template'</tt>).
Rendering-Methoden rendern jede Zeichenkette direkt. Rendering-Methoden rendern jede Zeichenkette direkt.
Expand Down Expand Up @@ -214,7 +214,7 @@ Rendert die inline Template Zeichenkette.


=== Auf Variablen in Templates zugreifen === Auf Variablen in Templates zugreifen


Templates werden im selben Kontext ausgewertet wie Routen. Instanz Variablen in Templates werden im selben Kontext ausgewertet wie Routen. Instanz Variablen in
Routen sind auch direkt im Template ansprechbar: Routen sind auch direkt im Template ansprechbar:


get '/:id' do get '/:id' do
Expand All @@ -229,7 +229,7 @@ Oder durch ein explizites Hash von lokalen Variablen:
haml '%h1= foo.name', :locals => { :foo => foo } haml '%h1= foo.name', :locals => { :foo => foo }
end end


Wird typischerweise bei Verwendung von Subtemplates (partials) in anderen Wird typischerweise bei Verwendung von Subtemplates (partials) in anderen
Templates eingesetzt. Templates eingesetzt.


=== Inline Templates === Inline Templates
Expand All @@ -253,12 +253,12 @@ Templates können am Ende der Datei definiert werden:
%div.title Hallo Welt!!!!! %div.title Hallo Welt!!!!!


Anmerkung: Inline Templates die in der Quelldatei definiert sind die Sinatra Anmerkung: Inline Templates die in der Quelldatei definiert sind die Sinatra
braucht werden automatisch geladen. Um andere Inline Templates in anderen braucht werden automatisch geladen. Um andere Inline Templates in anderen
Quelldateien aufzurufen muss `enable :inline_templates` explizit verwendet werden. Quelldateien aufzurufen muss `enable :inline_templates` explizit verwendet werden.


=== Benannte Templates === Benannte Templates


Templates können auch mit der top-level <tt>template</tt> Methode definiert Templates können auch mit der top-level <tt>template</tt> Methode definiert
werden: werden:


template :layout do template :layout do
Expand All @@ -273,7 +273,7 @@ werden:
haml :index haml :index
end end


Wenn ein Template mit dem Namen "layout" existiert, wird es bei jeden Aufruf Wenn ein Template mit dem Namen "layout" existiert, wird es bei jeden Aufruf
verwendet. Durch <tt>:layout => false</tt> kann das Ausführen verhindert werden. verwendet. Durch <tt>:layout => false</tt> kann das Ausführen verhindert werden.


get '/' do get '/' do
Expand All @@ -282,7 +282,7 @@ verwendet. Durch <tt>:layout => false</tt> kann das Ausführen verhindert werden


== Helfer == Helfer


Am top-level werden durch die <tt>helpers</tt> Methode, Helfer Methoden Am top-level werden durch die <tt>helpers</tt> Methode, Helfer Methoden
definiert bevor die Routen und Templates definiert werden: definiert bevor die Routen und Templates definiert werden:


helpers do helpers do
Expand All @@ -297,8 +297,8 @@ definiert bevor die Routen und Templates definiert werden:


== Filter == Filter


"Before" Filter werden immer vor jedem Request ausgeführt. Der Request kann so "Before" Filter werden immer vor jedem Request ausgeführt. Der Request kann so
Request und Antwort ändern. Gesetzte Instanz Variablen in Filtern können in Request und Antwort ändern. Gesetzte Instanz Variablen in Filtern können in
Routen und Templates verwendet werden: Routen und Templates verwendet werden:


before do before do
Expand All @@ -311,7 +311,7 @@ Routen und Templates verwendet werden:
params[:splat] #=> 'bar/baz' params[:splat] #=> 'bar/baz'
end end


"After" Filter werden nach jedem Request ausgeführt, können auch Request und "After" Filter werden nach jedem Request ausgeführt, können auch Request und
Antwort ändern. Gesetzte Instanz Variablen in before Filtern können in after Filter Antwort ändern. Gesetzte Instanz Variablen in before Filtern können in after Filter
verwendet werden: verwendet werden:


Expand Down Expand Up @@ -355,7 +355,7 @@ Eine Route kann mittels <tt>pass</tt> zu der nächsten treffenden Route springen
end end


Der Block wird sofort verlassen und es wird nach der nächsten treffenden Route Der Block wird sofort verlassen und es wird nach der nächsten treffenden Route
gesucht. Ein 404 Fehler wird zurückgegeben, wenn kein treffendes Routen-Muster gesucht. Ein 404 Fehler wird zurückgegeben, wenn kein treffendes Routen-Muster
gefunden wird. gefunden wird.


== Konfiguration == Konfiguration
Expand All @@ -373,7 +373,7 @@ gesetzt ist:
... ...
end end


Lauft nur wenn die Umgebung auf <tt>:production</tt> oder auf <tt>:test</tt> Lauft nur wenn die Umgebung auf <tt>:production</tt> oder auf <tt>:test</tt>
gesetzt ist: gesetzt ist:


configure :production, :test do configure :production, :test do
Expand All @@ -383,12 +383,12 @@ gesetzt ist:
== Fehler-Behandlung == Fehler-Behandlung


Error Handler laufen im selben Kontext wie Routen und before Filter, was bedeutet Error Handler laufen im selben Kontext wie Routen und before Filter, was bedeutet
es können alle Goodies wie <tt>haml</tt>, <tt>erb</tt>, <tt>halt</tt>, etc. es können alle Goodies wie <tt>haml</tt>, <tt>erb</tt>, <tt>halt</tt>, etc.
verwendet werden. verwendet werden.


=== Nicht gefunden === Nicht gefunden


Wenn eine <tt>Sinatra::NotFound</tt> Exception geworfen wird oder ein Statuscode Wenn eine <tt>Sinatra::NotFound</tt> Exception geworfen wird oder ein Statuscode
ist 404, wird der <tt>not_found</tt> Handler ausgeführt: ist 404, wird der <tt>not_found</tt> Handler ausgeführt:


not_found do not_found do
Expand All @@ -397,8 +397,8 @@ ist 404, wird der <tt>not_found</tt> Handler ausgeführt:


=== Fehler === Fehler


Der +error+ Handler wird immer ausgeführt wenn eine Exception in einem Routenblock Der +error+ Handler wird immer ausgeführt wenn eine Exception in einem Routenblock
oder in einen Filter geworfen wurde. Das Exception Objekt kann über die oder in einen Filter geworfen wurde. Das Exception Objekt kann über die
<tt>sinatra.error</tt> Rack Variable angesprochen werden: <tt>sinatra.error</tt> Rack Variable angesprochen werden:


error do error do
Expand Down Expand Up @@ -437,13 +437,13 @@ Oder ein Bereich:
'Boom' 'Boom'
end end


Sinatra verwendet verschiedene <tt>not_found</tt> und <tt>error</tt> Sinatra verwendet verschiedene <tt>not_found</tt> und <tt>error</tt>
Handler in der Development Umgebung. Handler in der Development Umgebung.


== Mime Typen == Mime Typen


Wenn mit <tt>send_file</tt> oder statische Dateien verwendet wird, kann es Wenn mit <tt>send_file</tt> oder statische Dateien verwendet wird, kann es
sein das Sinatra den Mime-Typ nicht versteht. Registriert wird mit +mime_type+ sein das Sinatra den Mime-Typ nicht versteht. Registriert wird mit +mime_type+
per Datei Endung: per Datei Endung:


mime_type :foo, 'text/foo' mime_type :foo, 'text/foo'
Expand All @@ -454,10 +454,10 @@ Es kann auch der +content_type+ Helfer verwendet werden:


== Rack Middleware == Rack Middleware


Sinatra baut auf Rack[http://rack.rubyforge.org/], einen minimalen Standard Sinatra baut auf Rack[http://rack.rubyforge.org/], einen minimalen Standard
Interface für Ruby Web Frameworks. Eines der am meisten interessantesten Interface für Ruby Web Frameworks. Eines der am meisten interessantesten
Fähigkeiten für Entwickler ist der Support von "Middleware" Komponenten die Fähigkeiten für Entwickler ist der Support von "Middleware" Komponenten die
zwischen dem Server und der Anwendung überwacht laufen und/oder den HTTP zwischen dem Server und der Anwendung überwacht laufen und/oder den HTTP
Request/Antwort manipulieren können. Request/Antwort manipulieren können.


Sinatra macht das bauen von Rack middleware pipelines sicher via der top-level Sinatra macht das bauen von Rack middleware pipelines sicher via der top-level
Expand All @@ -473,9 +473,9 @@ Sinatra macht das bauen von Rack middleware pipelines sicher via der top-level
'Hallo Welt' 'Hallo Welt'
end end


Die Semantik von +use+ sind identisch mit den Definierten von Die Semantik von +use+ sind identisch mit den Definierten von
Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL Rack::Builder[http://rack.rubyforge.org/doc/classes/Rack/Builder.html] DSL
(meistens verwendet von rackup Dateien). Als Beispiel, die +use+ Methode (meistens verwendet von rackup Dateien). Als Beispiel, die +use+ Methode
akzeptiert mehrere/verschiedene Argumente genauso wie Blöcke: akzeptiert mehrere/verschiedene Argumente genauso wie Blöcke:


use Rack::Auth::Basic do |username, password| use Rack::Auth::Basic do |username, password|
Expand Down Expand Up @@ -523,13 +523,13 @@ Klasse werden nach Version 0.9.2 nicht mehr unterstützt.


== Sinatra::Base - Middleware, Bibliotheken, und modulare Anwendungen == Sinatra::Base - Middleware, Bibliotheken, und modulare Anwendungen


Die Definition einer Anwendung vom top-level weg funktioniert gut für Die Definition einer Anwendung vom top-level weg funktioniert gut für
Micro-Anwendungen hat aber Nachteile wenn man wiederverwendbare Komponenten Micro-Anwendungen hat aber Nachteile wenn man wiederverwendbare Komponenten
wie Rack Middleware, Rails metal, einfache Bibliotheken mit Server Komponenten wie Rack Middleware, Rails metal, einfache Bibliotheken mit Server Komponenten
oder auch Sinatra Erweiterungen bauen will. oder auch Sinatra Erweiterungen bauen will.
Das top-level DSL belastet den Objekt-Namespace und setzt einen Style einer Das top-level DSL belastet den Objekt-Namespace und setzt einen Style einer
Micro-Anwendung voraus (ein einzelne Anwendungs-Datei, ./public und ./views Micro-Anwendung voraus (ein einzelne Anwendungs-Datei, ./public und ./views
Ordner, Logging, Exception Detail Seite, etc). Genau hier kommt Sinatra::Base Ordner, Logging, Exception Detail Seite, etc). Genau hier kommt Sinatra::Base
in das Spiel: in das Spiel:


require 'sinatra/base' require 'sinatra/base'
Expand All @@ -543,29 +543,29 @@ in das Spiel:
end end
end end


Die MyApp Klasse ist eine unabhängige Rack Komponente die als Rack Middleware, Die MyApp Klasse ist eine unabhängige Rack Komponente die als Rack Middleware,
Rack Anwendung oder als Rails metal verwendet werden kann. Rack Anwendung oder als Rails metal verwendet werden kann.
Verwendet wird sie mit +use+ oder +run+ von einer rackup +config.ru+ Datei oder Verwendet wird sie mit +use+ oder +run+ von einer rackup +config.ru+ Datei oder
als Server Komponente als Bibliothek: als Server Komponente als Bibliothek:


MyApp.run! :host => 'localhost', :port => 9090 MyApp.run! :host => 'localhost', :port => 9090


Die Methoden von der Sinatra::Base Subklasse sind genau die selben wie die Die Methoden von der Sinatra::Base Subklasse sind genau die selben wie die
über die top-level DSL möglichen. Die meisten top-level Anwendungen können zu über die top-level DSL möglichen. Die meisten top-level Anwendungen können zu
Sinatra::Base Komponenten mit 2 Veränderungen konvertiert werden: Sinatra::Base Komponenten mit 2 Veränderungen konvertiert werden:


* Die Datei sollte +sinatra/base+ und nicht aus +sinatra+; importieren * Die Datei sollte +sinatra/base+ und nicht aus +sinatra+; importieren
ansonsten werden alle von Sinatra's DSL Methoden im Namespace importiert. ansonsten werden alle von Sinatra's DSL Methoden im Namespace importiert.
* Alle Anwendungs Routen, Error Handler, Filter und Optionen in eine SubKlasse * Alle Anwendungs Routen, Error Handler, Filter und Optionen in eine SubKlasse
von Sinatra::Base. von Sinatra::Base.


+Sinatra::Base+ ist ein leeres Blatt. Die meisten Optionen sind per Standard +Sinatra::Base+ ist ein leeres Blatt. Die meisten Optionen sind per Standard
deaktiviert, das betrifft auch dem eingebauten Server. Siehe {Optionen und Konfiguration}[http://sinatra.github.com/configuration.html] für Details an möglichen Optionen. deaktiviert, das betrifft auch dem eingebauten Server. Siehe {Optionen und Konfiguration}[http://sinatra.github.com/configuration.html] für Details an möglichen Optionen.


SIDEBAR: Sinatras top-level DSL ist implementiert als einfaches Delegations SIDEBAR: Sinatras top-level DSL ist implementiert als einfaches Delegations
System. Die +Sinatra::Application+ Klasse -- ein paar spezielle SubKlassen von System. Die +Sinatra::Application+ Klasse -- ein paar spezielle SubKlassen von
Sinatra::Base -- enthält alle :get, :put, :post, :delete, :before, Sinatra::Base -- enthält alle :get, :put, :post, :delete, :before,
:error, :not_found, :configure und :set Meldungen gesendet durch den top-level. :error, :not_found, :configure und :set Meldungen gesendet durch den top-level.
Schaue am besten im Code nach: hier im {Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064] Schaue am besten im Code nach: hier im {Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064]
{inkludieren im Haupt-Namespace}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25]. {inkludieren im Haupt-Namespace}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25].


Expand Down Expand Up @@ -615,7 +615,7 @@ Um Sinatra Code in Zukunft zu aktualisieren:
* {Projekt Website}[http://sinatra.github.com/] - Ergänzende Dokumentation, * {Projekt Website}[http://sinatra.github.com/] - Ergänzende Dokumentation,
News und Links zu anderen Ressourcen. News und Links zu anderen Ressourcen.
* {helfen}[http://sinatra.github.com/contributing.html] - Einen Fehler gefunden? Brauchst du Hilfe? Hast du einen Patch? * {helfen}[http://sinatra.github.com/contributing.html] - Einen Fehler gefunden? Brauchst du Hilfe? Hast du einen Patch?
* {Lighthouse}[http://sinatra.lighthouseapp.com] - Issue tracking und Release Plan. * {Issue tracker}[http://github.com/sinatra/sinatra/issues]
* {Twitter}[http://twitter.com/sinatra] * {Twitter}[http://twitter.com/sinatra]
* {Mailing List}[http://groups.google.com/group/sinatrarb] * {Mailing List}[http://groups.google.com/group/sinatrarb]
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] auf http://freenode.net * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] auf http://freenode.net
2 changes: 1 addition & 1 deletion README.jp.rdoc
Expand Up @@ -546,7 +546,7 @@ Sinatraのソースを更新する方法:
ニュース、他のリソースへのリンクがあります。 ニュース、他のリソースへのリンクがあります。
* {プロジェクトに参加(貢献)する}[http://sinatra.github.com/contributing.html] - バグレポート * {プロジェクトに参加(貢献)する}[http://sinatra.github.com/contributing.html] - バグレポート
パッチの送信、サポートなど パッチの送信、サポートなど
* {Lighthouse}[http://sinatra.lighthouseapp.com] - チケット管理とリリース計画 * {Issue tracker}[http://github.com/sinatra/sinatra/issues] - チケット管理とリリース計画
* {Twitter}[http://twitter.com/sinatra] * {Twitter}[http://twitter.com/sinatra]
* {メーリングリスト}[http://groups.google.com/group/sinatrarb] * {メーリングリスト}[http://groups.google.com/group/sinatrarb]
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net
5 changes: 2 additions & 3 deletions README.rdoc
Expand Up @@ -152,7 +152,7 @@ Renders <tt>./views/index.erb</tt>


=== Erubis === Erubis


The erubis gem/library is required to render builder templates: The erubis gem/library is required to render erubis templates:


## You'll need to require erubis in your app ## You'll need to require erubis in your app
require 'erubis' require 'erubis'
Expand Down Expand Up @@ -640,8 +640,7 @@ To update the Sinatra sources in the future:
news, and links to other resources. news, and links to other resources.
* {Contributing}[http://www.sinatrarb.com/contributing] - Find a bug? Need * {Contributing}[http://www.sinatrarb.com/contributing] - Find a bug? Need
help? Have a patch? help? Have a patch?
* {Lighthouse}[http://sinatra.lighthouseapp.com] - Issue tracking and release * {Issue tracker}[http://github.com/sinatra/sinatra/issues]
planning.
* {Twitter}[http://twitter.com/sinatra] * {Twitter}[http://twitter.com/sinatra]
* {Mailing List}[http://groups.google.com/group/sinatrarb/topics] * {Mailing List}[http://groups.google.com/group/sinatrarb/topics]
* {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net
12 changes: 7 additions & 5 deletions lib/sinatra/base.rb
Expand Up @@ -467,7 +467,9 @@ def filter!(type, base = self.class)
def route!(base=self.class, pass_block=nil) def route!(base=self.class, pass_block=nil)
if routes = base.routes[@request.request_method] if routes = base.routes[@request.request_method]
original_params = @params original_params = @params
path = unescape(@request.path_info)
path = unescape(@request.path_info)
path = "/" if path.empty?


routes.each do |pattern, keys, conditions, block| routes.each do |pattern, keys, conditions, block|
if match = pattern.match(path) if match = pattern.match(path)
Expand Down Expand Up @@ -703,8 +705,8 @@ def set(option, value=self, &block)
metadef(option, &value) metadef(option, &value)
metadef("#{option}?") { !!__send__(option) } metadef("#{option}?") { !!__send__(option) }
metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) } metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) }
elsif value == self && option.respond_to?(:to_hash) elsif value == self && option.respond_to?(:each)
option.to_hash.each { |k,v| set(k, v) } option.each { |k,v| set(k, v) }
elsif respond_to?("#{option}=") elsif respond_to?("#{option}=")
__send__ "#{option}=", value __send__ "#{option}=", value
else else
Expand Down Expand Up @@ -947,11 +949,11 @@ def use(middleware, *args, &block)
@prototype = nil @prototype = nil
@middleware << [middleware, args, block] @middleware << [middleware, args, block]
end end

def quit!(server, handler_name) def quit!(server, handler_name)
## Use thins' hard #stop! if available, otherwise just #stop ## Use thins' hard #stop! if available, otherwise just #stop
server.respond_to?(:stop!) ? server.stop! : server.stop server.respond_to?(:stop!) ? server.stop! : server.stop
puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
end end


# Run the Sinatra app as a self-hosted server using # Run the Sinatra app as a self-hosted server using
Expand Down
12 changes: 12 additions & 0 deletions test/routing_test.rb
Expand Up @@ -84,6 +84,18 @@ class RoutingTest < Test::Unit::TestCase
assert_equal "<h1>Not Found</h1>", response.body assert_equal "<h1>Not Found</h1>", response.body
end end


it 'matches empty PATH_INFO to "/"' do
mock_app {
get '/' do
'worked'
end
}

get '/', {}, "PATH_INFO" => ""
assert ok?
assert_equal 'worked', body
end

it 'takes multiple definitions of a route' do it 'takes multiple definitions of a route' do
mock_app { mock_app {
user_agent(/Foo/) user_agent(/Foo/)
Expand Down
5 changes: 5 additions & 0 deletions test/settings_test.rb
Expand Up @@ -43,6 +43,11 @@ class SettingsTest < Test::Unit::TestCase
assert_equal 'bizzle', @base.baz assert_equal 'bizzle', @base.baz
end end


it 'sets multiple settings using #each' do
@base.set [["foo", "bar"]]
assert_equal "bar", @base.foo
end

it 'inherits settings methods when subclassed' do it 'inherits settings methods when subclassed' do
@base.set :foo, 'bar' @base.set :foo, 'bar'
@base.set :biz, Proc.new { 'baz' } @base.set :biz, Proc.new { 'baz' }
Expand Down

0 comments on commit 5556dbe

Please sign in to comment.