text:
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
require File.join(File.dirname(__FILE__), '..', '..', 'blueprints', 'blueprints')
require File.join(File.dirname(__FILE__), '..', '..', 'blueprints', 'helper')
require 'shoulda'
require 'base64'

class Api::UsersControllerTest < ActionController::TestCase

  # Testing unauthenticated requests
  context 'An unauthenticated request to api/users' do
    setup do
      # Set garbage HTTP header
      @request.env['HTTP_AUTHORIZATION'] = 'garbage http_header'
      @request.env['HTTP_ACCEPT'] = 'application/xml'
    end

    context '/index' do
      setup do
        get 'index'
      end

      should 'fail to authenticate the GET request' do
        assert_response 403
      end
    end

    context '/show' do
      setup do
        get 'show', :id => 1
      end

      should 'fail to authenticate the GET request' do
        assert_response 403
      end
    end

    context '/create' do
      setup do
        @res_create = post('create')
      end

      should 'fail to authenticate the GET request' do
        assert_response 403
      end
    end

    context '/update' do
      setup do
        put 'update', :id => 1
      end

      should 'fail to authenticate the GET request' do
        assert_response 403
      end
    end

    context '/destroy' do
      setup do
        delete 'destroy', :id => 1
      end

      should 'fail to authenticate the GET request' do
        assert_response 403
      end
    end
  end

  # Testing authenticated requests
  context 'An authenticated request to api/users' do
    setup do

      # Creates admin from blueprints.
      @admin = Admin.make
      @admin.reset_api_key
      base_encoded_md5 = @admin.api_key.strip
      auth_http_header = "MarkUsAuth #{base_encoded_md5}"
      @request.env['HTTP_AUTHORIZATION'] = auth_http_header
      @request.env['HTTP_ACCEPT'] = 'application/xml'
    end

    # Testing GET api/users
    context 'testing index function' do
      # Create three test accounts
      setup do
        @new_user1 = Student.create(:user_name => 'ApiTestStudent1',
          :last_name => 'ApiTesters', :first_name => 'ApiTesting1')
        @new_user2 = Student.create(:user_name => 'ApiTestStudent2',
          :last_name => 'ApiTesters', :first_name => 'ApiTesting2')
        @new_user3 = Student.create(:user_name => 'ApiTestStudent3',
          :last_name => 'ApiTesters3', :first_name => 'ApiTesting3')
      end

      should 'get all users in the collection if no options are used' do
        get 'index'
        assert_response :success
        assert_select 'user', User.all.size
      end

      should 'get only first 2 users if a limit of 2 is provided' do
        get 'index', :limit => '2'
        assert_response :success
        assert_select 'user', 2
        assert @response.body.include?(@admin.user_name)
        assert @response.body.include?(@new_user1.user_name)
      end

      should 'get the 3 latest users if a limit of 3 and offset of 1 is used' do
        get 'index', :limit => '3', :offset => '1'
        assert_response :success
        assert_select 'user', 3
        assert !@response.body.include?(@admin.user_name)
        assert @response.body.include?(@new_user1.user_name)
        assert @response.body.include?(@new_user2.user_name)
        assert @response.body.include?(@new_user3.user_name)
      end

      should 'get only matching users if a valid filter is used' do
        get 'index', :filter => 'last_name:ApiTesters'
        assert_response :success
        assert_select 'user', 2
        assert @response.body.include?(@new_user1.user_name)
        assert @response.body.include?(@new_user2.user_name)
      end

      should 'get only matching users if multiple valid filters are used' do
        get 'index', :filter => 'last_name:ApiTesters,first_name:ApiTesting1'
        assert_response :success
        assert_select 'user', 1
        assert @response.body.include?(@new_user1.user_name)
      end

      should 'ignore invalid filters' do
        get 'index', :filter => 'type:student,badfilter:invalid'
        assert_response :success
        assert_select 'user', 3
        assert @response.body.include?(@new_user1.user_name)
        assert @response.body.include?(@new_user2.user_name)
        assert @response.body.include?(@new_user3.user_name)
      end

      should 'use case-insensitive matching with filters' do
        get 'index', :filter => 'type:ADMIN'
        assert_response :success
        assert_select 'user', 1
        assert @response.body.include?(@admin.user_name)
      end

      should 'apply limit/offset after the filter' do
        get 'index', :filter => 'last_name:ApiTesters', :limit => '1', :offset => '1'
        assert_response :success
        assert_select 'user', 1
        assert @response.body.include?(@new_user2.user_name)
      end

      should 'display all default fields if the fields parameter is not used' do
        get 'index'
        assert_response :success
        elements = %w(first-name last-name user-name notes-count
                      grace-credits id type)
        elements.each do |element|
          assert_select element, {:minimum => 1}
        end
      end

      should 'only display specified fields if the fields parameter is used' do
        get 'index', :fields => 'first_name,last_name'
        assert_response :success
        assert_select 'first-name', {:minimum => 1}
        assert_select 'last-name', {:minimum => 1}
        elements = %w(user-name notes-count grace-credits id type)
        elements.each do |element|
          assert_select element, 0
        end
      end

      should 'ignore invalid fields provided in the fields parameter' do
        get 'index', :fields => 'first_name,invalid_field_name'
        assert_response :success
        assert_select 'first-name', {:minimum => 1}
        elements = %w(last-name user-name notes-count grace-credits
                      id type)
        elements.each do |element|
          assert_select element, 0
        end
      end
    end

    # Testing GET api/users/:id
    context 'testing show function' do
      setup do
        @user = Student.make
      end

      should 'return only that user and all default attributes if the id is valid' do
        get 'show', :id => @user.id.to_s
        assert_response :success
        assert @response.body.include?(@user.user_name)
        elements = %w(first-name last-name user-name notes-count
                      grace-credits id type)
        elements.each do |element|
          assert_select element, 1
        end
      end

      should 'return only that user and the specified fields if provided' do
        get 'show', :id => @user.id.to_s, :fields => 'first_name,user_name'
        assert_response :success
        assert @response.body.include?(@user.user_name)
        assert_select 'user-name', 1
        assert_select 'first-name', 1
        elements = %w(last-name notes-count grace-credits id type)
        elements.each do |element|
          assert_select element, 0
        end
      end

      should "return a 404 if a user with a numeric id doesn't exist" do
        get 'show', :id => '9999'
        assert_response 404
      end
    end

    # Testing application/json response
    context 'getting a json response' do
      setup do
        @request.env['HTTP_ACCEPT'] = 'application/json'
      end

      should 'be successful' do
        get 'show', :id => 'garbage'
        assert_template 'shared/http_status'
        assert_equal @response.content_type, 'application/json'
      end

      should 'not use the ActiveRecord class name as the root' do
        user = Admin.make
        get 'show', :id => user.id.to_s
        assert !@response.body.include?('{"admin":')
      end
    end

    # Testing application/xml response
    context 'getting an xml response' do
      setup do
        @request.env['HTTP_ACCEPT'] = 'application/xml'
        get 'show', :id => 'garbage'
      end

      should 'be successful' do
        assert_template 'shared/http_status'
        assert_equal @response.content_type, 'application/xml'
      end
    end

    # Testing an invalid HTTP_ACCEPT type
    context 'getting an rss response' do
      setup do
        @request.env['HTTP_ACCEPT'] = 'application/rss'
        get 'show', :id => 'garbage'
      end

      should 'not be successful' do
        assert_not_equal @response.content_type, 'application/rss'
      end
    end

    # Testing POST api/users
    context 'testing the create function with valid attributes' do
      setup do
        # Create parameters for request
        @attr = { :user_name => 'ApiTestUser', :last_name => 'Tester',
                  :first_name => 'Api', :type => 'admin' }
        # fire off request
        post 'create', :id => 1, :user_name => 'ApiTestUser', :last_name => 'Tester',
                 :first_name => 'Api', :type => 'admin'
      end

      should 'create the specified user' do
        assert_response 201
        @new_user = User.find_by_user_name(@attr[:user_name])
        assert !@new_user.nil?
        assert_equal(@new_user.last_name, @attr[:last_name])
        assert_equal(@new_user.first_name, @attr[:first_name])
        assert_equal(@new_user.type.downcase, @attr[:type])
      end
    end

    context 'testing the create function with an existing user_name to cause error' do
      setup do
        @user = Student.make
        @attr = {:user_name => @user.user_name, :last_name => 'Tester',
                 :first_name => 'Api', :type => 'admin' }
        @res = post('create', @attr)
      end

      should 'find an existing user and cause conflict' do
        assert !User.find_by_user_name(@attr[:user_name]).nil?
        assert_response :conflict
      end
    end

    context 'testing the create function with user_type set to garbage' do
      setup do
        @attr = {:user_name => 'ApiTestUser', :last_name => 'Tester',
                 :first_name => 'Api', :user_type => 'garbage' }
        @res = post('create', @attr)
      end

      should 'not be able to process user_type' do
        assert_response 422
      end
    end

    # Testing PUT api/users/:id
    context 'testing the update function' do
      setup do
        @user = Student.make
        @second_user = Student.make
      end

      should 'update those attributes that are supplied' do
        put 'update', :id => @user.id, :user_name => 'ApiTester',
            :last_name => 'ApiTestLast', :first_name => 'ApiTestFirst'
        updated_user = User.find_by_id(@user.id)
        assert_equal(updated_user.user_name, 'ApiTester')
        assert_equal(updated_user.last_name, 'ApiTestLast')
        assert_equal(updated_user.first_name, 'ApiTestFirst')
      end

      should 'not be able to use a user_name that already exists' do
        put 'update', :id => @user.id, :user_name => @second_user.user_name,
            :last_name => 'ApiTestLast', :first_name => 'ApiTestFirst'
        assert_response 409
      end

      should 'not be able to update a user that does not exist' do
        put 'update', :id => '9999', :user_name => 'RandomName'
        assert User.find_by_user_name('RandomName').nil?
        assert_response 404
      end
    end

    context 'testing that the destroy function is disabled' do
      setup do
        delete 'destroy', :id => 1
      end

      should "pretend the function doesn't exist" do
        assert_response :missing
      end
    end
  end
end


text:
/*jslint node: true */

// not sure if this is required:
/*jshint sub: true */

"use strict";

var Expression  = require('./Expression'),
    Context     = require('./Context'),
    MathError   = require('./Error'),
    language    = require('./Language/default'),
    Code        = require('./Language').Code,
    Global      = require('./global');

// Define sin, cos, tan, etc.
var defaults    = require('./global/defaults');
defaults.attach(Global);

module.exports = M;

function M(e, c) {
    return language.parse(e, c || Global);
}

M.toString = function() {
    return [
    'function M(expression, context) {',
    '    /*!',
    '     *  Math JavaScript Library v3.9.1',
    '     *  https://github.com/aantthony/javascript-cas',
    '     *  ',
    '     *  Copyright 2010 Anthony Foster. All rights reserved.',
    '     */',
    '    [awesome code]',
    '}'].join('\n');
};

M['Context']    = Context;
M['Expression'] = Expression;
M['Global']     = Global;
M['Error']      = MathError;

Expression.prototype.s = function (lang) {
    Code.language = language;
    Code.newContext();
    return this._s(Code, lang);
};
Expression.prototype.compile = function (x) {
    return this.s('text/javascript').compile(x);
}

var extensions = {};

M['register'] = function (name, installer){
    if(Expression.prototype[name]) {
        throw('Method .' + name + ' is already in use!');
    }
    extensions[name] = installer;
};

M['load'] = function(name, config) {
    extensions[name](M, Expression, config);
    delete extensions[name];
};

redpajama_set_name: RedPajamaGithub


text:
Martini ist ein mächtiges Package zur schnellen Entwicklung von modularen Webanwendungen und -services in Golang.

## Ein Projekt starten

Nach der Installation von Go und dem Einrichten des [GOPATH](http://golang.org/doc/code.html#GOPATH), erstelle Deine erste `.go`-Datei. Speichere sie unter `server.go`.

~~~ go
package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hallo Welt!"
  })
  m.Run()
}
~~~

Installiere anschließend das Martini Package (**Go 1.1** oder höher wird vorausgesetzt):
~~~
go get github.com/go-martini/martini
~~~

Starte den Server:
~~~
go run server.go
~~~

Der Martini-Webserver ist nun unter `localhost:3000` erreichbar.

## Hilfe

Abonniere den [Emailverteiler](https://groups.google.com/forum/#!forum/martini-go)

Schaue das [Demovideo](http://martini.codegangsta.io/#demo)

Stelle Fragen auf Stackoverflow mit dem [Martini-Tag](http://stackoverflow.com/questions/tagged/martini)

GoDoc [Dokumentation](http://godoc.org/github.com/go-martini/martini)

## Eigenschaften
* Sehr einfach nutzbar
* Nicht-intrusives Design
* Leicht kombinierbar mit anderen Golang Packages
* Ausgezeichnetes Path Matching und Routing
* Modulares Design - einfaches Hinzufügen und Entfernen von Funktionen
* Eine Vielzahl von guten Handlern/Middlewares nutzbar
* Großer Funktionsumfang mitgeliefert
* **Voll kompatibel mit dem [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc) Interface.**
* Standardmäßiges Ausliefern von Dateien (z.B. von AngularJS-Apps im HTML5-Modus)

## Mehr Middleware
Mehr Informationen zur Middleware und Funktionalität findest Du in den Repositories der [martini-contrib](https://github.com/martini-contrib) Gruppe.

## Inhaltsverzeichnis
* [Classic Martini](#classic-martini)
  * [Handler](#handler)
  * [Routing](#routing)
  * [Services](#services)
  * [Statische Dateien bereitstellen](#statische-dateien-bereitstellen)
* [Middleware Handler](#middleware-handler)
  * [Next()](#next)
* [Martini Env](#martini-env)
* [FAQ](#faq)

## Classic Martini
Einen schnellen Start in ein Projekt ermöglicht [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic), dessen Voreinstellungen sich für die meisten Webanwendungen eignen:
~~~ go
  m := martini.Classic()
  // ... Middleware und Routing hier einfügen
  m.Run()
~~~

Aufgelistet findest Du einige Aspekte, die [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) automatich berücksichtigt:

  * Request/Response Logging - [martini.Logger](http://godoc.org/github.com/go-martini/martini#Logger)
  * Panic Recovery - [martini.Recovery](http://godoc.org/github.com/go-martini/martini#Recovery)
  * Static File serving - [martini.Static](http://godoc.org/github.com/go-martini/martini#Static)
  * Routing - [martini.Router](http://godoc.org/github.com/go-martini/martini#Router)

### Handler
Handler sind das Herz und die Seele von Martini. Ein Handler ist grundsätzlich jede Art von aufrufbaren Funktionen:
~~~ go
m.Get("/", func() {
  println("Hallo Welt")
})
~~~

#### Rückgabewerte
Wenn ein Handler Rückgabewerte beinhaltet, übergibt Martini diese an den aktuellen [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) in Form eines String:
~~~ go
m.Get("/", func() string {
  return "Hallo Welt" // HTTP 200 : "Hallo Welt"
})
~~~

Die Rückgabe eines Statuscode ist optional:
~~~ go
m.Get("/", func() (int, string) {
  return 418, "Ich bin eine Teekanne" // HTTP 418 : "Ich bin eine Teekanne"
})
~~~

#### Service Injection
Handler werden per Reflection aufgerufen. Martini macht Gebrauch von *Dependency Injection*, um Abhängigkeiten in der Argumentliste von Handlern aufzulösen. **Dies macht Martini komplett kompatibel mit Golangs `http.HandlerFunc` Interface.**

Fügst Du einem Handler ein Argument hinzu, sucht Martini in seiner Liste von Services und versucht, die Abhängigkeiten via Type Assertion aufzulösen.
~~~ go
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res und req wurden von Martini injiziert
  res.WriteHeader(200) // HTTP 200
})
~~~

Die Folgenden Services sind Bestandteil von [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic):

  * [*log.Logger](http://godoc.org/log#Logger) - Globaler Logger für Martini.
  * [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) - http request context.
  * [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) - `map[string]string` von benannten Parametern, welche durch Route Matching gefunden wurden.
  * [martini.Routes](http://godoc.org/github.com/go-martini/martini#Routes) - Routen Hilfeservice.
  * [martini.Route](http://godoc.org/github.com/go-martini/martini#Route) - Aktuelle, aktive Route.
  * [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer interface.
  * [*http.Request](http://godoc.org/net/http/#Request) - http Request.

### Routing
Eine Route ist in Martini eine HTTP-Methode gepaart mit einem URL-Matching-Pattern. Jede Route kann eine oder mehrere Handler-Methoden übernehmen:
~~~ go
m.Get("/", func() {
  // zeige etwas an
})

m.Patch("/", func() {
  // aktualisiere etwas
})

m.Post("/", func() {
  // erstelle etwas
})

m.Put("/", func() {
  // ersetze etwas
})

m.Delete("/", func() {
  // lösche etwas
})

m.Options("/", func() {
  // HTTP-Optionen
})

m.NotFound(func() {
  // bearbeite 404-Fehler
})
~~~

Routen werden in der Reihenfolge, in welcher sie definiert wurden, zugeordnet. Die bei einer Anfrage zuerst zugeordnete Route wird daraufhin aufgerufen.

Routenmuster enthalten ggf. benannte Parameter, die über den [martini.Params](http://godoc.org/github.com/go-martini/martini#Params) Service abrufbar sind:
~~~ go
m.Get("/hello/:name", func(params martini.Params) string {
  return "Hallo " + params["name"]
})
~~~

Routen können mit Globs versehen werden:
~~~ go
m.Get("/hello/**", func(params martini.Params) string {
  return "Hallo " + params["_1"]
})
~~~

Reguläre Ausdrücke sind ebenfalls möglich:
~~~go
m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hallo %s", params["name"])
})
~~~
Weitere Informationen zum Syntax regulärer Ausdrücke findest Du in der [Go Dokumentation](http://golang.org/pkg/regexp/syntax/).

Routen-Handler können auch ineinander verschachtelt werden. Dies ist bei der Authentifizierung und den Berechtigungen nützlich.
~~~ go
m.Get("/secret", authorize, func() {
  // wird ausgeführt, solange authorize nichts zurückgibt
})
~~~

Routengruppen können durch die Group-Methode hinzugefügt werden.
~~~ go
m.Group("/books", func(r martini.Router) {
    r.Get("/:id", GetBooks)
    r.Post("/new", NewBook)
    r.Put("/update/:id", UpdateBook)
    r.Delete("/delete/:id", DeleteBook)
})
~~~

Sowohl Handlern als auch Middlewares können Gruppen übergeben werden.
~~~ go
m.Group("/books", func(r martini.Router) {
    r.Get("/:id", GetBooks)
    r.Post("/new", NewBook)
    r.Put("/update/:id", UpdateBook)
    r.Delete("/delete/:id", DeleteBook)
}, MyMiddleware1, MyMiddleware2)
~~~

### Services
Services sind Objekte, welche der Argumentliste von Handlern beigefügt werden können.
Du kannst einem Service der *Global* oder *Request* Ebene zuordnen.

#### Global Mapping
Eine Martini-Instanz implementiert das inject.Injector Interface, sodass ein Service leicht zugeordnet werden kann:
~~~ go
db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // der Service ist allen Handlern unter *MyDatabase verfügbar
// ...
m.Run()
~~~

#### Request-Level Mapping
Das Zuordnen auf der Request-Ebene kann in einem Handler via  [martini.Context](http://godoc.org/github.com/go-martini/martini#Context) realisiert werden:
~~~ go
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // zugeordnet als *MyCustomLogger
}
~~~

#### Werten einem Interface zuordnen
Einer der mächtigsten Aspekte von Services ist dessen Fähigkeit, einen Service einem Interface zuzuordnen. Möchtest Du den [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) mit einem Decorator (Objekt) und dessen Zusatzfunktionen überschreiben, definiere den Handler wie folgt:
~~~ go
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // überschribe ResponseWriter mit dem  ResponseWriter Decorator
}
~~~

### Statische Dateien bereitstellen
Eine [martini.Classic()](http://godoc.org/github.com/go-martini/martini#Classic) Instanz übertragt automatisch statische Dateien aus dem "public"-Ordner im Stammverzeichnis Deines Servers. Dieses Verhalten lässt sich durch weitere [martini.Static](http://godoc.org/github.com/go-martini/martini#Static) Handler auf andere Verzeichnisse übertragen.
~~~ go
m.Use(martini.Static("assets")) // überträgt auch vom "assets"-Verzeichnis
~~~

#### Eine voreingestelle Datei übertragen
Du kannst die URL zu einer lokalen Datei angeben, sollte die URL einer Anfrage nicht gefunden werden. Durch einen Präfix können bestimmte URLs ignoriert werden.
Dies ist für Server nützlich, welche statische Dateien übertragen und ggf. zusätzliche Handler defineren (z.B. eine REST-API). Ist dies der Fall, so ist das Anlegen eines Handlers in der NotFound-Reihe nützlich.

Das gezeigte Beispiel zeigt die `/index.html` immer an, wenn die angefrage URL keiner lokalen Datei zugeordnet werden kann bzw. wenn sie nicht mit `/api/v` beginnt:
~~~ go
static := martini.Static("assets", martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
m.NotFound(static, http.NotFound)
~~~

## Middleware Handler
Middleware-Handler befinden sich logisch zwischen einer Anfrage via HTTP und dem Router. Im wesentlichen unterscheiden sie sich nicht von anderen Handlern in Martini.
Du kannst einen Middleware-Handler dem Stack folgendermaßen anfügen:
~~~ go
m.Use(func() {
  // durchlaufe die Middleware
})
~~~

Volle Kontrolle über den Middleware Stack erlangst Du mit der `Handlers`-Funktion.
Sie ersetzt jeden zuvor definierten Handler:
~~~ go
m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)
~~~

Middleware Handler arbeiten gut mit Aspekten wie Logging, Berechtigungen, Authentifizierung, Sessions, Komprimierung durch gzip, Fehlerseiten und anderen Operationen zusammen, die vor oder nach einer Anfrage passieren.
~~~ go
// überprüfe einen API-Schlüssel
m.Use(func(res http.ResponseWriter, req *http.Request) {
  if req.Header.Get("X-API-KEY") != "secret123" {
    res.WriteHeader(http.StatusUnauthorized)
  }
})
~~~

### Next()
[Context.Next()](http://godoc.org/github.com/go-martini/martini#Context) ist eine optionale Funktion, die Middleware-Handler aufrufen können, um sie nach dem Beenden der anderen Handler auszuführen. Dies funktioniert besonders gut, wenn Operationen nach einer HTTP-Anfrage ausgeführt werden müssen.
~~~ go
// protokolliere vor und nach einer Anfrage
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("vor einer Anfrage")

  c.Next()

  log.Println("nach einer Anfrage")
})
~~~

## Martini Env

Einige Martini-Handler machen von der globalen `martini.Env` Variable gebrauch, die der Entwicklungsumgebung erweiterte Funktionen bietet, welche die Produktivumgebung nicht enthält. Es wird empfohlen, die `MARTINI_ENV=production` Umgebungsvariable zu setzen, sobald der Martini-Server in den Live-Betrieb übergeht.

## FAQ

### Wo finde ich eine bestimmte Middleware?

Starte die Suche mit einem Blick in die Projekte von [martini-contrib](https://github.com/martini-contrib). Solltest Du nicht fündig werden, kontaktiere ein Mitglied des martini-contrib Teams, um eine neue Repository anzulegen.

 * [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler zum Parsen des `Accept-Language` HTTP-Header.
 * [accessflags](https://github.com/martini-contrib/accessflags) - Handler zur Ermöglichung von Zugriffskontrollen.
 * [auth](https://github.com/martini-contrib/auth) - Handler zur Authentifizierung.
 * [binding](https://github.com/martini-contrib/binding) - Handler zum Zuordnen/Validieren einer Anfrage zu einem Struct.
 * [cors](https://github.com/martini-contrib/cors) - Handler für CORS-Support.
 * [csrf](https://github.com/martini-contrib/csrf) - CSRF-Schutz für Applikationen
 * [encoder](https://github.com/martini-contrib/encoder) - Enkodierungsservice zum Datenrendering in den verschiedensten Formaten.
 * [gzip](https://github.com/martini-contrib/gzip) - Handler zum Ermöglichen von gzip-Kompression bei HTTP-Anfragen.
 * [gorelic](https://github.com/martini-contrib/gorelic) - NewRelic Middleware
 * [logstasher](https://github.com/martini-contrib/logstasher) - Middlewaredie Logstashkompatibles JSON ausgibt
 * [method](https://github.com/martini-contrib/method) - Überschreibe eine HTTP-Method via Header oder Formularfelder.
 * [oauth2](https://github.com/martini-contrib/oauth2) - Handler der den Login mit OAuth 2.0 in Martinianwendungen ermöglicht. Google Sign-in, Facebook Connect und Github werden ebenfalls unterstützt.
 * [permissions2](https://github.com/xyproto/permissions2) - Handler zum Mitverfolgen von Benutzern, Loginstatus und Berechtigungen.
 * [render](https://github.com/martini-contrib/render) - Handler, der einen einfachen Service zum Rendern von JSON und HTML-Templates bereitstellt.
 * [secure](https://github.com/martini-contrib/secure) - Implementation von Sicherheitsfunktionen
 * [sessions](https://github.com/martini-contrib/sessions) - Handler mit einem Session service.
 * [sessionauth](https://github.com/martini-contrib/sessionauth) - Handler zur einfachen Aufforderung eines Logins für Routes und zur Bearbeitung von Benutzerlogins in der Sitzung
 * [strict](https://github.com/martini-contrib/strict) - Strikter Modus.
 * [strip](https://github.com/martini-contrib/strip) - URL-Prefix Stripping.
 * [staticbin](https://github.com/martini-contrib/staticbin) - Handler for serving static files from binary data
 * [throttle](https://github.com/martini-contrib/throttle) - Middleware zum Drosseln von HTTP-Anfragen.
 * [vauth](https://github.com/rafecolton/vauth) - Handler zur Webhook-Authentifizierung (momentan nur GitHub und TravisCI)
 * [web](https://github.com/martini-contrib/web) - hoisie web.go's Kontext

### Wie integriere ich in bestehende Systeme?

Eine Martiniinstanz implementiert `http.Handler`, sodass Subrouten in bestehenden Servern einfach genutzt werden können. Hier ist eine funktionierende Martinianwendungen für die Google App Engine:

~~~ go
package hello

import (
  "net/http"
  "github.com/go-martini/martini"
)

func init() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hallo Welt!"
  })
  http.Handle("/", m)
}
~~~

### Wie ändere ich den Port/Host?

Martinis `Run` Funktion sucht automatisch nach den PORT und HOST Umgebungsvariablen, um diese zu nutzen. Andernfalls ist localhost:3000 voreingestellt.
Für mehr Flexibilität über den Port und den Host nutze stattdessen die `martini.RunOnAddr` Funktion.

~~~ go
  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))
~~~

### Automatisches Aktualisieren?

[Gin](https://github.com/codegangsta/gin) und [Fresh](https://github.com/pilu/fresh) aktualisieren Martini-Apps live.

## Bei Martini mitwirken

Martinis Maxime ist Minimalismus und sauberer Code. Die meisten Beiträge sollten sich in den Repositories der [martini-contrib](https://github.com/martini-contrib) Gruppe wiederfinden. Beinhaltet Dein Beitrag Veränderungen am Kern von Martini, zögere nicht, einen Pull Request zu machen.

## Über das Projekt

Inspiriert von [Express](https://github.com/visionmedia/express) und [Sinatra](https://github.com/sinatra/sinatra)

Martini wird leidenschaftlich von niemand Geringerem als dem [Code Gangsta](http://codegangsta.io/) entwickelt


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<title>FFI Tutorial</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Mike Pall">
<meta name="Copyright" content="Copyright (C) 2005-2013, Mike Pall">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">

LuaJIT

FFI Tutorial

LuaJIT

Download »

Installation

Running

Extensions

FFI Library

FFI Tutorial

ffi.* API

FFI Semantics

jit.* Library

Lua/C API

Status

Changes

FAQ

Performance »

Wiki »

Mailing List »

This page is intended to give you an overview of the features of the FFI
library by presenting a few use cases and guidelines.

This page makes no attempt to explain all of the FFI library, though.
You'll want to have a look at the ffi.* API
function reference and the FFI
semantics to learn more.

Loading the FFI Library

The FFI library is built into LuaJIT by default, but it's not loaded
and initialized by default. The suggested way to use the FFI library
is to add the following to the start of every Lua file that needs one
of its functions:

local ffi = require("ffi")

Please note this doesn't define an <tt>ffi</tt> variable in the table
of globals — you really need to use the local variable. The
<tt>require</tt> function ensures the library is only loaded once.

Note: If you want to experiment with the FFI from the interactive prompt
of the command line executable, omit the <tt>local</tt>, as it doesn't
preserve local variables across lines.

Accessing Standard System Functions

The following code explains how to access standard system functions.
We slowly print two lines of dots by sleeping for 10 milliseconds
after each dot:

①

②
③
④

⑤

⑥local ffi = require("ffi")
ffi.cdef[[
void Sleep(int ms);
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
]]

local sleep
if ffi.os == "Windows" then
  function sleep(s)
    ffi.C.Sleep(s*1000)
  end
else
  function sleep(s)
    ffi.C.poll(nil, 0, s*1000)
  end
end

for i=1,160 do
  io.write("."); io.flush()
  sleep(0.01)
end
io.write("\n")

Here's the step-by-step explanation:

① This defines the
C library functions we're going to use. The part inside the
double-brackets (in green) is just standard C syntax. You can
usually get this info from the C header files or the
documentation provided by each C library or C compiler.

② The difficulty we're
facing here, is that there are different standards to choose from.
Windows has a simple <tt>Sleep()</tt> function. On other systems there
are a variety of functions available to achieve sub-second sleeps, but
with no clear consensus. Thankfully <tt>poll()</tt> can be used for
this task, too, and it's present on most non-Windows systems. The
check for <tt>ffi.os</tt> makes sure we use the Windows-specific
function only on Windows systems.

③ Here we're wrapping the
call to the C function in a Lua function. This isn't strictly
necessary, but it's helpful to deal with system-specific issues only
in one part of the code. The way we're wrapping it ensures the check
for the OS is only done during initialization and not for every call.

④ A more subtle point is
that we defined our <tt>sleep()</tt> function (for the sake of this
example) as taking the number of seconds, but accepting fractional
seconds. Multiplying this by 1000 gets us milliseconds, but that still
leaves it a Lua number, which is a floating-point value. Alas, the
<tt>Sleep()</tt> function only accepts an integer value. Luckily for
us, the FFI library automatically performs the conversion when calling
the function (truncating the FP value towards zero, like in C).

Some readers will notice that <tt>Sleep()</tt> is part of
<tt>KERNEL32.DLL</tt> and is also a <tt>stdcall</tt> function. So how
can this possibly work? The FFI library provides the <tt>ffi.C</tt>
default C library namespace, which allows calling functions from
the default set of libraries, like a C compiler would. Also, the
FFI library automatically detects <tt>stdcall</tt> functions, so you
don't need to declare them as such.

⑤ The <tt>poll()</tt>
function takes a couple more arguments we're not going to use. You can
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
for the <tt>nfds</tt> parameter. Please note that the
number <tt>0</tt> does not convert to a pointer value,
unlike in C++. You really have to pass pointers to pointer arguments
and numbers to number arguments.

The page on FFI semantics has all
of the gory details about
conversions between Lua
objects and C types. For the most part you don't have to deal
with this, as it's performed automatically and it's carefully designed
to bridge the semantic differences between Lua and C.

⑥ Now that we have defined
our own <tt>sleep()</tt> function, we can just call it from plain Lua
code. That wasn't so bad, huh? Turning these boring animated dots into
a fascinating best-selling game is left as an exercise for the reader.
:-)

Accessing the zlib Compression Library

The following code shows how to access the zlib compression library from Lua code.
We'll define two convenience wrapper functions that take a string and
compress or uncompress it to another string:

①

②

③

④

⑤

⑥

⑦local ffi = require("ffi")
ffi.cdef[[
unsigned long compressBound(unsigned long sourceLen);
int compress2(uint8_t *dest, unsigned long *destLen,
	      const uint8_t *source, unsigned long sourceLen, int level);
int uncompress(uint8_t *dest, unsigned long *destLen,
	       const uint8_t *source, unsigned long sourceLen);
]]
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")

local function compress(txt)
  local n = zlib.compressBound(#txt)
  local buf = ffi.new("uint8_t[?]", n)
  local buflen = ffi.new("unsigned long[1]", n)
  local res = zlib.compress2(buf, buflen, txt, #txt, 9)
  assert(res == 0)
  return ffi.string(buf, buflen[0])
end

local function uncompress(comp, n)
  local buf = ffi.new("uint8_t[?]", n)
  local buflen = ffi.new("unsigned long[1]", n)
  local res = zlib.uncompress(buf, buflen, comp, #comp)
  assert(res == 0)
  return ffi.string(buf, buflen[0])
end

-- Simple test code.
local txt = string.rep("abcd", 1000)
print("Uncompressed size: ", #txt)
local c = compress(txt)
print("Compressed size: ", #c)
local txt2 = uncompress(c, #txt)
assert(txt2 == txt)

Here's the step-by-step explanation:

① This defines some of the
C functions provided by zlib. For the sake of this example, some
type indirections have been reduced and it uses the pre-defined
fixed-size integer types, while still adhering to the zlib API/ABI.

② This loads the zlib shared
library. On POSIX systems it's named <tt>libz.so</tt> and usually
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
missing standard prefixes/suffixes, we can simply load the
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
you'll have to download it first from the
» zlib site. The check for
<tt>ffi.os</tt> makes sure we pass the right name to
<tt>ffi.load()</tt>.

③ First, the maximum size of
the compression buffer is obtained by calling the
<tt>zlib.compressBound</tt> function with the length of the
uncompressed string. The next line allocates a byte buffer of this
size. The <tt>[?]</tt> in the type specification indicates a
variable-length array (VLA). The actual number of elements of this
array is given as the 2nd argument to <tt>ffi.new()</tt>.

④ This may look strange at
first, but have a look at the declaration of the <tt>compress2</tt>
function from zlib: the destination length is defined as a pointer!
This is because you pass in the maximum buffer size and get back the
actual length that was used.

In C you'd pass in the address of a local variable
(<tt>&buflen</tt>). But since there's no address-of operator in
Lua, we'll just pass in a one-element array. Conveniently it can be
initialized with the maximum buffer size in one step. Calling the
actual <tt>zlib.compress2</tt> function is then straightforward.

⑤ We want to return the
compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>.
It needs a pointer to the start of the data and the actual length. The
length has been returned in the <tt>buflen</tt> array, so we'll just
get it from there.

Note that since the function returns now, the <tt>buf</tt> and
<tt>buflen</tt> variables will eventually be garbage collected. This
is fine, because <tt>ffi.string()</tt> has copied the contents to a
newly created (interned) Lua string. If you plan to call this function
lots of times, consider reusing the buffers and/or handing back the
results in buffers instead of strings. This will reduce the overhead
for garbage collection and string interning.

⑥ The <tt>uncompress</tt>
functions does the exact opposite of the <tt>compress</tt> function.
The compressed data doesn't include the size of the original string,
so this needs to be passed in. Otherwise no surprises here.

⑦ The code, that makes use
of the functions we just defined, is just plain Lua code. It doesn't
need to know anything about the LuaJIT FFI — the convenience
wrapper functions completely hide it.

One major advantage of the LuaJIT FFI is that you are now able to
write those wrappers in Lua. And at a fraction of the time it
would cost you to create an extra C module using the Lua/C API.
Many of the simpler C functions can probably be used directly
from your Lua code, without any wrappers.

Side note: the zlib API uses the <tt>long</tt> type for passing
lengths and sizes around. But all those zlib functions actually only
deal with 32 bit values. This is an unfortunate choice for a
public API, but may be explained by zlib's history — we'll just
have to deal with it.

First, you should know that a <tt>long</tt> is a 64 bit type e.g.
on POSIX/x64 systems, but a 32 bit type on Windows/x64 and on
32 bit systems. Thus a <tt>long</tt> result can be either a plain
Lua number or a boxed 64 bit integer cdata object, depending on
the target system.

Ok, so the <tt>ffi.*</tt> functions generally accept cdata objects
wherever you'd want to use a number. That's why we get a away with
passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua
library functions or modules don't know how to deal with this. So for
maximum portability one needs to use <tt>tonumber()</tt> on returned
<tt>long</tt> results before passing them on. Otherwise the
application might work on some systems, but would fail in a POSIX/x64
environment.

Defining Metamethods for a C Type

The following code explains how to define metamethods for a C type.
We define a simple point type and add some operations to it:

①

②

③

④

⑤

⑥local ffi = require("ffi")
ffi.cdef[[
typedef struct { double x, y; } point_t;
]]

local point
local mt = {
  __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
  __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
  __index = {
    area = function(a) return a.x*a.x + a.y*a.y end,
  },
}
point = ffi.metatype("point_t", mt)

local a = point(3, 4)
print(a.x, a.y)  --> 3  4
print(#a)        --> 5
print(a:area())  --> 25
local b = a + point(0.5, 8)
print(#b)        --> 12.5

Here's the step-by-step explanation:

① This defines the C type for a
two-dimensional point object.

② We have to declare the variable
holding the point constructor first, because it's used inside of a
metamethod.

③ Let's define an <tt>__add</tt>
metamethod which adds the coordinates of two points and creates a new
point object. For simplicity, this function assumes that both arguments
are points. But it could be any mix of objects, if at least one operand
is of the required type (e.g. adding a point plus a number or vice
versa). Our <tt>__len</tt> metamethod returns the distance of a point to
the origin.

④ If we run out of operators, we can
define named methods, too. Here the <tt>__index</tt> table defines an
<tt>area</tt> function. For custom indexing needs, one might want to
define <tt>__index</tt> and <tt>__newindex</tt> functions instead.

⑤ This associates the metamethods with
our C type. This only needs to be done once. For convenience, a
constructor is returned by
<tt>ffi.metatype()</tt>.
We're not required to use it, though. The original C type can still
be used e.g. to create an array of points. The metamethods automatically
apply to any and all uses of this type.

Please note that the association with a metatable is permanent and
the metatable must not be modified afterwards! Ditto for the
<tt>__index</tt> table.

⑥ Here are some simple usage examples
for the point type and their expected results. The pre-defined
operations (such as <tt>a.x</tt>) can be freely mixed with the newly
defined metamethods. Note that <tt>area</tt> is a method and must be
called with the Lua syntax for methods: <tt>a:area()</tt>, not
<tt>a.area()</tt>.

The C type metamethod mechanism is most useful when used in
conjunction with C libraries that are written in an object-oriented
style. Creators return a pointer to a new instance and methods take an
instance pointer as the first argument. Sometimes you can just point
<tt>__index</tt> to the library namespace and <tt>__gc</tt> to the
destructor and you're done. But often enough you'll want to add
convenience wrappers, e.g. to return actual Lua strings or when
returning multiple values.

Some C libraries only declare instance pointers as an opaque
<tt>void *</tt> type. In this case you can use a fake type for all
declarations, e.g. a pointer to a named (incomplete) struct will do:
<tt>typedef struct foo_type *foo_handle</tt>. The C side doesn't
know what you declare with the LuaJIT FFI, but as long as the underlying
types are compatible, everything still works.

Translating C Idioms

Here's a list of common C idioms and their translation to the
LuaJIT FFI:

Idiom
C code
Lua code

Pointer dereference
<tt>int *p;</tt>	<tt>x = *p;
*p = y;</tt>	<tt>x = p[0]
p[0] = y</tt>

Pointer indexing
<tt>int i, *p;</tt>	<tt>x = p[i];
p[i+1] = y;</tt>	<tt>x = p[i]
p[i+1] = y</tt>

Array indexing
<tt>int i, a[];</tt>	<tt>x = a[i];
a[i+1] = y;</tt>	<tt>x = a[i]
a[i+1] = y</tt>

<tt>struct</tt>/<tt>union</tt> dereference
<tt>struct foo s;</tt>	<tt>x = s.field;
s.field = y;</tt>	<tt>x = s.field
s.field = y</tt>

<tt>struct</tt>/<tt>union</tt> pointer deref.
<tt>struct foo *sp;</tt>	<tt>x = sp->field;
sp->field = y;</tt>	<tt>x = s.field
s.field = y</tt>

Pointer arithmetic
<tt>int i, *p;</tt>	<tt>x = p + i;
y = p - i;</tt>	<tt>x = p + i
y = p - i</tt>

Pointer difference
<tt>int *p1, *p2;</tt>	<tt>x = p1 - p2;</tt>	<tt>x = p1 - p2</tt>

Array element pointer
<tt>int i, a[];</tt>	<tt>x = &a[i];</tt>	<tt>x = a+i</tt>

Cast pointer to address
<tt>int *p;</tt>	<tt>x = (intptr_t)p;</tt>	<tt>x = tonumber(
 ffi.cast("intptr_t",
          p))</tt>

Functions with outargs
<tt>void foo(int *inoutlen);</tt>	<tt>int len = x;
foo(&len);
y = len;</tt>	<tt>local len =
  ffi.new("int[1]", x)
foo(len)
y = len[0]</tt>

Vararg conversions
<tt>int printf(char *fmt, ...);</tt>	<tt>printf("%g", 1.0);
printf("%d", 1);
 </tt>	<tt>printf("%g", 1);
printf("%d",
  ffi.new("int", 1))</tt>

To Cache or Not to Cache

It's a common Lua idiom to cache library functions in local variables
or upvalues, e.g.:

local byte, char = string.byte, string.char
local function foo(x)
  return char(byte(x)+1)
end

This replaces several hash-table lookups with a (faster) direct use of
a local or an upvalue. This is less important with LuaJIT, since the
JIT compiler optimizes hash-table lookups a lot and is even able to
hoist most of them out of the inner loops. It can't eliminate
all of them, though, and it saves some typing for often-used
functions. So there's still a place for this, even with LuaJIT.

The situation is a bit different with C function calls via the
FFI library. The JIT compiler has special logic to eliminate all
of the lookup overhead for functions resolved from a
C library namespace!
Thus it's not helpful and actually counter-productive to cache
individual C functions like this:

local funca, funcb = ffi.C.funcb, ffi.C.funcb -- Not helpful!
local function foo(x, n)
  for i=1,n do funcb(funca(x, i), 1) end
end

This turns them into indirect calls and generates bigger and slower
machine code. Instead you'll want to cache the namespace itself and
rely on the JIT compiler to eliminate the lookups:

local C = ffi.C          -- Instead use this!
local function foo(x, n)
  for i=1,n do C.funcb(C.funca(x, i), 1) end
end

This generates both shorter and faster code. So don't cache
C functions, but do cache namespaces! Most often the
namespace is already in a local variable at an outer scope, e.g. from
<tt>local lib = ffi.load(...)</tt>. Note that copying
it to a local variable in the function scope is unnecessary.

Copyright © 2005-2013 Mike Pall

·
Contact


text:
    <div data-bb-type="title" data-bb-caption="User Interface `title.example`" i18n="true">

`fs`

Use in script:

Show zh-CN string

Your Name:

                <input type="text"  i18n="true" value="Hello World `title`"/>


text:
#include <aws/dynamodb/model/UpdateTableRequest.h>
#include <aws/core/utils/json/JsonSerializer.h>

#include <utility>

using namespace Aws::DynamoDB::Model;
using namespace Aws::Utils::Json;
using namespace Aws::Utils;

UpdateTableRequest::UpdateTableRequest() :
    m_attributeDefinitionsHasBeenSet(false),
    m_tableNameHasBeenSet(false),
    m_provisionedThroughputHasBeenSet(false),
    m_globalSecondaryIndexUpdatesHasBeenSet(false),
    m_streamSpecificationHasBeenSet(false)
{
}

Aws::String UpdateTableRequest::SerializePayload() const
{
  JsonValue payload;

  if(m_attributeDefinitionsHasBeenSet)
  {
   Array<JsonValue> attributeDefinitionsJsonList(m_attributeDefinitions.size());
   for(unsigned attributeDefinitionsIndex = 0; attributeDefinitionsIndex < attributeDefinitionsJsonList.GetLength(); ++attributeDefinitionsIndex)
   {
     attributeDefinitionsJsonList[attributeDefinitionsIndex].AsObject(m_attributeDefinitions[attributeDefinitionsIndex].Jsonize());
   }
   payload.WithArray("AttributeDefinitions", std::move(attributeDefinitionsJsonList));

  }

  if(m_tableNameHasBeenSet)
  {
   payload.WithString("TableName", m_tableName);

  }

  if(m_provisionedThroughputHasBeenSet)
  {
   payload.WithObject("ProvisionedThroughput", m_provisionedThroughput.Jsonize());

  }

  if(m_globalSecondaryIndexUpdatesHasBeenSet)
  {
   Array<JsonValue> globalSecondaryIndexUpdatesJsonList(m_globalSecondaryIndexUpdates.size());
   for(unsigned globalSecondaryIndexUpdatesIndex = 0; globalSecondaryIndexUpdatesIndex < globalSecondaryIndexUpdatesJsonList.GetLength(); ++globalSecondaryIndexUpdatesIndex)
   {
     globalSecondaryIndexUpdatesJsonList[globalSecondaryIndexUpdatesIndex].AsObject(m_globalSecondaryIndexUpdates[globalSecondaryIndexUpdatesIndex].Jsonize());
   }
   payload.WithArray("GlobalSecondaryIndexUpdates", std::move(globalSecondaryIndexUpdatesJsonList));

  }

  if(m_streamSpecificationHasBeenSet)
  {
   payload.WithObject("StreamSpecification", m_streamSpecification.Jsonize());

  }

  return payload.WriteReadable();
}

Aws::Http::HeaderValueCollection UpdateTableRequest::GetRequestSpecificHeaders() const
{
  Aws::Http::HeaderValueCollection headers;
  headers.insert(Aws::Http::HeaderValuePair("X-Amz-Target", "DynamoDB_20120810.UpdateTable"));
  return headers;

}


text:
using System;
using System.Linq;
using System.Linq.Expressions;
using LinqToDB;
using LinqToDB.Mapping;
using NUnit.Framework;

namespace Tests.UserTests
{
	[TestFixture]
	public class Issue1974Tests : TestBase
	{
		public class Person1974
		{
			[Column]
			public int ID {get; set;}

			[Column]
			public string? Name {get; set;}

			[Association(QueryExpressionMethod = nameof(ArticleExpr), CanBeNull = true, Relationship = Relationship.OneToOne)]
			public Article? BoughtQuery {get; set; }

			[Association(ThisKey = nameof(ID), OtherKey = nameof(Article.PersonId), CanBeNull = true, Relationship = Relationship.OneToOne)]
			public Article? Bought {get; set; }

			public static Expression<Func<Person1974, IDataContext, IQueryable<Article>>> ArticleExpr()
			{
				return (p, db) => db.GetTable<Article>().Where(a => a.PersonId == p.ID);
			}
		}

		public class Article
		{
			[Column]
			public string? ID {get; set;}

			[Column]
			public int PersonId {get; set;}

			[Column]
			public double Price {get; set;}
		}

		[Test]
		public void SelectAssociations([IncludeDataSources(TestProvName.AllSQLite)] string context)
		{
			using (var db = GetDataContext(context))
			using (db.CreateLocalTable(new []
			{
				new Person1974{ID = 1, Name = "Person1"},
				new Person1974{ID = 2, Name = "Person2"}
			}))
			using (db.CreateLocalTable(new []
			{
				new Article{ID = "Article", PersonId = 2},
			}))
			{
				var items = db.GetTable<Person1974>().LoadWith(p => p.Bought).LoadWith(p => p.BoughtQuery).ToArray();

				Assert.That(items[0].Bought,      Is.Null);
				Assert.That(items[0].BoughtQuery, Is.Null);

				Assert.That(items[1].Bought!.ID,      Is.EqualTo("Article"));
				Assert.That(items[1].BoughtQuery!.ID, Is.EqualTo("Article"));
			}
		}
	}
}


text:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <title>use (Configuration::CSC)</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  <link rel="stylesheet" href="../../.././rdoc-style.css" type="text/css" media="screen" />

# File lib/albacore/config/cscconfig.rb, line 24
    def use(netversion)
      self.command = File.join(get_net_version(netversion), "csc.exe")
    end


text:
/**
 * Created by 166878 on 14.11.2016.
 */

function GetCertTable(){
    $(".certificate_row").remove();
    $(".table-loader").removeClass("hidden");
    $("#total-sum").html(0);
    var cert_status = 4;
    var user_id= $("#cert_table").attr("data-id-user");
    var percent = parseInt($("#cert_table").attr("data-user-percent"));
    if (isNaN(percent) || (percent<0) || (percent>100)){
        percent = 0
    }
    var fields = JSON.stringify(["ID_Sertificate", "name", "last_name", "phone_number", "flight_type", "price"]);
    var criteria = JSON.stringify({ "ID_SertState": [cert_status], "ID_User" : [user_id], "ID_CertificatePack":[null]});
    var sort = JSON.stringify({"ID_Sertificate":["ASC"]});

    jQuery.post("/certificate/select", {field_names : fields, criteria : criteria, sort : sort}, function (data) {
        console.log(data);
        $(".table-loader").addClass("hidden");
        if (data.length == 0){
            $("#cert_table").append(
                "
Подходящих сертификатов нет
"
            );
        }
        else {
            data.forEach(function (item) {
                var name = "", last_name = "", phone_number = "";
                var flight_type = "", price = 0;
                if (item.name) {
                    name = item.name;
                }
                if (item.last_name) {
                    last_name = item.last_name;
                }
                if (item.phone_number) {
                    phone_number = item.phone_number;
                }
                if (item.flight_type) {
                    flight_type = item.flight_type;
                }
                if (item.price) {
                    price = parseInt(item.price) * (1 - percent / 100);
                }
                $("#cert_table").append(
                    "
" +
                    "<input style='cursor:pointer;' onclick='event.cancelBubble=true;' onchange='IncreaseTotal(this)' type='checkbox' autocomplete='off' class='cert_checkbox' data-cert_id='" + item.ID_Sertificate + "' data-price='"+price+"'>	" +
                    "" + item.ID_Sertificate + "	" +
                    "" + name + " " + last_name + "	" +
                    "" + phone_number + "	" +
                    "" + price + " р.	" +
                    "" + flight_type + "	" +
                    "
"
                )
            });
        }

    })
}

function IncreaseTotal(data) {
    var total_sum = parseInt($("#total-sum").html());
    if ($(data).prop("checked")){
        total_sum += parseInt($(data).attr("data-price"))
    }
    else {
        total_sum -= parseInt($(data).attr("data-price"))
    }
    $("#total-sum").html(total_sum);
}

function mark_all() {
    $(".cert_checkbox").prop("checked",true);
    var selector = $(".cert_checkbox");
    var total_sum = 0;
    for (var i = 0; i<selector.length; ++i){
        total_sum += parseInt($(selector[i]).attr("data-price"));
    }
    $("#total-sum").html(total_sum);
}

function unmark_all() {
    $(".cert_checkbox").prop("checked",false);
    $("#total-sum").html(0);
}

function mark(data) {
    var box = $(data.firstChild.firstChild);
    if (box.prop("checked")){
        box.prop("checked",false)
    }
    else{
        box.prop("checked", true)
    }
}

function PayBtnClick() {
    var checked_certs = [];
    var selector = $("input:checked");
    var payment_method = $("#payment_method").val();
    var payment_show = payment_method==0?"Карта":"Наличные";
    for (var i = 0; i<selector.length; ++i){
        checked_certs[i] = parseInt($(selector[i]).attr("data-cert_id"));
    }

    var yesNoDialog = new YesNoDialog;
    yesNoDialog.setModalSelector("#yes-no-modal");
    yesNoDialog.show({
        caption: "Подтвердите оплату",
        yes_caption: "Оплатить",
        no_caption: "Отмена",
        data: {checked_certs : checked_certs, method: payment_method, reload: 0},
        yes_handler: YesBtn,
        no_handler: NoBtn
    });
    yesNoDialog.showLoader();
    var msg = "";
    if (checked_certs.length == 0){
        msg="
Сертификаты не выбраны.
";
        yesNoDialog.yes_handler = NoBtn;
        yesNoDialog.message = msg;
        yesNoDialog.no_caption="";
        yesNoDialog.yes_caption = "Ок";
        yesNoDialog.hideLoader();
        yesNoDialog.applyParams();
    }
    else {
        $(yesNoDialog.modal_selector+">div").removeClass("modal-sm");
        $(yesNoDialog.modal_selector+">div").addClass("modal-lg");
        var percent = parseInt($("#cert_table").attr("data-user-percent"));
        if (isNaN(percent)){
            percent = 0
        }
        var total_sum = 0;
        var fields = JSON.stringify(["ID_Sertificate", "name", "last_name", "phone_number", "flight_type", "price"]);
        var criteria = JSON.stringify({ "ID_Sertificate": checked_certs});
        var sort = JSON.stringify({"ID_Sertificate":["ASC"]});
        jQuery.post("/certificate/select", {field_names : fields, criteria : criteria, sort : sort}, function (data) {
            console.log(data);
            msg += "
" +
                        "
"+
                            "ID	"+
                            "Клиент	"+
                            "Телефон	"+
                            "Цена	"+
                            "Тип полёта	"+
                        "
";
            data.forEach(function (item) {
                var name = "", last_name = "", phone_number = "";
                var flight_type = "", price = 0;
                if (item.name){
                    name = item.name;
                }
                if (item.last_name){
                    last_name = item.last_name;
                }
                if (item.phone_number){
                    phone_number = item.phone_number;
                }
                if (item.flight_type){
                    flight_type = item.flight_type;
                }
                if (item.price){
                    price= parseInt(item.price)*(1-percent/100);
                }
                total_sum += price;
                msg +=  "
" +
                            ""+item.ID_Sertificate+"	" +
                            "" + name + " " + last_name + "	" +
                            "" + phone_number + "	" +
                            "" + price + " р.	" +
                            "" + flight_type + "	" +
                        "
";
            });
            msg += "
" +
                "
Сумма к оплате:"+total_sum+" рублей
" +
                "
Способ оплаты:"+payment_show+"
";
            yesNoDialog.message = msg;
            yesNoDialog.hideLoader();
            yesNoDialog.applyParams();

        })
    }
}

function YesBtn(event) {
    var modal = event.data;
    modal.no_caption="";
    modal.message="";
    modal.yes_caption = "Ок";
    $(modal.modal_selector+">div").addClass("modal-sm");
    $(modal.modal_selector+">div").removeClass("modal-lg");
    modal.showLoader();
    modal.yes_handler = NoBtn;
    modal.applyParams();
    var payment_method = modal.data.method;
    var checked_certs = modal.data.checked_certs;
    var params = {
        payment_method: payment_method,
        cert_ids: JSON.stringify(checked_certs)
    };
    jQuery.post("/certificate_pack/create", params, function (data) {
        console.log(data);
        var errors = data.error_msg;
        if (errors.length > 0){
            msg = "Возникли следующие ошибки при выполнении действия:
" + errors.join("
")+".";
        }
        else{
            msg = "Оплата пакета сертификатов с номером "+data.pack_id+" успешно поддтверждена.";
            modal.data.reload = 1;
        }
        modal.message = msg;
        modal.hideLoader();
        modal.applyParams();
    })
}
function NoBtn(event) {
    var modal = event.data;
    modal.close();
    if (modal.data.reload){
        GetCertTable();
    }
}

function GetPayMethods() {
    jQuery.getJSON("/certificate_pack/get_payment_methods", function (data) {
        console.log(data);
        data.forEach(function (item) {
            $("#payment_method").append(
                "<option value=" + item.id + ">" + item.name + "</option>"
            )
        })
    })
}

$(document).ready(function (event) {
    GetCertTable();
    GetPayMethods();
});


text:
import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterViewChecked,DoCheck,OnDestroy,Input,Output,Renderer2,EventEmitter,IterableDiffers,forwardRef,ViewChild} from '@angular/core';
import {CommonModule} from '@angular/common';
import {SelectItem} from '../common/selectitem';
import {DomHandler} from '../dom/domhandler';
import {ObjectUtils} from '../utils/objectutils';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';

export const MULTISELECT_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => MultiSelect),
  multi: true
};

@Component({
    selector: 'p-multiSelect',
    template: `

                <input #in type="text" readonly="readonly" [attr.id]="inputId" (focus)="onFocus($event)" (blur)="onInputBlur($event)" [disabled]="disabled" [attr.tabindex]="tabindex">

                {{valuesAsString}}

                            <input #cb type="checkbox" readonly="readonly" [checked]="isAllChecked()">

                        <input type="text" role="textbox" (input)="onFilter($event)"
                                    class="ui-inputtext ui-widget ui-state-default ui-corner-all">

                                    <input type="checkbox" readonly="readonly" [checked]="isSelected(option.value)">

                            {{option.label}}

    `,
    providers: [DomHandler,ObjectUtils,MULTISELECT_VALUE_ACCESSOR]
})
export class MultiSelect implements OnInit,AfterViewInit,AfterViewChecked,DoCheck,OnDestroy,ControlValueAccessor {

    @Input() options: SelectItem[];

    @Output() onChange: EventEmitter<any> = new EventEmitter();

    @Output() onBlur: EventEmitter<any> = new EventEmitter();

    @Input() scrollHeight: string = '200px';

    @Input() defaultLabel: string = 'Choose';

    @Input() style: any;

    @Input() styleClass: string;

    @Input() inputId: string;

    @Input() disabled: boolean;

    @Input() filter: boolean = true;

    @Input() overlayVisible: boolean;

    @Input() tabindex: number;

    @Input() appendTo: any;

    @Input() dataKey: string;

    @Input() displaySelectedLabel: boolean = true;

    @Input() maxSelectedLabels: number = 3;

    @Input() selectedItemsLabel: string = '{0} items selected';

    @ViewChild('container') containerViewChild: ElementRef;

    @ViewChild('panel') panelViewChild: ElementRef;

    public value: any[];

    public onModelChange: Function = () => {};

    public onModelTouched: Function = () => {};

    public valuesAsString: string;

    public focus: boolean;

    public documentClickListener: any;

    public container: HTMLDivElement;

    public panel: HTMLDivElement;

    public selfClick: boolean;

    public panelClick: boolean;

    public filterValue: string;

    public visibleOptions: SelectItem[];

    public filtered: boolean;

    public valueDiffer: any;

    public optionsDiffer: any;

    constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, differs: IterableDiffers, public objectUtils: ObjectUtils) {
        this.valueDiffer = differs.find([]).create(null);
        this.optionsDiffer = differs.find([]).create(null);
    }

    ngOnInit() {
        this.updateLabel();

        this.documentClickListener = this.renderer.listen('document', 'click', () => {
            if(!this.selfClick && !this.panelClick && this.overlayVisible) {
                this.hide();
            }

            this.selfClick = false;
            this.panelClick = false;
        });
    }

    ngAfterViewInit() {
        this.container = <HTMLDivElement> this.containerViewChild.nativeElement;
        this.panel = <HTMLDivElement> this.panelViewChild.nativeElement;

        if(this.appendTo) {
            if(this.appendTo === 'body')
                document.body.appendChild(this.panel);
            else
                this.domHandler.appendChild(this.panel, this.appendTo);
        }

        if(this.overlayVisible) {
            this.show();
        }
    }

    ngAfterViewChecked() {
        if(this.filtered) {
            if(this.appendTo)
                this.domHandler.absolutePosition(this.panel, this.container);
            else
                this.domHandler.relativePosition(this.panel, this.container);

            this.filtered = false;
        }
    }

    ngDoCheck() {
        let valueChanges = this.valueDiffer.diff(this.value);
        let optionChanges = this.optionsDiffer.diff(this.options);

        if(valueChanges||optionChanges) {
            this.updateLabel();
        }
    }

    writeValue(value: any) : void {
        this.value = value;
        this.updateLabel();
    }

    registerOnChange(fn: Function): void {
        this.onModelChange = fn;
    }

    registerOnTouched(fn: Function): void {
        this.onModelTouched = fn;
    }

    setDisabledState(val: boolean): void {
        this.disabled = val;
    }

    onItemClick(event, value) {
        let selectionIndex = this.findSelectionIndex(value);
        if(selectionIndex != -1)
            this.value = this.value.filter((val,i) => i!=selectionIndex);
        else
            this.value = [...this.value||[],value];

        this.onModelChange(this.value);
        this.onChange.emit({originalEvent: event, value: this.value});
    }

    isSelected(value) {
        return this.findSelectionIndex(value) != -1;
    }

    findSelectionIndex(val: any): number {
        let index = -1;

        if(this.value) {
            for(let i = 0; i < this.value.length; i++) {
                if(this.objectUtils.equals(this.value[i], val, this.dataKey)) {
                    index = i;
                    break;
                }
            }
        }

        return index;
    }

    toggleAll(event, checkbox) {
        if(checkbox.checked) {
            this.value = [];
        }
        else {
            let opts = this.getVisibleOptions();
            if(opts) {
                this.value = [];
                for(let i = 0; i < opts.length; i++) {
                    this.value.push(opts[i].value);
                }
            }
        }
        checkbox.checked = !checkbox.checked;
        this.onModelChange(this.value);
        this.onChange.emit({originalEvent: event, value: this.value});
    }

    isAllChecked() {
        if(this.filterValue && this.filterValue.trim().length)
            return this.value&&this.visibleOptions&&this.visibleOptions.length&&(this.value.length == this.visibleOptions.length);
        else
            return this.value&&this.options&&(this.value.length == this.options.length);
    }

    show() {
        this.overlayVisible = true;
        this.panel.style.zIndex = String(++DomHandler.zindex);

        if(this.appendTo)
            this.domHandler.absolutePosition(this.panel, this.container);
        else
            this.domHandler.relativePosition(this.panel, this.container);

        this.domHandler.fadeIn(this.panel, 250);
    }

    hide() {
        this.overlayVisible = false;
    }

    close(event) {
        this.hide();
        event.preventDefault();
        event.stopPropagation();
    }

    onMouseclick(event,input) {
        if(this.disabled) {
            return;
        }

        if(!this.panelClick) {
            if(this.overlayVisible) {
                this.hide();
            }
            else {
                input.focus();
                this.show();
            }
        }

        this.selfClick = true;
    }

    onFocus(event) {
        this.focus = true;
    }

    onInputBlur(event) {
        this.focus = false;
        this.onBlur.emit({originalEvent: event});
        this.onModelTouched();
    }

    updateLabel() {
        if(this.value && this.options && this.value.length && this.displaySelectedLabel) {
            let label = '';
            for(let i = 0; i < this.value.length; i++) {
                if(i != 0) {
                    label = label + ', ';
                }
                label = label + this.findLabelByValue(this.value[i]);
            }

            if(this.value.length <= this.maxSelectedLabels) {
                this.valuesAsString = label;
            }
            else {
                let pattern = /{(.*?)}/,
                newSelectedItemsLabel = this.selectedItemsLabel.replace(this.selectedItemsLabel.match(pattern)[0], this.value.length + '');
                this.valuesAsString = newSelectedItemsLabel;
            }
        }
        else {
            this.valuesAsString = this.defaultLabel;
        }
    }

    findLabelByValue(val: any): string {
        let label = null;
        for(let i = 0; i < this.options.length; i++) {
            let option = this.options[i];
            if(option.value == val) {
                label = option.label;
                break;
            }
        }
        return label;
    }

    onFilter(event) {
        this.filterValue = event.target.value.trim().toLowerCase();
        this.visibleOptions = [];
        for(let i = 0; i < this.options.length; i++) {
            let option = this.options[i];
            if(option.label.toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1) {
                this.visibleOptions.push(option);
            }
        }
        this.filtered = true;
    }

    isItemVisible(option: SelectItem): boolean {
        if(this.filterValue && this.filterValue.trim().length) {
            for(let i = 0; i < this.visibleOptions.length; i++) {
                if(this.visibleOptions[i].value == option.value) {
                    return true;
                }
            }
        }
        else {
            return true;
        }
    }

    getVisibleOptions(): SelectItem[] {
        if(this.filterValue && this.filterValue.trim().length) {
            let items = [];
            for(let i = 0; i < this.options.length; i++) {
                let option = this.options[i];
                if(option.label.toLowerCase().includes(this.filterValue.toLowerCase())) {
                    items.push(option);
                }
            }
            return items;
        }
        else {
            return this.options;
        }
    }

    ngOnDestroy() {
        if(this.documentClickListener) {
            this.documentClickListener();
        }

        if(this.appendTo) {
            this.container.appendChild(this.panel);
        }
    }

}

@NgModule({
    imports: [CommonModule],
    exports: [MultiSelect],
    declarations: [MultiSelect]
})
export class MultiSelectModule { }