Rebuild
This commit is contained in:
parent
5483a097fd
commit
87fefe0c35
160
advanced.html
160
advanced.html
@ -5,9 +5,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="To perform a set of operations within a transaction, the general flow is as below.
|
<meta name="description" content="After perform any operations, if there are any error happened, GORM will set it to *DB's Error field">
|
||||||
The database handle returned from db.Begin() should be used for all oper">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -70,8 +69,8 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
data-level="5"
|
data-level="5"
|
||||||
data-chapter-title="Advanced Usage"
|
data-chapter-title="Advanced Usage"
|
||||||
data-filepath="advanced.md"
|
data-filepath="advanced.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -179,12 +178,12 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -482,12 +481,12 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -497,11 +496,26 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -533,11 +547,26 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -586,7 +615,7 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Advanced Usage</a>
|
<a href="." >Advanced Usage</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -604,9 +633,14 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
<li><a href="#a-specific-example">A Specific Example</a></li>
|
<li><a href="#a-specific-example">A Specific Example</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#raw-sql">Raw SQL</a></li>
|
<li><a href="#sql-builder">SQL Builder</a><ul>
|
||||||
<li><a href="#row-rows">Row & Rows</a><ul>
|
<li><a href="#run-raw-sql">Run Raw SQL</a></li>
|
||||||
<li><a href="#scan-rows">Scan Rows</a></li>
|
<li><a href="#sqlrow-sqlrows">sql.Row & sql.Rows</a></li>
|
||||||
|
<li><a href="#scan-sqlrows-in-iteration">Scan sql.Rows In Iteration</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#generic-database-interface-sqldb">Generic database interface sql.DB</a><ul>
|
||||||
|
<li><a href="#connection-pool">Connection Pool</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#composite-primary-key">Composite Primary Key</a></li>
|
<li><a href="#composite-primary-key">Composite Primary Key</a></li>
|
||||||
@ -617,40 +651,35 @@ The database handle returned from db.Begin() should be used for all oper">
|
|||||||
</ul>
|
</ul>
|
||||||
<!-- toc stop -->
|
<!-- toc stop -->
|
||||||
<h2 id="error-handling">Error Handling</h2>
|
<h2 id="error-handling">Error Handling</h2>
|
||||||
<pre><code class="lang-go">query := db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&user)
|
<p>After perform any operations, if there are any error happened, GORM will set it to <code>*DB</code>'s <code>Error</code> field</p>
|
||||||
query := db.First(&user).Limit(<span class="hljs-number">10</span>).Find(&users)
|
<pre><code class="lang-go"><span class="hljs-keyword">if</span> err := db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&user).Error; err != <span class="hljs-literal">nil</span> {
|
||||||
<span class="hljs-comment">// query.Error will return the last happened error</span>
|
|
||||||
|
|
||||||
<span class="hljs-comment">// So you could do error handing in your application like this:</span>
|
|
||||||
<span class="hljs-keyword">if</span> err := db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&user).Error; err != <span class="hljs-constant">nil</span> {
|
|
||||||
<span class="hljs-comment">// error handling...</span>
|
<span class="hljs-comment">// error handling...</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-comment">// RecordNotFound</span>
|
<span class="hljs-comment">// If there are more than one error happened, get all of them with `GetErrors`, it returns `[]error`</span>
|
||||||
<span class="hljs-comment">// If no record found when you query data, gorm will return RecordNotFound error, you could check it like this:</span>
|
db.First(&user).Limit(<span class="hljs-number">10</span>).Find(&users).GetErrors()
|
||||||
db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"hello world"</span>).First(&User{}).Error == gorm.RecordNotFound
|
|
||||||
<span class="hljs-comment">// Or use the shortcut method</span>
|
<span class="hljs-comment">// Check if returns RecordNotFound error</span>
|
||||||
db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"hello world"</span>).First(&user).RecordNotFound()
|
db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"hello world"</span>).First(&user).RecordNotFound()
|
||||||
|
|
||||||
<span class="hljs-keyword">if</span> db.Model(&user).Related(&credit_card).RecordNotFound() {
|
<span class="hljs-keyword">if</span> db.Model(&user).Related(&credit_card).RecordNotFound() {
|
||||||
<span class="hljs-comment">// no credit card found error handling</span>
|
<span class="hljs-comment">// no credit card found handling</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="transactions">Transactions</h2>
|
<h2 id="transactions">Transactions</h2>
|
||||||
<p>To perform a set of operations within a transaction, the general flow is as below.
|
<p>To perform a set of operations within a transaction, the general flow is as below.</p>
|
||||||
The database handle returned from <code>db.Begin()</code> should be used for all operations within the transaction.
|
<pre><code class="lang-go"><span class="hljs-comment">// begin a transaction</span>
|
||||||
(Note that all individual save and delete operations are run in a transaction by default.)</p>
|
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// begin</span>
|
|
||||||
tx := db.Begin()
|
tx := db.Begin()
|
||||||
|
|
||||||
<span class="hljs-comment">// do some database operations (use 'tx' from this point, not 'db')</span>
|
<span class="hljs-comment">// do some database operations in the transaction (use 'tx' from this point, not 'db')</span>
|
||||||
tx.Create(...)
|
tx.Create(...)
|
||||||
...
|
|
||||||
|
|
||||||
<span class="hljs-comment">// rollback in case of error</span>
|
<span class="hljs-comment">// ...</span>
|
||||||
|
|
||||||
|
<span class="hljs-comment">// rollback the transaction in case of error</span>
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
|
|
||||||
<span class="hljs-comment">// Or commit if all is ok</span>
|
<span class="hljs-comment">// Or commit the transaction</span>
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="a-specific-example">A Specific Example</h3>
|
<h3 id="a-specific-example">A Specific Example</h3>
|
||||||
@ -658,26 +687,37 @@ tx.Commit()
|
|||||||
tx := db.Begin()
|
tx := db.Begin()
|
||||||
<span class="hljs-comment">// Note the use of tx as the database handle once you are within a transaction</span>
|
<span class="hljs-comment">// Note the use of tx as the database handle once you are within a transaction</span>
|
||||||
|
|
||||||
<span class="hljs-keyword">if</span> err := tx.Create(&Animal{Name: <span class="hljs-string">"Giraffe"</span>}).Error; err != <span class="hljs-constant">nil</span> {
|
<span class="hljs-keyword">if</span> err := tx.Create(&Animal{Name: <span class="hljs-string">"Giraffe"</span>}).Error; err != <span class="hljs-literal">nil</span> {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
<span class="hljs-keyword">return</span> err
|
<span class="hljs-keyword">return</span> err
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">if</span> err := tx.Create(&Animal{Name: <span class="hljs-string">"Lion"</span>}).Error; err != <span class="hljs-constant">nil</span> {
|
<span class="hljs-keyword">if</span> err := tx.Create(&Animal{Name: <span class="hljs-string">"Lion"</span>}).Error; err != <span class="hljs-literal">nil</span> {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
<span class="hljs-keyword">return</span> err
|
<span class="hljs-keyword">return</span> err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
<span class="hljs-keyword">return</span> <span class="hljs-constant">nil</span>
|
<span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="raw-sql">Raw SQL</h2>
|
<h2 id="sql-builder">SQL Builder</h2>
|
||||||
|
<h4 id="run-raw-sql">Run Raw SQL</h4>
|
||||||
|
<p>Run Raw SQL</p>
|
||||||
<pre><code class="lang-go">db.Exec(<span class="hljs-string">"DROP TABLE users;"</span>)
|
<pre><code class="lang-go">db.Exec(<span class="hljs-string">"DROP TABLE users;"</span>)
|
||||||
db.Exec(<span class="hljs-string">"UPDATE orders SET shipped_at=? WHERE id IN (?)"</span>, time.Now, []<span class="hljs-typename">int64</span>{<span class="hljs-number">11</span>,<span class="hljs-number">22</span>,<span class="hljs-number">33</span>})
|
db.Exec(<span class="hljs-string">"UPDATE orders SET shipped_at=? WHERE id IN (?)"</span>, time.Now, []<span class="hljs-keyword">int64</span>{<span class="hljs-number">11</span>,<span class="hljs-number">22</span>,<span class="hljs-number">33</span>})
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Scan</span>
|
||||||
|
<span class="hljs-keyword">type</span> Result <span class="hljs-keyword">struct</span> {
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
Age <span class="hljs-keyword">int</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">var</span> result Result
|
||||||
|
db.Raw(<span class="hljs-string">"SELECT name, age FROM users WHERE name = ?"</span>, <span class="hljs-number">3</span>).Scan(&result)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="row--rows">Row & Rows</h2>
|
<h4 id="sqlrow--sqlrows">sql.Row & sql.Rows</h4>
|
||||||
<p>It is even possible to get query result as <code>*sql.Row</code> or <code>*sql.Rows</code></p>
|
<p>Get query result as <code>*sql.Row</code> or <code>*sql.Rows</code></p>
|
||||||
<pre><code class="lang-go">row := db.Table(<span class="hljs-string">"users"</span>).Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).Select(<span class="hljs-string">"name, age"</span>).Row() <span class="hljs-comment">// (*sql.Row)</span>
|
<pre><code class="lang-go">row := db.Table(<span class="hljs-string">"users"</span>).Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).Select(<span class="hljs-string">"name, age"</span>).Row() <span class="hljs-comment">// (*sql.Row)</span>
|
||||||
row.Scan(&name, &age)
|
row.Scan(&name, &age)
|
||||||
|
|
||||||
@ -698,7 +738,7 @@ rows, err := db.Raw(<span class="hljs-string">"select name, age, email from
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="scan-rows">Scan Rows</h3>
|
<h4 id="scan-sqlrows-in-iteration">Scan sql.Rows In Iteration</h4>
|
||||||
<pre><code class="lang-go">rows, err := db.Model(&User{}).Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).Select(<span class="hljs-string">"name, age, email"</span>).Rows() <span class="hljs-comment">// (*sql.Rows, error)</span>
|
<pre><code class="lang-go">rows, err := db.Model(&User{}).Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).Select(<span class="hljs-string">"name, age, email"</span>).Rows() <span class="hljs-comment">// (*sql.Rows, error)</span>
|
||||||
<span class="hljs-keyword">defer</span> rows.Close()
|
<span class="hljs-keyword">defer</span> rows.Close()
|
||||||
|
|
||||||
@ -708,27 +748,39 @@ rows, err := db.Raw(<span class="hljs-string">"select name, age, email from
|
|||||||
<span class="hljs-comment">// do something</span>
|
<span class="hljs-comment">// do something</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<h2 id="generic-database-interface-sqldb">Generic database interface sql.DB</h2>
|
||||||
|
<p>Get generic database interface <a href="http://golang.org/pkg/database/sql/#DB" target="_blank">*sql.DB</a> from <code>*gorm.DB</code> connection</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-comment">// Get generic database object `*sql.DB` to use its functions</span>
|
||||||
|
db.DB()
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Ping</span>
|
||||||
|
db.DB().Ping()
|
||||||
|
</code></pre>
|
||||||
|
<h4 id="connection-pool">Connection Pool</h4>
|
||||||
|
<pre><code class="lang-go">db.DB().SetMaxIdleConns(<span class="hljs-number">10</span>)
|
||||||
|
db.DB().SetMaxOpenConns(<span class="hljs-number">100</span>)
|
||||||
|
</code></pre>
|
||||||
<h2 id="composite-primary-key">Composite Primary Key</h2>
|
<h2 id="composite-primary-key">Composite Primary Key</h2>
|
||||||
|
<p>Set multiple fields as priamry key to enable composite primary key</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Product <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Product <span class="hljs-keyword">struct</span> {
|
||||||
ID <span class="hljs-typename">string</span> <span class="hljs-string">`gorm:"primary_key"`</span>
|
ID <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"primary_key"`</span>
|
||||||
LanguageCode <span class="hljs-typename">string</span> <span class="hljs-string">`gorm:"primary_key"`</span>
|
LanguageCode <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"primary_key"`</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="logger">Logger</h2>
|
<h2 id="logger">Logger</h2>
|
||||||
<p>Gorm has built-in logger support</p>
|
<p>Gorm has built-in logger support, by default, it will print happened errors</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Enable Logger</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Enable Logger, show detailed log</span>
|
||||||
db.LogMode(<span class="hljs-constant">true</span>)
|
db.LogMode(<span class="hljs-literal">true</span>)
|
||||||
|
|
||||||
<span class="hljs-comment">// Diable Logger</span>
|
<span class="hljs-comment">// Diable Logger, don't show any log</span>
|
||||||
db.LogMode(<span class="hljs-constant">false</span>)
|
db.LogMode(<span class="hljs-literal">false</span>)
|
||||||
|
|
||||||
<span class="hljs-comment">// Debug a single operation</span>
|
<span class="hljs-comment">// Debug a single operation, show detailed log for this operation</span>
|
||||||
db.Debug().Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&User{})
|
db.Debug().Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&User{})
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p><img src="https:/raw.github.com/jinzhu/gorm/master/doc/logger.png" alt="logger"></p>
|
<h4 id="customize-logger">Customize Logger</h4>
|
||||||
<h3 id="customize-logger">Customize Logger</h3>
|
<p>Refer GORM's default logger for how to customize it <a href="https://github.com/jinzhu/gorm/blob/master/logger.go" target="_blank">https://github.com/jinzhu/gorm/blob/master/logger.go</a></p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Refer gorm's default logger for how to: https://github.com/jinzhu/gorm/blob/master/logger.go#files</span>
|
<pre><code class="lang-go">db.SetLogger(gorm.Logger{revel.TRACE})
|
||||||
db.SetLogger(gorm.Logger{revel.TRACE})
|
|
||||||
db.SetLogger(log.New(os.Stdout, <span class="hljs-string">"\r\n"</span>, <span class="hljs-number">0</span>))
|
db.SetLogger(log.New(os.Stdout, <span class="hljs-string">"\r\n"</span>, <span class="hljs-number">0</span>))
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="Supports polymorphic has-many and has-one associations.">
|
<meta name="description" content="Specify Foreign Key">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +69,8 @@
|
|||||||
data-level="2.3"
|
data-level="2.3"
|
||||||
data-chapter-title="Associations"
|
data-chapter-title="Associations"
|
||||||
data-filepath="associations.md"
|
data-filepath="associations.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -178,12 +178,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -481,12 +481,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -496,11 +496,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -532,11 +547,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -585,7 +615,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Associations</a>
|
<a href="." >Associations</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -607,21 +637,46 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<!-- toc stop -->
|
<!-- toc stop -->
|
||||||
<h2 id="belongs-to">Belongs To</h2>
|
<h2 id="belongs-to">Belongs To</h2>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// User belongs to a profile, ProfileID is the foreign key</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// `User` belongs to `Profile`, `ProfileID` is the foreign key</span>
|
||||||
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Profile Profile
|
Profile Profile
|
||||||
ProfileID <span class="hljs-typename">int</span>
|
ProfileID <span class="hljs-keyword">int</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Model(&user).Related(&profile)
|
db.Model(&user).Related(&profile)
|
||||||
<span class="hljs-comment">//// SELECT * FROM profiles WHERE id = 111; // 111 is user's foreign key ProfileID</span>
|
<span class="hljs-comment">//// SELECT * FROM profiles WHERE id = 111; // 111 is user's foreign key ProfileID</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Profile Profile <span class="hljs-string">`gorm:"ForeignKey:ProfileRefer"`</span> <span class="hljs-comment">// use ProfileRefer as foreign key</span>
|
||||||
|
ProfileRefer <span class="hljs-keyword">int</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key & Association Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Refer <span class="hljs-keyword">string</span>
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Profile Profile <span class="hljs-string">`gorm:"ForeignKey:ProfileID;AssociationForeignKey:Refer"`</span>
|
||||||
|
ProfileID <span class="hljs-keyword">int</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
<h2 id="has-one">Has One</h2>
|
<h2 id="has-one">Has One</h2>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// User has one CreditCard, UserID is the foreign key</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// User has one CreditCard, UserID is the foreign key</span>
|
||||||
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
@ -631,8 +686,8 @@ db.Model(&user).Related(&profile)
|
|||||||
|
|
||||||
<span class="hljs-keyword">type</span> CreditCard <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> CreditCard <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
UserID <span class="hljs-typename">uint</span>
|
UserID <span class="hljs-keyword">uint</span>
|
||||||
Number <span class="hljs-typename">string</span>
|
Number <span class="hljs-keyword">string</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">var</span> card CreditCard
|
<span class="hljs-keyword">var</span> card CreditCard
|
||||||
@ -642,6 +697,31 @@ db.Model(&user).Related(&card, <span class="hljs-string">"CreditCar
|
|||||||
<span class="hljs-comment">// If the field name is same as the variable's type name, like above example, it could be omitted, like:</span>
|
<span class="hljs-comment">// If the field name is same as the variable's type name, like above example, it could be omitted, like:</span>
|
||||||
db.Model(&user).Related(&card)
|
db.Model(&user).Related(&card)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
UserRefer <span class="hljs-keyword">uint</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Profile Profile <span class="hljs-string">`gorm:"ForeignKey:UserRefer"`</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key & Association Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
UserID <span class="hljs-keyword">uint</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Refer <span class="hljs-keyword">string</span>
|
||||||
|
Profile Profile <span class="hljs-string">`gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"`</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
<h2 id="has-many">Has Many</h2>
|
<h2 id="has-many">Has Many</h2>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// User has many emails, UserID is the foreign key</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// User has many emails, UserID is the foreign key</span>
|
||||||
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
@ -651,13 +731,38 @@ db.Model(&user).Related(&card)
|
|||||||
|
|
||||||
<span class="hljs-keyword">type</span> Email <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Email <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Email <span class="hljs-typename">string</span>
|
Email <span class="hljs-keyword">string</span>
|
||||||
UserID <span class="hljs-typename">uint</span>
|
UserID <span class="hljs-keyword">uint</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Model(&user).Related(&emails)
|
db.Model(&user).Related(&emails)
|
||||||
<span class="hljs-comment">//// SELECT * FROM emails WHERE user_id = 111; // 111 is user's primary key</span>
|
<span class="hljs-comment">//// SELECT * FROM emails WHERE user_id = 111; // 111 is user's primary key</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
UserRefer <span class="hljs-keyword">uint</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Profile []Profiles <span class="hljs-string">`gorm:"ForeignKey:UserRefer"`</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key & Association Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Profile <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
UserID <span class="hljs-keyword">uint</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Refer <span class="hljs-keyword">string</span>
|
||||||
|
Profile []Profiles <span class="hljs-string">`gorm:"ForeignKey:UserID;AssociationForeignKey:Refer"`</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
<h2 id="many-to-many">Many To Many</h2>
|
<h2 id="many-to-many">Many To Many</h2>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// User has and belongs to many languages, use `user_languages` as join table</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// User has and belongs to many languages, use `user_languages` as join table</span>
|
||||||
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
@ -667,31 +772,42 @@ db.Model(&user).Related(&emails)
|
|||||||
|
|
||||||
<span class="hljs-keyword">type</span> Language <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Language <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Model(&user).Related(&languages)
|
db.Model(&user).Related(&languages)
|
||||||
<span class="hljs-comment">//// SELECT * FROM "languages" INNER JOIN "user_languages" ON "user_languages"."language_id" = "languages"."id" WHERE "user_languages"."user_id" = 111</span>
|
<span class="hljs-comment">//// SELECT * FROM "languages" INNER JOIN "user_languages" ON "user_languages"."language_id" = "languages"."id" WHERE "user_languages"."user_id" = 111</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<p><em>Specify Foreign Key & Association Key</em></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> CustomizePerson <span class="hljs-keyword">struct</span> {
|
||||||
|
IdPerson <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"primary_key:true"`</span>
|
||||||
|
Accounts []CustomizeAccount <span class="hljs-string">`gorm:"many2many:PersonAccount;AssociationForeignKey:idAccount;ForeignKey:idPerson"`</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> CustomizeAccount <span class="hljs-keyword">struct</span> {
|
||||||
|
IdAccount <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"primary_key:true"`</span>
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
<h2 id="polymorphism">Polymorphism</h2>
|
<h2 id="polymorphism">Polymorphism</h2>
|
||||||
<p>Supports polymorphic has-many and has-one associations.</p>
|
<p>Supports polymorphic has-many and has-one associations.</p>
|
||||||
<pre><code class="lang-go"> <span class="hljs-keyword">type</span> Cat <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"> <span class="hljs-keyword">type</span> Cat <span class="hljs-keyword">struct</span> {
|
||||||
Id <span class="hljs-typename">int</span>
|
Id <span class="hljs-keyword">int</span>
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
Toy Toy <span class="hljs-string">`gorm:"polymorphic:Owner;"`</span>
|
Toy Toy <span class="hljs-string">`gorm:"polymorphic:Owner;"`</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">type</span> Dog <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Dog <span class="hljs-keyword">struct</span> {
|
||||||
Id <span class="hljs-typename">int</span>
|
Id <span class="hljs-keyword">int</span>
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
Toy Toy <span class="hljs-string">`gorm:"polymorphic:Owner;"`</span>
|
Toy Toy <span class="hljs-string">`gorm:"polymorphic:Owner;"`</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">type</span> Toy <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Toy <span class="hljs-keyword">struct</span> {
|
||||||
Id <span class="hljs-typename">int</span>
|
Id <span class="hljs-keyword">int</span>
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
OwnerId <span class="hljs-typename">int</span>
|
OwnerId <span class="hljs-keyword">int</span>
|
||||||
OwnerType <span class="hljs-typename">string</span>
|
OwnerType <span class="hljs-keyword">string</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>Note: polymorphic belongs-to and many-to-many are explicitly NOT supported, and will throw errors.</p>
|
<p>Note: polymorphic belongs-to and many-to-many are explicitly NOT supported, and will throw errors.</p>
|
||||||
@ -742,7 +858,7 @@ db.Model(&user).Association(<span class="hljs-string">"Languages"<
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="models.html" class="navigation navigation-prev " aria-label="Previous page: Naming Conventions & Overriding">
|
<a href="models.html" class="navigation navigation-prev " aria-label="Previous page: Conventions & Overriding">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
101
callbacks.html
101
callbacks.html
@ -5,9 +5,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="Callbacks are methods defined on the pointer of struct.
|
<meta name="description" content="You could define callback methods to pointer of model struct, it will be called when creating, updating, querying, deleting, if any callback returns an err">
|
||||||
If any callback returns an error, gorm will stop future operations and rollback all changes.">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -70,8 +69,8 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
data-level="4"
|
data-level="4"
|
||||||
data-chapter-title="Callbacks"
|
data-chapter-title="Callbacks"
|
||||||
data-filepath="callbacks.md"
|
data-filepath="callbacks.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -179,12 +178,12 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -482,12 +481,12 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -497,11 +496,26 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -533,11 +547,26 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -586,7 +615,7 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Callbacks</a>
|
<a href="." >Callbacks</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -601,43 +630,54 @@ If any callback returns an error, gorm will stop future operations and rollback
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a href="#creating-an-object">Creating An Object</a></li>
|
<li><a href="#creating-an-object">Creating An Object</a></li>
|
||||||
<li><a href="#updating-an-object">Updating An Object</a></li>
|
<li><a href="#updating-an-object">Updating An Object</a></li>
|
||||||
<li><a href="#destroying-an-object">Destroying An Object</a></li>
|
<li><a href="#deleting-an-object">Deleting An Object</a></li>
|
||||||
<li><a href="#after-find">After Find</a></li>
|
<li><a href="#querying-an-object">Querying An Object</a></li>
|
||||||
<li><a href="#example">Example</a></li>
|
<li><a href="#callback-examples">Callback Examples</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- toc stop -->
|
<!-- toc stop -->
|
||||||
<p>Callbacks are methods defined on the pointer of struct.
|
<p>You could define callback methods to pointer of model struct, it will be called when creating, updating, querying, deleting, if any callback returns an error, gorm will stop future operations and rollback all changes.</p>
|
||||||
If any callback returns an error, gorm will stop future operations and rollback all changes.</p>
|
|
||||||
<p>Here is the list of all available callbacks:
|
|
||||||
(listed in the same order in which they will get called during the respective operations)</p>
|
|
||||||
<h3 id="creating-an-object">Creating An Object</h3>
|
<h3 id="creating-an-object">Creating An Object</h3>
|
||||||
<pre><code class="lang-go">BeforeSave
|
<p>Available Callbacks for creating</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-comment">// begin transaction</span>
|
||||||
|
BeforeSave
|
||||||
BeforeCreate
|
BeforeCreate
|
||||||
<span class="hljs-comment">// save before associations</span>
|
<span class="hljs-comment">// save before associations</span>
|
||||||
|
<span class="hljs-comment">// update timestamp `CreatedAt`, `UpdatedAt`</span>
|
||||||
<span class="hljs-comment">// save self</span>
|
<span class="hljs-comment">// save self</span>
|
||||||
|
<span class="hljs-comment">// reload fields that have default value and its value is blank</span>
|
||||||
<span class="hljs-comment">// save after associations</span>
|
<span class="hljs-comment">// save after associations</span>
|
||||||
AfterCreate
|
AfterCreate
|
||||||
AfterSave
|
AfterSave
|
||||||
|
<span class="hljs-comment">// commit or rollback transaction</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="updating-an-object">Updating An Object</h3>
|
<h3 id="updating-an-object">Updating An Object</h3>
|
||||||
<pre><code class="lang-go">BeforeSave
|
<p>Available Callbacks for updating</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-comment">// begin transaction</span>
|
||||||
|
BeforeSave
|
||||||
BeforeUpdate
|
BeforeUpdate
|
||||||
<span class="hljs-comment">// save before associations</span>
|
<span class="hljs-comment">// save before associations</span>
|
||||||
|
<span class="hljs-comment">// update timestamp `UpdatedAt`</span>
|
||||||
<span class="hljs-comment">// save self</span>
|
<span class="hljs-comment">// save self</span>
|
||||||
<span class="hljs-comment">// save after associations</span>
|
<span class="hljs-comment">// save after associations</span>
|
||||||
AfterUpdate
|
AfterUpdate
|
||||||
AfterSave
|
AfterSave
|
||||||
|
<span class="hljs-comment">// commit or rollback transaction</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="destroying-an-object">Destroying An Object</h3>
|
<h3 id="deleting-an-object">Deleting An Object</h3>
|
||||||
<pre><code class="lang-go">BeforeDelete
|
<p>Available Callbacks for deleting</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-comment">// begin transaction</span>
|
||||||
|
BeforeDelete
|
||||||
<span class="hljs-comment">// delete self</span>
|
<span class="hljs-comment">// delete self</span>
|
||||||
AfterDelete
|
AfterDelete
|
||||||
|
<span class="hljs-comment">// commit or rollback transaction</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="after-find">After Find</h3>
|
<h3 id="querying-an-object">Querying An Object</h3>
|
||||||
|
<p>Available Callbacks for querying</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// load data from database</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// load data from database</span>
|
||||||
|
<span class="hljs-comment">// Preloading (edger loading)</span>
|
||||||
AfterFind
|
AfterFind
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="example">Example</h3>
|
<h3 id="callback-examples">Callback Examples</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (u *User) BeforeUpdate() (err error) {
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (u *User) BeforeUpdate() (err error) {
|
||||||
<span class="hljs-keyword">if</span> u.readonly() {
|
<span class="hljs-keyword">if</span> u.readonly() {
|
||||||
err = errors.New(<span class="hljs-string">"read only user"</span>)
|
err = errors.New(<span class="hljs-string">"read only user"</span>)
|
||||||
@ -653,14 +693,17 @@ AfterFind
|
|||||||
<span class="hljs-keyword">return</span>
|
<span class="hljs-keyword">return</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>Save/delete operations in gorm are running in a transaction.
|
<p>Save/Delete operations in gorm are running in transactions, so changes made in that transaction are not visible unless it is commited.
|
||||||
Changes made in that transaction are not visible unless it is commited.
|
If you want to use those changes in your callbacks, you need to run your SQL in the same transaction. So you need to pass current transaction to callbacks like this:</p>
|
||||||
So if you want to use those changes in your callbacks, you need to run your SQL in the same transaction.
|
|
||||||
For this Gorm supports passing transactions to callbacks like this:</p>
|
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (u *User) AfterCreate(tx *gorm.DB) (err error) {
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (u *User) AfterCreate(tx *gorm.DB) (err error) {
|
||||||
tx.Model(u).Update(<span class="hljs-string">"role"</span>, <span class="hljs-string">"admin"</span>)
|
tx.Model(u).Update(<span class="hljs-string">"role"</span>, <span class="hljs-string">"admin"</span>)
|
||||||
<span class="hljs-keyword">return</span>
|
<span class="hljs-keyword">return</span>
|
||||||
}
|
}
|
||||||
|
</code></pre>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (u *User) AfterCreate(scope *gorm.Scope) (err error) {
|
||||||
|
scope.DB().Model(u).Update(<span class="hljs-string">"role"</span>, <span class="hljs-string">"admin"</span>)
|
||||||
|
<span class="hljs-keyword">return</span>
|
||||||
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="gorm.Open return type *gorm.DB instead of gorm.DB">
|
<meta name="description" content="gorm.Open return type *gorm.DB instead of gorm.DB">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -67,8 +67,8 @@
|
|||||||
data-level="7"
|
data-level="7"
|
||||||
data-chapter-title="Change Log"
|
data-chapter-title="Change Log"
|
||||||
data-filepath="changelog.md"
|
data-filepath="changelog.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -176,12 +176,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -479,12 +479,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -494,11 +494,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -530,11 +545,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -583,7 +613,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Change Log</a>
|
<a href="." >Change Log</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -602,20 +632,21 @@
|
|||||||
<li><p><strong>Updating will only update changed fields</strong></p>
|
<li><p><strong>Updating will only update changed fields</strong></p>
|
||||||
<p>Most applications won't be affected, only when you are changing updating values in callbacks like <code>BeforeSave</code>, <code>BeforeUpdate</code>, you should use <code>scope.SetColumn</code> then, for example:</p>
|
<p>Most applications won't be affected, only when you are changing updating values in callbacks like <code>BeforeSave</code>, <code>BeforeUpdate</code>, you should use <code>scope.SetColumn</code> then, for example:</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (user *User) BeforeUpdate(scope *gorm.Scope) {
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (user *User) BeforeUpdate(scope *gorm.Scope) {
|
||||||
<span class="hljs-keyword">if</span> pw, err := bcrypt.GenerateFromPassword(user.Password, <span class="hljs-number">0</span>); err == <span class="hljs-constant">nil</span> {
|
<span class="hljs-keyword">if</span> pw, err := bcrypt.GenerateFromPassword(user.Password, <span class="hljs-number">0</span>); err == <span class="hljs-literal">nil</span> {
|
||||||
scope.SetColumn(<span class="hljs-string">"EncryptedPassword"</span>, pw)
|
scope.SetColumn(<span class="hljs-string">"EncryptedPassword"</span>, pw)
|
||||||
<span class="hljs-comment">// user.EncryptedPassword = pw // doesn't work, won't including EncryptedPassword field when updating</span>
|
<span class="hljs-comment">// user.EncryptedPassword = pw // doesn't work, won't including EncryptedPassword field when updating</span>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
</li>
|
</li>
|
||||||
<li><p><strong>Soft delete's default querying scope will only check <code>deleted_at IS NULL</code></strong></p>
|
<li><p><strong>Soft Delete's default querying scope will only check <code>deleted_at IS NULL</code></strong></p>
|
||||||
<p>Before <code>db.Find(&user)</code> will generate querying SQL if user has <code>DeletedAt</code> field</p>
|
<p>Before it will check <code>deleted_at</code> less than <code>0001-01-02</code> also to exclude blank time, like:</p>
|
||||||
<p><code>SELECT * FROM users WHERE deleted_at IS NULL OR deleted_at <= '0001-01-02'</code></p>
|
<p><code>SELECT * FROM users WHERE deleted_at IS NULL OR deleted_at <= '0001-01-02'</code></p>
|
||||||
<p>Now won't include blank time check <code><= '0001-01-02</code> anymore, will generat SQL like:</p>
|
<p>But it is not necessary if you are using type <code>*time.Time</code> for your model's <code>DeletedAt</code>, which has been used by <code>gorm.Model</code>, so below SQl is enough</p>
|
||||||
<p><code>SELECT * FROM users WHERE deleted_at IS NULL</code></p>
|
<p><code>SELECT * FROM users WHERE deleted_at IS NULL</code></p>
|
||||||
<p>So your application's <code>DeletedAt</code> field should not use <code>time.Time</code> as data type, need to use pointer <code>*time.Time</code> or something like <code>NullTime</code>.
|
<p>So if you are using <code>gorm.Model</code>, then you are good, nothing need to be change, just make sure all records having blank time for <code>deleted_at</code> set to <code>NULL</code>, sample migrate script:</p>
|
||||||
If you are using <code>gorm.Model</code>, then you are good, nothing need to be change, just make sure all records using blank time for <code>deleted_at</code> has been set to NULL, sample migration script:</p>
|
</li>
|
||||||
|
</ul>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
||||||
<span class="hljs-string">"github.com/jinzhu/now"</span>
|
<span class="hljs-string">"github.com/jinzhu/now"</span>
|
||||||
)
|
)
|
||||||
@ -627,11 +658,17 @@ If you are using <code>gorm.Model</code>, then you are good, nothing need to be
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
</li>
|
<ul>
|
||||||
<li><p><strong>New ToDBName logic</strong></p>
|
<li><p><strong>New ToDBName logic</strong></p>
|
||||||
<p>Before when GORM convert Struct, Field's name to db name, only those common initialisms from <a href="https://github.com/golang/lint/blob/master/lint.go#L702" target="_blank">golint</a> like <code>HTTP</code>, <code>URI</code> are special handled.</p>
|
<p>Before when GORM convert Struct, Field's name to db name, only those common initialisms from <a href="https://github.com/golang/lint/blob/master/lint.go#L702" target="_blank">golint</a> like <code>HTTP</code>, <code>URI</code> are special handled.</p>
|
||||||
<p>So field <code>HTTP</code>'s db name will be <code>http</code> not <code>h_t_t_p</code>, but some other initialisms like <code>SKU</code> that not in golint, it's db name will be <code>s_k_u</code>, this release fixed this, any upper case initialisms should be converted correctly.</p>
|
<p>So field <code>HTTP</code>'s db name will be <code>http</code> not <code>h_t_t_p</code>, but some other initialisms like <code>SKU</code> that not in golint, it's db name will be <code>s_k_u</code>, which looks ugly, this release fixed this, any upper case initialisms should be converted correctly.</p>
|
||||||
<p>If your applications using some upper case initialisms which doesn't exist in <a href="https://github.com/golang/lint/blob/master/lint.go#L702" target="_blank">golint</a>, you need to overwrite generated column name with tag, like <code>sql:"column:s_k_u"</code>, or alert your database's column name according to new logic</p>
|
<p>If your applications using some upper case initialisms which doesn't exist in <a href="https://github.com/golang/lint/blob/master/lint.go#L702" target="_blank">golint</a>, you need to overwrite default column name with tag, like <code>gorm:"column:s_k_u"</code>, or alert your database's column name according to new logic</p>
|
||||||
|
</li>
|
||||||
|
<li><p>Error <code>RecordNotFound</code> has been renamed to <code>ErrRecordNotFound</code></p>
|
||||||
|
</li>
|
||||||
|
<li><p><code>mssql</code> driver has been moved out from default drivers, import it with <code>import _ "github.com/jinzhu/gorm/dialects/mssql"</code></p>
|
||||||
|
</li>
|
||||||
|
<li><p><code>Hstore</code> has been moved to package <code>github.com/jinzhu/gorm/dialects/postgres</code></p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
164
curd.html
164
curd.html
@ -6,7 +6,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="Refer Associations for more details">
|
<meta name="description" content="Refer Associations for more details">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +69,8 @@
|
|||||||
data-level="3"
|
data-level="3"
|
||||||
data-chapter-title="CRUD: Reading and Writing Data"
|
data-chapter-title="CRUD: Reading and Writing Data"
|
||||||
data-filepath="curd.md"
|
data-filepath="curd.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -178,12 +178,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -481,12 +481,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -496,11 +496,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -532,11 +547,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -585,7 +615,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >CRUD: Reading and Writing Data</a>
|
<a href="." >CRUD: Reading and Writing Data</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -688,13 +718,13 @@ db.Create(&user)
|
|||||||
<span class="hljs-comment">//// COMMIT;</span>
|
<span class="hljs-comment">//// COMMIT;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="create-with-associations">Create With Associations</h3>
|
<h3 id="create-with-associations">Create With Associations</h3>
|
||||||
<p>Refer Associations for more details</p>
|
<p>Refer <a href="associations.html">Associations</a> for more details</p>
|
||||||
<h3 id="default-values">Default Values</h3>
|
<h3 id="default-values">Default Values</h3>
|
||||||
<p>You could defined default value in the <code>sql</code> tag, then the generated creating SQL will ignore these fields that including default value and its value is blank, and after inserted the record into databae, gorm will load those fields's value from database.</p>
|
<p>You could define default value in the <code>gorm</code> tag, then the inserting SQL will ignore these fields that has default value and its value is blank, and after insert the record into databae, gorm will load those fields's value from database.</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Animal <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Animal <span class="hljs-keyword">struct</span> {
|
||||||
ID <span class="hljs-typename">int64</span>
|
ID <span class="hljs-keyword">int64</span>
|
||||||
Name <span class="hljs-typename">string</span> <span class="hljs-string">`sql:"default:'galeone'"`</span>
|
Name <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"default:'galeone'"`</span>
|
||||||
Age <span class="hljs-typename">int64</span>
|
Age <span class="hljs-keyword">int64</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">var</span> animal = Animal{Age: <span class="hljs-number">99</span>, Name: <span class="hljs-string">""</span>}
|
<span class="hljs-keyword">var</span> animal = Animal{Age: <span class="hljs-number">99</span>, Name: <span class="hljs-string">""</span>}
|
||||||
@ -704,10 +734,10 @@ db.Create(&animal)
|
|||||||
<span class="hljs-comment">// animal.Name => 'galeone'</span>
|
<span class="hljs-comment">// animal.Name => 'galeone'</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="setting-primary-key-in-callbacks">Setting Primary Key In Callbacks</h3>
|
<h3 id="setting-primary-key-in-callbacks">Setting Primary Key In Callbacks</h3>
|
||||||
<p>If you want to set primary key in <code>BeforeCreate</code> callback, you could use <code>scope.SetColumn</code>, for example:</p>
|
<p>If you want to set primary field's value in <code>BeforeCreate</code> callback, you could use <code>scope.SetColumn</code>, for example:</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (user *User) BeforeCreate(scope *gorm.Scope) error {
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (user *User) BeforeCreate(scope *gorm.Scope) error {
|
||||||
scope.SetColumn(<span class="hljs-string">"ID"</span>, uuid.New())
|
scope.SetColumn(<span class="hljs-string">"ID"</span>, uuid.New())
|
||||||
<span class="hljs-keyword">return</span> <span class="hljs-constant">nil</span>
|
<span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="extra-creating-option">Extra Creating option</h3>
|
<h3 id="extra-creating-option">Extra Creating option</h3>
|
||||||
@ -716,11 +746,11 @@ db.Set(<span class="hljs-string">"gorm:insert_option"</span>, <span cl
|
|||||||
<span class="hljs-comment">// INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT;</span>
|
<span class="hljs-comment">// INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="query">Query</h2>
|
<h2 id="query">Query</h2>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Get the first record</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Get first record, order by primary key</span>
|
||||||
db.First(&user)
|
db.First(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users ORDER BY id LIMIT 1;</span>
|
<span class="hljs-comment">//// SELECT * FROM users ORDER BY id LIMIT 1;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Get the last record</span>
|
<span class="hljs-comment">// Get last record, order by primary key</span>
|
||||||
db.Last(&user)
|
db.Last(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users ORDER BY id DESC LIMIT 1;</span>
|
<span class="hljs-comment">//// SELECT * FROM users ORDER BY id DESC LIMIT 1;</span>
|
||||||
|
|
||||||
@ -733,7 +763,7 @@ db.First(&user, <span class="hljs-number">10</span>)
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE id = 10;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE id = 10;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="query-with-where-plain-sql">Query With Where (Plain SQL)</h3>
|
<h3 id="query-with-where-plain-sql">Query With Where (Plain SQL)</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Get the first matched record</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Get first matched record</span>
|
||||||
db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&user)
|
db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).First(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;</span>
|
||||||
|
|
||||||
@ -744,13 +774,13 @@ db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hlj
|
|||||||
db.Where(<span class="hljs-string">"name <> ?"</span>, <span class="hljs-string">"jinzhu"</span>).Find(&users)
|
db.Where(<span class="hljs-string">"name <> ?"</span>, <span class="hljs-string">"jinzhu"</span>).Find(&users)
|
||||||
|
|
||||||
<span class="hljs-comment">// IN</span>
|
<span class="hljs-comment">// IN</span>
|
||||||
db.Where(<span class="hljs-string">"name in (?)"</span>, []<span class="hljs-typename">string</span>{<span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"jinzhu 2"</span>}).Find(&users)
|
db.Where(<span class="hljs-string">"name in (?)"</span>, []<span class="hljs-keyword">string</span>{<span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"jinzhu 2"</span>}).Find(&users)
|
||||||
|
|
||||||
<span class="hljs-comment">// LIKE</span>
|
<span class="hljs-comment">// LIKE</span>
|
||||||
db.Where(<span class="hljs-string">"name LIKE ?"</span>, <span class="hljs-string">"%jin%"</span>).Find(&users)
|
db.Where(<span class="hljs-string">"name LIKE ?"</span>, <span class="hljs-string">"%jin%"</span>).Find(&users)
|
||||||
|
|
||||||
<span class="hljs-comment">// AND</span>
|
<span class="hljs-comment">// AND</span>
|
||||||
db.Where(<span class="hljs-string">"name = ? and age >= ?"</span>, <span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"22"</span>).Find(&users)
|
db.Where(<span class="hljs-string">"name = ? AND age >= ?"</span>, <span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"22"</span>).Find(&users)
|
||||||
|
|
||||||
<span class="hljs-comment">// Time</span>
|
<span class="hljs-comment">// Time</span>
|
||||||
db.Where(<span class="hljs-string">"updated_at > ?"</span>, lastWeek).Find(&users)
|
db.Where(<span class="hljs-string">"updated_at > ?"</span>, lastWeek).Find(&users)
|
||||||
@ -758,16 +788,17 @@ db.Where(<span class="hljs-string">"updated_at > ?"</span>, lastWee
|
|||||||
db.Where(<span class="hljs-string">"created_at BETWEEN ? AND ?"</span>, lastWeek, today).Find(&users)
|
db.Where(<span class="hljs-string">"created_at BETWEEN ? AND ?"</span>, lastWeek, today).Find(&users)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="query-with-where-struct--map">Query With Where (Struct & Map)</h3>
|
<h3 id="query-with-where-struct--map">Query With Where (Struct & Map)</h3>
|
||||||
|
<p><strong>NOTE</strong> When query with struct, GORM will only query with those fields has value</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Struct</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Struct</span>
|
||||||
db.Where(&User{Name: <span class="hljs-string">"jinzhu"</span>, Age: <span class="hljs-number">20</span>}).First(&user)
|
db.Where(&User{Name: <span class="hljs-string">"jinzhu"</span>, Age: <span class="hljs-number">20</span>}).First(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Map</span>
|
<span class="hljs-comment">// Map</span>
|
||||||
db.Where(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">20</span>}).Find(&users)
|
db.Where(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">20</span>}).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Slice of primary keys</span>
|
<span class="hljs-comment">// Slice of primary keys</span>
|
||||||
db.Where([]<span class="hljs-typename">int64</span>{<span class="hljs-number">20</span>, <span class="hljs-number">21</span>, <span class="hljs-number">22</span>}).Find(&users)
|
db.Where([]<span class="hljs-keyword">int64</span>{<span class="hljs-number">20</span>, <span class="hljs-number">21</span>, <span class="hljs-number">22</span>}).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE id IN (20, 21, 22);</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE id IN (20, 21, 22);</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="query-with-not">Query With Not</h3>
|
<h3 id="query-with-not">Query With Not</h3>
|
||||||
@ -775,14 +806,14 @@ db.Where([]<span class="hljs-typename">int64</span>{<span class="hljs-number">20
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Not In</span>
|
<span class="hljs-comment">// Not In</span>
|
||||||
db.Not(<span class="hljs-string">"name"</span>, []<span class="hljs-typename">string</span>{<span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"jinzhu 2"</span>}).Find(&users)
|
db.Not(<span class="hljs-string">"name"</span>, []<span class="hljs-keyword">string</span>{<span class="hljs-string">"jinzhu"</span>, <span class="hljs-string">"jinzhu 2"</span>}).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Not In slice of primary keys</span>
|
<span class="hljs-comment">// Not In slice of primary keys</span>
|
||||||
db.Not([]<span class="hljs-typename">int64</span>{<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>}).First(&user)
|
db.Not([]<span class="hljs-keyword">int64</span>{<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>}).First(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE id NOT IN (1,2,3);</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE id NOT IN (1,2,3);</span>
|
||||||
|
|
||||||
db.Not([]<span class="hljs-typename">int64</span>{}).First(&user)
|
db.Not([]<span class="hljs-keyword">int64</span>{}).First(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users;</span>
|
<span class="hljs-comment">//// SELECT * FROM users;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Plain SQL</span>
|
<span class="hljs-comment">// Plain SQL</span>
|
||||||
@ -794,6 +825,7 @@ db.Not(User{Name: <span class="hljs-string">"jinzhu"</span>}).First(&a
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name <> "jinzhu";</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name <> "jinzhu";</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="query-with-inline-condition">Query With Inline Condition</h3>
|
<h3 id="query-with-inline-condition">Query With Inline Condition</h3>
|
||||||
|
<p><strong>NOTE</strong> When query with primary key, you should carefully check the value you passed is a valid primary key, to avoid SQL injection</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Get by primary key</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Get by primary key</span>
|
||||||
db.First(&user, <span class="hljs-number">23</span>)
|
db.First(&user, <span class="hljs-number">23</span>)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE id = 23 LIMIT 1;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE id = 23 LIMIT 1;</span>
|
||||||
@ -810,7 +842,7 @@ db.Find(&users, User{Age: <span class="hljs-number">20</span>})
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE age = 20;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE age = 20;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Map</span>
|
<span class="hljs-comment">// Map</span>
|
||||||
db.Find(&users, <span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"age"</span>: <span class="hljs-number">20</span>})
|
db.Find(&users, <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"age"</span>: <span class="hljs-number">20</span>})
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE age = 20;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE age = 20;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="query-with-or">Query With Or</h3>
|
<h3 id="query-with-or">Query With Or</h3>
|
||||||
@ -822,7 +854,7 @@ db.Where(<span class="hljs-string">"name = 'jinzhu'"</span>)
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Map</span>
|
<span class="hljs-comment">// Map</span>
|
||||||
db.Where(<span class="hljs-string">"name = 'jinzhu'"</span>).Or(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"jinzhu 2"</span>}).Find(&users)
|
db.Where(<span class="hljs-string">"name = 'jinzhu'"</span>).Or(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"jinzhu 2"</span>}).Find(&users)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="query-chains">Query Chains</h3>
|
<h3 id="query-chains">Query Chains</h3>
|
||||||
<p>Gorm has a chainable API, you could use it like this</p>
|
<p>Gorm has a chainable API, you could use it like this</p>
|
||||||
@ -837,7 +869,7 @@ db.Set(<span class="hljs-string">"gorm:query_option"</span>, <span cla
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE id = 10 FOR UPDATE;</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE id = 10 FOR UPDATE;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="firstorinit">FirstOrInit</h3>
|
<h3 id="firstorinit">FirstOrInit</h3>
|
||||||
<p>Get the first matched record, or initialize a record with search conditions.</p>
|
<p>Get first matched record, or initalize a new one with given conditions (only works with struct, map conditions)</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
||||||
db.FirstOrInit(&user, User{Name: <span class="hljs-string">"non_existing"</span>})
|
db.FirstOrInit(&user, User{Name: <span class="hljs-string">"non_existing"</span>})
|
||||||
<span class="hljs-comment">//// user -> User{Name: "non_existing"}</span>
|
<span class="hljs-comment">//// user -> User{Name: "non_existing"}</span>
|
||||||
@ -845,17 +877,17 @@ db.FirstOrInit(&user, User{Name: <span class="hljs-string">"non_existin
|
|||||||
<span class="hljs-comment">// Found</span>
|
<span class="hljs-comment">// Found</span>
|
||||||
db.Where(User{Name: <span class="hljs-string">"Jinzhu"</span>}).FirstOrInit(&user)
|
db.Where(User{Name: <span class="hljs-string">"Jinzhu"</span>}).FirstOrInit(&user)
|
||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}</span>
|
||||||
db.FirstOrInit(&user, <span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"jinzhu"</span>})
|
db.FirstOrInit(&user, <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"jinzhu"</span>})
|
||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h4 id="attrs">Attrs</h4>
|
<h4 id="attrs">Attrs</h4>
|
||||||
<p>Ignore some values when searching, but use them to initialize the struct if record is not found.</p>
|
<p>Initalize struct with argument if record haven't been found</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
||||||
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Attrs(User{Age: <span class="hljs-number">20</span>}).FirstOrInit(&user)
|
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Attrs(User{Age: <span class="hljs-number">20</span>}).FirstOrInit(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM USERS WHERE name = 'non_existing';</span>
|
<span class="hljs-comment">//// SELECT * FROM USERS WHERE name = 'non_existing';</span>
|
||||||
<span class="hljs-comment">//// user -> User{Name: "non_existing", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Name: "non_existing", Age: 20}</span>
|
||||||
|
|
||||||
db.Where(User{Name: <span class="hljs-string">"noexisting_user"</span>}).Attrs(<span class="hljs-string">"age"</span>, <span class="hljs-number">20</span>).FirstOrInit(&user)
|
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Attrs(<span class="hljs-string">"age"</span>, <span class="hljs-number">20</span>).FirstOrInit(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM USERS WHERE name = 'non_existing';</span>
|
<span class="hljs-comment">//// SELECT * FROM USERS WHERE name = 'non_existing';</span>
|
||||||
<span class="hljs-comment">//// user -> User{Name: "non_existing", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Name: "non_existing", Age: 20}</span>
|
||||||
|
|
||||||
@ -865,7 +897,7 @@ db.Where(User{Name: <span class="hljs-string">"Jinzhu"</span>}).Attrs(
|
|||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h4 id="assign">Assign</h4>
|
<h4 id="assign">Assign</h4>
|
||||||
<p>Ignore some values when searching, but assign it to the result regardless it is found or not.</p>
|
<p>Assign argument to results regardless it is found or not</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
||||||
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Assign(User{Age: <span class="hljs-number">20</span>}).FirstOrInit(&user)
|
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Assign(User{Age: <span class="hljs-number">20</span>}).FirstOrInit(&user)
|
||||||
<span class="hljs-comment">//// user -> User{Name: "non_existing", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Name: "non_existing", Age: 20}</span>
|
||||||
@ -876,7 +908,7 @@ db.Where(User{Name: <span class="hljs-string">"Jinzhu"</span>}).Assign
|
|||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 30}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu", Age: 30}</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="firstorcreate">FirstOrCreate</h3>
|
<h3 id="firstorcreate">FirstOrCreate</h3>
|
||||||
<p>Get the first matched record, or create with search conditions.</p>
|
<p>Get first matched record, or create a new one with given conditions (only works with struct, map conditions)</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
||||||
db.FirstOrCreate(&user, User{Name: <span class="hljs-string">"non_existing"</span>})
|
db.FirstOrCreate(&user, User{Name: <span class="hljs-string">"non_existing"</span>})
|
||||||
<span class="hljs-comment">//// INSERT INTO "users" (name) VALUES ("non_existing");</span>
|
<span class="hljs-comment">//// INSERT INTO "users" (name) VALUES ("non_existing");</span>
|
||||||
@ -887,7 +919,7 @@ db.Where(User{Name: <span class="hljs-string">"Jinzhu"</span>}).FirstO
|
|||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu"}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "Jinzhu"}</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h4 id="attrs">Attrs</h4>
|
<h4 id="attrs">Attrs</h4>
|
||||||
<p>Ignore some values when searching, but use them to create the struct if record is not found. like <code>FirstOrInit</code></p>
|
<p>Assgin struct with argument if record haven't been found</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
||||||
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Attrs(User{Age: <span class="hljs-number">20</span>}).FirstOrCreate(&user)
|
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Attrs(User{Age: <span class="hljs-number">20</span>}).FirstOrCreate(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'non_existing';</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'non_existing';</span>
|
||||||
@ -900,7 +932,7 @@ db.Where(User{Name: <span class="hljs-string">"jinzhu"</span>}).Attrs(
|
|||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "jinzhu", Age: 20}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "jinzhu", Age: 20}</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h4 id="assign">Assign</h4>
|
<h4 id="assign">Assign</h4>
|
||||||
<p>Ignore some values when searching, but assign it to the record regardless it is found or not, then save back to database. like <code>FirstOrInit</code></p>
|
<p>Assign it to the record regardless it is found or not, and save back to database.</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Unfound</span>
|
||||||
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Assign(User{Age: <span class="hljs-number">20</span>}).FirstOrCreate(&user)
|
db.Where(User{Name: <span class="hljs-string">"non_existing"</span>}).Assign(User{Age: <span class="hljs-number">20</span>}).FirstOrCreate(&user)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'non_existing';</span>
|
<span class="hljs-comment">//// SELECT * FROM users WHERE name = 'non_existing';</span>
|
||||||
@ -914,16 +946,18 @@ db.Where(User{Name: <span class="hljs-string">"jinzhu"</span>}).Assign
|
|||||||
<span class="hljs-comment">//// user -> User{Id: 111, Name: "jinzhu", Age: 30}</span>
|
<span class="hljs-comment">//// user -> User{Id: 111, Name: "jinzhu", Age: 30}</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="select">Select</h3>
|
<h3 id="select">Select</h3>
|
||||||
|
<p>Specify fields that you want to retrieve from database, by default, will select all fields;</p>
|
||||||
<pre><code class="lang-go">db.Select(<span class="hljs-string">"name, age"</span>).Find(&users)
|
<pre><code class="lang-go">db.Select(<span class="hljs-string">"name, age"</span>).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT name, age FROM users;</span>
|
<span class="hljs-comment">//// SELECT name, age FROM users;</span>
|
||||||
|
|
||||||
db.Select([]<span class="hljs-typename">string</span>{<span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>}).Find(&users)
|
db.Select([]<span class="hljs-keyword">string</span>{<span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>}).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT name, age FROM users;</span>
|
<span class="hljs-comment">//// SELECT name, age FROM users;</span>
|
||||||
|
|
||||||
db.Table(<span class="hljs-string">"users"</span>).Select(<span class="hljs-string">"COALESCE(age,?)"</span>, <span class="hljs-number">42</span>).Rows()
|
db.Table(<span class="hljs-string">"users"</span>).Select(<span class="hljs-string">"COALESCE(age,?)"</span>, <span class="hljs-number">42</span>).Rows()
|
||||||
<span class="hljs-comment">//// SELECT COALESCE(age,'42') FROM users;</span>
|
<span class="hljs-comment">//// SELECT COALESCE(age,'42') FROM users;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="order">Order</h3>
|
<h3 id="order">Order</h3>
|
||||||
|
<p>Specify order when retrieve records from database, set reorder to <code>true</code> to overwrite defined conditions</p>
|
||||||
<pre><code class="lang-go">db.Order(<span class="hljs-string">"age desc, name"</span>).Find(&users)
|
<pre><code class="lang-go">db.Order(<span class="hljs-string">"age desc, name"</span>).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age desc, name;</span>
|
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age desc, name;</span>
|
||||||
|
|
||||||
@ -932,29 +966,32 @@ db.Order(<span class="hljs-string">"age desc"</span>).Order(<span clas
|
|||||||
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age desc, name;</span>
|
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age desc, name;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// ReOrder</span>
|
<span class="hljs-comment">// ReOrder</span>
|
||||||
db.Order(<span class="hljs-string">"age desc"</span>).Find(&users1).Order(<span class="hljs-string">"age"</span>, <span class="hljs-constant">true</span>).Find(&users2)
|
db.Order(<span class="hljs-string">"age desc"</span>).Find(&users1).Order(<span class="hljs-string">"age"</span>, <span class="hljs-literal">true</span>).Find(&users2)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age desc; (users1)</span>
|
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age desc; (users1)</span>
|
||||||
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age; (users2)</span>
|
<span class="hljs-comment">//// SELECT * FROM users ORDER BY age; (users2)</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="limit">Limit</h3>
|
<h3 id="limit">Limit</h3>
|
||||||
|
<p>Specify the number of records to be retrieved</p>
|
||||||
<pre><code class="lang-go">db.Limit(<span class="hljs-number">3</span>).Find(&users)
|
<pre><code class="lang-go">db.Limit(<span class="hljs-number">3</span>).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users LIMIT 3;</span>
|
<span class="hljs-comment">//// SELECT * FROM users LIMIT 3;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Cancel limit condition with -1</span>
|
<span class="hljs-comment">// Cancel limit condition with -1</span>
|
||||||
db.Limit(<span class="hljs-number">10</span>).Find(&users1).Limit(-<span class="hljs-number">1</span>).Find(&users2)
|
db.Limit(<span class="hljs-number">10</span>).Find(&users1).Limit(<span class="hljs-number">-1</span>).Find(&users2)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users LIMIT 10; (users1)</span>
|
<span class="hljs-comment">//// SELECT * FROM users LIMIT 10; (users1)</span>
|
||||||
<span class="hljs-comment">//// SELECT * FROM users; (users2)</span>
|
<span class="hljs-comment">//// SELECT * FROM users; (users2)</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="offset">Offset</h3>
|
<h3 id="offset">Offset</h3>
|
||||||
|
<p>Specify the number of records to skip before starting to return the records</p>
|
||||||
<pre><code class="lang-go">db.Offset(<span class="hljs-number">3</span>).Find(&users)
|
<pre><code class="lang-go">db.Offset(<span class="hljs-number">3</span>).Find(&users)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users OFFSET 3;</span>
|
<span class="hljs-comment">//// SELECT * FROM users OFFSET 3;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Cancel offset condition with -1</span>
|
<span class="hljs-comment">// Cancel offset condition with -1</span>
|
||||||
db.Offset(<span class="hljs-number">10</span>).Find(&users1).Offset(-<span class="hljs-number">1</span>).Find(&users2)
|
db.Offset(<span class="hljs-number">10</span>).Find(&users1).Offset(<span class="hljs-number">-1</span>).Find(&users2)
|
||||||
<span class="hljs-comment">//// SELECT * FROM users OFFSET 10; (users1)</span>
|
<span class="hljs-comment">//// SELECT * FROM users OFFSET 10; (users1)</span>
|
||||||
<span class="hljs-comment">//// SELECT * FROM users; (users2)</span>
|
<span class="hljs-comment">//// SELECT * FROM users; (users2)</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="count">Count</h3>
|
<h3 id="count">Count</h3>
|
||||||
|
<p>Get how many records for a model</p>
|
||||||
<pre><code class="lang-go">db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).Or(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu 2"</span>).Find(&users).Count(&count)
|
<pre><code class="lang-go">db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>).Or(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu 2"</span>).Find(&users).Count(&count)
|
||||||
<span class="hljs-comment">//// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)</span>
|
<span class="hljs-comment">//// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)</span>
|
||||||
<span class="hljs-comment">//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)</span>
|
<span class="hljs-comment">//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)</span>
|
||||||
@ -978,11 +1015,12 @@ rows, err := db.Table(<span class="hljs-string">"orders"</span>).Selec
|
|||||||
|
|
||||||
<span class="hljs-keyword">type</span> Result <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Result <span class="hljs-keyword">struct</span> {
|
||||||
Date time.Time
|
Date time.Time
|
||||||
Total <span class="hljs-typename">int64</span>
|
Total <span class="hljs-keyword">int64</span>
|
||||||
}
|
}
|
||||||
db.Table(<span class="hljs-string">"orders"</span>).Select(<span class="hljs-string">"date(created_at) as date, sum(amount) as total"</span>).Group(<span class="hljs-string">"date(created_at)"</span>).Having(<span class="hljs-string">"sum(amount) > ?"</span>, <span class="hljs-number">100</span>).Scan(&results)
|
db.Table(<span class="hljs-string">"orders"</span>).Select(<span class="hljs-string">"date(created_at) as date, sum(amount) as total"</span>).Group(<span class="hljs-string">"date(created_at)"</span>).Having(<span class="hljs-string">"sum(amount) > ?"</span>, <span class="hljs-number">100</span>).Scan(&results)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="joins">Joins</h3>
|
<h3 id="joins">Joins</h3>
|
||||||
|
<p>Specify Joins conditions</p>
|
||||||
<pre><code class="lang-go">rows, err := db.Table(<span class="hljs-string">"users"</span>).Select(<span class="hljs-string">"users.name, emails.email"</span>).Joins(<span class="hljs-string">"left join emails on emails.user_id = users.id"</span>).Rows()
|
<pre><code class="lang-go">rows, err := db.Table(<span class="hljs-string">"users"</span>).Select(<span class="hljs-string">"users.name, emails.email"</span>).Joins(<span class="hljs-string">"left join emails on emails.user_id = users.id"</span>).Rows()
|
||||||
<span class="hljs-keyword">for</span> rows.Next() {
|
<span class="hljs-keyword">for</span> rows.Next() {
|
||||||
...
|
...
|
||||||
@ -994,11 +1032,11 @@ db.Table(<span class="hljs-string">"users"</span>).Select(<span class=
|
|||||||
db.Joins(<span class="hljs-string">"JOIN emails ON emails.user_id = users.id AND emails.email = ?"</span>, <span class="hljs-string">"jinzhu@example.org"</span>).Joins(<span class="hljs-string">"JOIN credit_cards ON credit_cards.user_id = users.id"</span>).Where(<span class="hljs-string">"credit_cards.number = ?"</span>, <span class="hljs-string">"411111111111"</span>).Find(&user)
|
db.Joins(<span class="hljs-string">"JOIN emails ON emails.user_id = users.id AND emails.email = ?"</span>, <span class="hljs-string">"jinzhu@example.org"</span>).Joins(<span class="hljs-string">"JOIN credit_cards ON credit_cards.user_id = users.id"</span>).Where(<span class="hljs-string">"credit_cards.number = ?"</span>, <span class="hljs-string">"411111111111"</span>).Find(&user)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="pluck">Pluck</h3>
|
<h3 id="pluck">Pluck</h3>
|
||||||
<p>Get selected attributes as map</p>
|
<p>Query single column from a model as a map, if you want to query multiple columns, you could use <a href="#scan"><code>Scan</code></a></p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">var</span> ages []<span class="hljs-typename">int64</span>
|
<pre><code class="lang-go"><span class="hljs-keyword">var</span> ages []<span class="hljs-keyword">int64</span>
|
||||||
db.Find(&users).Pluck(<span class="hljs-string">"age"</span>, &ages)
|
db.Find(&users).Pluck(<span class="hljs-string">"age"</span>, &ages)
|
||||||
|
|
||||||
<span class="hljs-keyword">var</span> names []<span class="hljs-typename">string</span>
|
<span class="hljs-keyword">var</span> names []<span class="hljs-keyword">string</span>
|
||||||
db.Model(&User{}).Pluck(<span class="hljs-string">"name"</span>, &names)
|
db.Model(&User{}).Pluck(<span class="hljs-string">"name"</span>, &names)
|
||||||
|
|
||||||
db.Table(<span class="hljs-string">"deleted_users"</span>).Pluck(<span class="hljs-string">"name"</span>, &names)
|
db.Table(<span class="hljs-string">"deleted_users"</span>).Pluck(<span class="hljs-string">"name"</span>, &names)
|
||||||
@ -1009,8 +1047,8 @@ db.Select(<span class="hljs-string">"name, age"</span>).Find(&user
|
|||||||
<h3 id="scan">Scan</h3>
|
<h3 id="scan">Scan</h3>
|
||||||
<p>Scan results into another struct.</p>
|
<p>Scan results into another struct.</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Result <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Result <span class="hljs-keyword">struct</span> {
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
Age <span class="hljs-typename">int</span>
|
Age <span class="hljs-keyword">int</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">var</span> result Result
|
<span class="hljs-keyword">var</span> result Result
|
||||||
@ -1020,6 +1058,7 @@ db.Table(<span class="hljs-string">"users"</span>).Select(<span class=
|
|||||||
db.Raw(<span class="hljs-string">"SELECT name, age FROM users WHERE name = ?"</span>, <span class="hljs-number">3</span>).Scan(&result)
|
db.Raw(<span class="hljs-string">"SELECT name, age FROM users WHERE name = ?"</span>, <span class="hljs-number">3</span>).Scan(&result)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="scopes">Scopes</h3>
|
<h3 id="scopes">Scopes</h3>
|
||||||
|
<p>Pass current database connection to <code>func(*DB) *DB</code>, which could be used to add conditions dynamically</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">func</span> AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
|
||||||
<span class="hljs-keyword">return</span> db.Where(<span class="hljs-string">"amount > ?"</span>, <span class="hljs-number">1000</span>)
|
<span class="hljs-keyword">return</span> db.Where(<span class="hljs-string">"amount > ?"</span>, <span class="hljs-number">1000</span>)
|
||||||
}
|
}
|
||||||
@ -1032,7 +1071,7 @@ db.Raw(<span class="hljs-string">"SELECT name, age FROM users WHERE name =
|
|||||||
<span class="hljs-keyword">return</span> db.Where(<span class="hljs-string">"pay_mode_sign = ?"</span>, <span class="hljs-string">"C"</span>)
|
<span class="hljs-keyword">return</span> db.Where(<span class="hljs-string">"pay_mode_sign = ?"</span>, <span class="hljs-string">"C"</span>)
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> OrderStatus(status []<span class="hljs-typename">string</span>) <span class="hljs-keyword">func</span> (db *gorm.DB) *gorm.DB {
|
<span class="hljs-keyword">func</span> OrderStatus(status []<span class="hljs-keyword">string</span>) <span class="hljs-keyword">func</span> (db *gorm.DB) *gorm.DB {
|
||||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">func</span> (db *gorm.DB) *gorm.DB {
|
<span class="hljs-keyword">return</span> <span class="hljs-keyword">func</span> (db *gorm.DB) *gorm.DB {
|
||||||
<span class="hljs-keyword">return</span> db.Scopes(AmountGreaterThan1000).Where(<span class="hljs-string">"status in (?)"</span>, status)
|
<span class="hljs-keyword">return</span> db.Scopes(AmountGreaterThan1000).Where(<span class="hljs-string">"status in (?)"</span>, status)
|
||||||
}
|
}
|
||||||
@ -1044,7 +1083,7 @@ db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
|
|||||||
db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
|
db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
|
||||||
<span class="hljs-comment">// Find all COD orders and amount greater than 1000</span>
|
<span class="hljs-comment">// Find all COD orders and amount greater than 1000</span>
|
||||||
|
|
||||||
db.Scopes(OrderStatus([]<span class="hljs-typename">string</span>{<span class="hljs-string">"paid"</span>, <span class="hljs-string">"shipped"</span>})).Find(&orders)
|
db.Scopes(OrderStatus([]<span class="hljs-keyword">string</span>{<span class="hljs-string">"paid"</span>, <span class="hljs-string">"shipped"</span>})).Find(&orders)
|
||||||
<span class="hljs-comment">// Find all paid, shipped orders</span>
|
<span class="hljs-comment">// Find all paid, shipped orders</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="specifying-the-table-name">Specifying The Table Name</h3>
|
<h3 id="specifying-the-table-name">Specifying The Table Name</h3>
|
||||||
@ -1076,12 +1115,11 @@ db.Model(&user).Update(<span class="hljs-string">"name"</span>, <s
|
|||||||
<span class="hljs-comment">//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
<span class="hljs-comment">//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Update single attribute with combined conditions</span>
|
<span class="hljs-comment">// Update single attribute with combined conditions</span>
|
||||||
db.Model(&user).Where(<span class="hljs-string">"active = ?"</span>, <span class="hljs-constant">true</span>).Update(<span class="hljs-string">"name"</span>, <span class="hljs-string">"hello"</span>)
|
db.Model(&user).Where(<span class="hljs-string">"active = ?"</span>, <span class="hljs-literal">true</span>).Update(<span class="hljs-string">"name"</span>, <span class="hljs-string">"hello"</span>)
|
||||||
<span class="hljs-comment">//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;</span>
|
<span class="hljs-comment">//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;</span>
|
||||||
|
|
||||||
|
|
||||||
<span class="hljs-comment">// Update multiple attributes with `map`, will only update those changed fields</span>
|
<span class="hljs-comment">// Update multiple attributes with `map`, will only update those changed fields</span>
|
||||||
db.Model(&user).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>, <span class="hljs-string">"actived"</span>: <span class="hljs-constant">false</span>})
|
db.Model(&user).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>, <span class="hljs-string">"actived"</span>: <span class="hljs-literal">false</span>})
|
||||||
<span class="hljs-comment">//// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
<span class="hljs-comment">//// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Update multiple attributes with `struct`, will only update those changed & non blank fields</span>
|
<span class="hljs-comment">// Update multiple attributes with `struct`, will only update those changed & non blank fields</span>
|
||||||
@ -1090,18 +1128,18 @@ db.Model(&user).Updates(User{Name: <span class="hljs-string">"hello&quo
|
|||||||
|
|
||||||
<span class="hljs-comment">// WARNING when update with struct, GORM will only update those fields that with non blank value</span>
|
<span class="hljs-comment">// WARNING when update with struct, GORM will only update those fields that with non blank value</span>
|
||||||
<span class="hljs-comment">// For below Update, nothing will be updated as "", 0, false are blank values of their types</span>
|
<span class="hljs-comment">// For below Update, nothing will be updated as "", 0, false are blank values of their types</span>
|
||||||
db.Model(&user).Updates(User{Name: <span class="hljs-string">""</span>, Age: <span class="hljs-number">0</span>, Actived: <span class="hljs-constant">false</span>})
|
db.Model(&user).Updates(User{Name: <span class="hljs-string">""</span>, Age: <span class="hljs-number">0</span>, Actived: <span class="hljs-literal">false</span>})
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="update-selected-fields">Update Selected Fields</h3>
|
<h3 id="update-selected-fields">Update Selected Fields</h3>
|
||||||
<p>If you only want to update or ignore some fields when updating, you could use <code>Select</code>, <code>Omit</code></p>
|
<p>If you only want to update or ignore some fields when updating, you could use <code>Select</code>, <code>Omit</code></p>
|
||||||
<pre><code class="lang-go">db.Model(&user).Select(<span class="hljs-string">"name"</span>).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>, <span class="hljs-string">"actived"</span>: <span class="hljs-constant">false</span>})
|
<pre><code class="lang-go">db.Model(&user).Select(<span class="hljs-string">"name"</span>).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>, <span class="hljs-string">"actived"</span>: <span class="hljs-literal">false</span>})
|
||||||
<span class="hljs-comment">//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
<span class="hljs-comment">//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
||||||
|
|
||||||
db.Model(&user).Omit(<span class="hljs-string">"name"</span>).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>, <span class="hljs-string">"actived"</span>: <span class="hljs-constant">false</span>})
|
db.Model(&user).Omit(<span class="hljs-string">"name"</span>).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>, <span class="hljs-string">"actived"</span>: <span class="hljs-literal">false</span>})
|
||||||
<span class="hljs-comment">//// UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
<span class="hljs-comment">//// UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="update-changed-fields-without-callbacks">Update Changed Fields Without Callbacks</h3>
|
<h3 id="update-changed-fields-without-callbacks">Update Changed Fields Without Callbacks</h3>
|
||||||
<p>Updating operations above will invoke <code>BeforeUpdate</code>, <code>AfterUpdate</code>, Update UpdatedAt timestamp, Save Associations callbacks, if you don't call them, you could use <code>UpdateColumn</code>, <code>UpdateColumns</code></p>
|
<p>Above updating operations will perform the mdoel's <code>BeforeUpdate</code>, <code>AfterUpdate</code> method, update its <code>UpdatedAt</code> timestamp, save its <code>Associations</code> when updaing, if you don't want to call them, you could use <code>UpdateColumn</code>, <code>UpdateColumns</code></p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Update single attribute, similar with `Update`</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Update single attribute, similar with `Update`</span>
|
||||||
db.Model(&user).UpdateColumn(<span class="hljs-string">"name"</span>, <span class="hljs-string">"hello"</span>)
|
db.Model(&user).UpdateColumn(<span class="hljs-string">"name"</span>, <span class="hljs-string">"hello"</span>)
|
||||||
<span class="hljs-comment">//// UPDATE users SET name='hello' WHERE id = 111;</span>
|
<span class="hljs-comment">//// UPDATE users SET name='hello' WHERE id = 111;</span>
|
||||||
@ -1112,7 +1150,7 @@ db.Model(&user).UpdateColumns(User{Name: <span class="hljs-string">"hel
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="batch-updates">Batch Updates</h3>
|
<h3 id="batch-updates">Batch Updates</h3>
|
||||||
<p>Callbacks won't run when do batch updates</p>
|
<p>Callbacks won't run when do batch updates</p>
|
||||||
<pre><code class="lang-go">db.Table(<span class="hljs-string">"users"</span>).Where(<span class="hljs-string">"id IN (?)"</span>, []<span class="hljs-typename">int</span>{<span class="hljs-number">10</span>, <span class="hljs-number">11</span>}).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>})
|
<pre><code class="lang-go">db.Table(<span class="hljs-string">"users"</span>).Where(<span class="hljs-string">"id IN (?)"</span>, []<span class="hljs-keyword">int</span>{<span class="hljs-number">10</span>, <span class="hljs-number">11</span>}).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"name"</span>: <span class="hljs-string">"hello"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">18</span>})
|
||||||
<span class="hljs-comment">//// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);</span>
|
<span class="hljs-comment">//// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// Update with struct only works with none zero values, or use map[string]interface{}</span>
|
<span class="hljs-comment">// Update with struct only works with none zero values, or use map[string]interface{}</span>
|
||||||
@ -1126,7 +1164,7 @@ db.Model(User{}).Updates(User{Name: <span class="hljs-string">"hello"<
|
|||||||
<pre><code class="lang-go">DB.Model(&product).Update(<span class="hljs-string">"price"</span>, gorm.Expr(<span class="hljs-string">"price * ? + ?"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">100</span>))
|
<pre><code class="lang-go">DB.Model(&product).Update(<span class="hljs-string">"price"</span>, gorm.Expr(<span class="hljs-string">"price * ? + ?"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">100</span>))
|
||||||
<span class="hljs-comment">//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';</span>
|
<span class="hljs-comment">//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';</span>
|
||||||
|
|
||||||
DB.Model(&product).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-typename">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"price"</span>: gorm.Expr(<span class="hljs-string">"price * ? + ?"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">100</span>)})
|
DB.Model(&product).Updates(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">interface</span>{}{<span class="hljs-string">"price"</span>: gorm.Expr(<span class="hljs-string">"price * ? + ?"</span>, <span class="hljs-number">2</span>, <span class="hljs-number">100</span>)})
|
||||||
<span class="hljs-comment">//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';</span>
|
<span class="hljs-comment">//// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2';</span>
|
||||||
|
|
||||||
DB.Model(&product).UpdateColumn(<span class="hljs-string">"quantity"</span>, gorm.Expr(<span class="hljs-string">"quantity - ?"</span>, <span class="hljs-number">1</span>))
|
DB.Model(&product).UpdateColumn(<span class="hljs-string">"quantity"</span>, gorm.Expr(<span class="hljs-string">"quantity - ?"</span>, <span class="hljs-number">1</span>))
|
||||||
@ -1138,7 +1176,7 @@ DB.Model(&product).Where(<span class="hljs-string">"quantity > 1&quo
|
|||||||
<h3 id="change-updating-values-in-callbacks">Change Updating Values In Callbacks</h3>
|
<h3 id="change-updating-values-in-callbacks">Change Updating Values In Callbacks</h3>
|
||||||
<p>If you want to change updating values in callbacks using <code>BeforeUpdate</code>, <code>BeforeSave</code>, you could use <code>scope.SetColumn</code>, for example:</p>
|
<p>If you want to change updating values in callbacks using <code>BeforeUpdate</code>, <code>BeforeSave</code>, you could use <code>scope.SetColumn</code>, for example:</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (user *User) BeforeSave(scope *gorm.Scope) (err error) {
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> (user *User) BeforeSave(scope *gorm.Scope) (err error) {
|
||||||
<span class="hljs-keyword">if</span> pw, err := bcrypt.GenerateFromPassword(user.Password, <span class="hljs-number">0</span>); err == <span class="hljs-constant">nil</span> {
|
<span class="hljs-keyword">if</span> pw, err := bcrypt.GenerateFromPassword(user.Password, <span class="hljs-number">0</span>); err == <span class="hljs-literal">nil</span> {
|
||||||
scope.SetColumn(<span class="hljs-string">"EncryptedPassword"</span>, pw)
|
scope.SetColumn(<span class="hljs-string">"EncryptedPassword"</span>, pw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1149,6 +1187,7 @@ db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE F
|
|||||||
//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);
|
//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="delete">Delete</h2>
|
<h2 id="delete">Delete</h2>
|
||||||
|
<p><strong>WARNING</strong> When delete a record, you need to ensure it's primary field has value, and GORM will use the primary key to delete the record, if primary field's blank, GORM will delete all records for the model</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Delete an existing record</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Delete an existing record</span>
|
||||||
db.Delete(&email)
|
db.Delete(&email)
|
||||||
<span class="hljs-comment">//// DELETE from emails where id=10;</span>
|
<span class="hljs-comment">//// DELETE from emails where id=10;</span>
|
||||||
@ -1158,12 +1197,15 @@ db.Set(<span class="hljs-string">"gorm:delete_option"</span>, <span cl
|
|||||||
<span class="hljs-comment">//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);</span>
|
<span class="hljs-comment">//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="batch-delete">Batch Delete</h3>
|
<h3 id="batch-delete">Batch Delete</h3>
|
||||||
|
<p>Delete all matched records</p>
|
||||||
<pre><code class="lang-go">db.Where(<span class="hljs-string">"email LIKE ?"</span>, <span class="hljs-string">"%jinzhu%"</span>).Delete(Email{})
|
<pre><code class="lang-go">db.Where(<span class="hljs-string">"email LIKE ?"</span>, <span class="hljs-string">"%jinzhu%"</span>).Delete(Email{})
|
||||||
<span class="hljs-comment">//// DELETE from emails where email LIKE "%jinhu%";</span>
|
<span class="hljs-comment">//// DELETE from emails where email LIKE "%jinhu%";</span>
|
||||||
|
|
||||||
|
db.Delete(Email{}, <span class="hljs-string">"email LIKE ?"</span>, <span class="hljs-string">"%jinzhu%"</span>)
|
||||||
|
<span class="hljs-comment">//// DELETE from emails where email LIKE "%jinhu%";</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="soft-delete">Soft Delete</h3>
|
<h3 id="soft-delete">Soft Delete</h3>
|
||||||
<p>If struct has <code>DeletedAt</code> field, it will get soft delete ability automatically!
|
<p>If model has <code>DeletedAt</code> field, it will get soft delete ability automatically! then it won't be deleted from database permanently when call <code>Delete</code>, but only set field <code>DeletedAt</code>'s value to current time</p>
|
||||||
Then it won't be deleted from database permanently when call <code>Delete</code>.</p>
|
|
||||||
<pre><code class="lang-go">db.Delete(&user)
|
<pre><code class="lang-go">db.Delete(&user)
|
||||||
<span class="hljs-comment">//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;</span>
|
<span class="hljs-comment">//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;</span>
|
||||||
|
|
||||||
|
120
database.html
120
database.html
@ -5,8 +5,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="NOTE don't forgot params parseTime to handle data type time.Time, more support parameters">
|
<meta name="description" content="When connect to a database, you need to import the database's driver first, for example:">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +69,8 @@
|
|||||||
data-level="1"
|
data-level="1"
|
||||||
data-chapter-title="Database"
|
data-chapter-title="Database"
|
||||||
data-filepath="database.md"
|
data-filepath="database.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -178,12 +178,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -481,12 +481,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -496,11 +496,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -532,11 +547,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -585,7 +615,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Database</a>
|
<a href="." >Database</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -605,7 +635,6 @@
|
|||||||
<li><a href="#write-dialect-for-unsupported-databases">Write Dialect for unsupported databases</a></li>
|
<li><a href="#write-dialect-for-unsupported-databases">Write Dialect for unsupported databases</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#generic-database-object-sqldb">Generic database object *sql.DB</a></li>
|
|
||||||
<li><a href="#migration">Migration</a><ul>
|
<li><a href="#migration">Migration</a><ul>
|
||||||
<li><a href="#auto-migration">Auto Migration</a></li>
|
<li><a href="#auto-migration">Auto Migration</a></li>
|
||||||
<li><a href="#has-table">Has Table</a></li>
|
<li><a href="#has-table">Has Table</a></li>
|
||||||
@ -620,12 +649,22 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<!-- toc stop -->
|
<!-- toc stop -->
|
||||||
<h2 id="connecting-to-a-database">Connecting to a database</h2>
|
<h2 id="connecting-to-a-database">Connecting to a database</h2>
|
||||||
|
<p>When connect to a database, you need to import the database's driver first, for example:</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">import</span> _ <span class="hljs-string">"github.com/go-sql-driver/mysql"</span>
|
||||||
|
</code></pre>
|
||||||
|
<p>GORM has wrapped some drivers, for easier to remember the import path, so you could import the mysql driver with</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">import</span> _ <span class="hljs-string">"github.com/jinzhu/gorm/dialects/mysql"</span>
|
||||||
|
<span class="hljs-comment">// import _ "github.com/jinzhu/gorm/dialects/postgres"</span>
|
||||||
|
<span class="hljs-comment">// import _ "github.com/jinzhu/gorm/dialects/sqlite"</span>
|
||||||
|
<span class="hljs-comment">// import _ "github.com/jinzhu/gorm/dialects/mssql"</span>
|
||||||
|
</code></pre>
|
||||||
<h4 id="mysql">MySQL</h4>
|
<h4 id="mysql">MySQL</h4>
|
||||||
<p><strong>NOTE</strong> don't forgot params <code>parseTime</code> to handle data type <code>time.Time</code>, <a href="https://github.com/go-sql-driver/mysql#parameters" target="_blank">more support parameters</a></p>
|
<p><strong>NOTE</strong> in order to handle <code>time.Time</code> you need to include <code>parseTime</code> as param <a href="https://github.com/go-sql-driver/mysql#parameters" target="_blank">more supported parameters</a></p>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
||||||
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
||||||
_ <span class="hljs-string">"github.com/go-sql-driver/mysql"</span>
|
_ <span class="hljs-string">"github.com/jinzhu/gorm/dialects/mysql"</span>
|
||||||
)
|
)
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> main() {
|
<span class="hljs-keyword">func</span> main() {
|
||||||
db, err := gorm.Open(<span class="hljs-string">"mysql"</span>, <span class="hljs-string">"user:password@/dbname?charset=utf8&parseTime=True&loc=Local"</span>)
|
db, err := gorm.Open(<span class="hljs-string">"mysql"</span>, <span class="hljs-string">"user:password@/dbname?charset=utf8&parseTime=True&loc=Local"</span>)
|
||||||
}
|
}
|
||||||
@ -633,8 +672,9 @@
|
|||||||
<h4 id="postgresql">PostgreSQL</h4>
|
<h4 id="postgresql">PostgreSQL</h4>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
||||||
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
||||||
_ <span class="hljs-string">"github.com/lib/pq"</span>
|
_ <span class="hljs-string">"github.com/jinzhu/gorm/dialects/postgres"</span>
|
||||||
)
|
)
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> main() {
|
<span class="hljs-keyword">func</span> main() {
|
||||||
db, err := gorm.Open(<span class="hljs-string">"postgres"</span>, <span class="hljs-string">"user=gorm dbname=gorm sslmode=disable"</span>)
|
db, err := gorm.Open(<span class="hljs-string">"postgres"</span>, <span class="hljs-string">"user=gorm dbname=gorm sslmode=disable"</span>)
|
||||||
}
|
}
|
||||||
@ -642,33 +682,20 @@
|
|||||||
<h4 id="sqlite3">Sqlite3</h4>
|
<h4 id="sqlite3">Sqlite3</h4>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
|
||||||
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
||||||
_ <span class="hljs-string">"github.com/mattn/go-sqlite3"</span>
|
_ <span class="hljs-string">"github.com/jinzhu/gorm/dialects/sqlite"</span>
|
||||||
)
|
)
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> main() {
|
<span class="hljs-keyword">func</span> main() {
|
||||||
db, err := gorm.Open(<span class="hljs-string">"sqlite3"</span>, <span class="hljs-string">"/tmp/gorm.db"</span>)
|
db, err := gorm.Open(<span class="hljs-string">"sqlite3"</span>, <span class="hljs-string">"/tmp/gorm.db"</span>)
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h4 id="write-dialect-for-unsupported-databases">Write Dialect for unsupported databases</h4>
|
<h4 id="write-dialect-for-unsupported-databases">Write Dialect for unsupported databases</h4>
|
||||||
<p>GORM officially support above databases, for unsupported databaes, you could write a dialect for that.</p>
|
<p>GORM officially support above databases, but you could write a dialect for those unsupported databaes,</p>
|
||||||
<p>Refer: <a href="https://github.com/jinzhu/gorm/blob/master/dialect.go" target="_blank">https://github.com/jinzhu/gorm/blob/master/dialect.go</a></p>
|
<p>Refer: <a href="https://github.com/jinzhu/gorm/blob/master/dialect.go" target="_blank">https://github.com/jinzhu/gorm/blob/master/dialect.go</a></p>
|
||||||
<h2 id="generic-database-object-sqldb">Generic database object *sql.DB</h2>
|
|
||||||
<p><a href="http://golang.org/pkg/database/sql/#DB" target="_blank">*sql.DB</a></p>
|
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Get generic database object *sql.DB to use its functions</span>
|
|
||||||
db.DB()
|
|
||||||
|
|
||||||
<span class="hljs-comment">// Connection Pool</span>
|
|
||||||
db.DB().SetMaxIdleConns(<span class="hljs-number">10</span>)
|
|
||||||
db.DB().SetMaxOpenConns(<span class="hljs-number">100</span>)
|
|
||||||
|
|
||||||
<span class="hljs-comment">// Ping</span>
|
|
||||||
db.DB().Ping()
|
|
||||||
</code></pre>
|
|
||||||
<h2 id="migration">Migration</h2>
|
<h2 id="migration">Migration</h2>
|
||||||
<!-- toc -->
|
|
||||||
<h3 id="auto-migration">Auto Migration</h3>
|
<h3 id="auto-migration">Auto Migration</h3>
|
||||||
<p>Automatically migrate your schema, to keep your schema update to date</p>
|
<p>Automatically migrate your schema, to keep your schema update to date</p>
|
||||||
<p><strong>WARNING</strong> AutoMigrate will ONLY create tables, columns and indexes if doesn't exist,
|
<p><strong>WARNING</strong> AutoMigrate will ONLY create tables, missing columns and missing indexes, <strong>WON'T</strong> change existing column's type or delete unused columns to protect your data</p>
|
||||||
WON'T change existing column's type or delete unused columns to protect your data</p>
|
|
||||||
<pre><code class="lang-go">db.AutoMigrate(&User{})
|
<pre><code class="lang-go">db.AutoMigrate(&User{})
|
||||||
|
|
||||||
db.AutoMigrate(&User{}, &Product{}, &Order{})
|
db.AutoMigrate(&User{}, &Product{}, &Order{})
|
||||||
@ -677,28 +704,37 @@ db.AutoMigrate(&User{}, &Product{}, &Order{})
|
|||||||
db.Set(<span class="hljs-string">"gorm:table_options"</span>, <span class="hljs-string">"ENGINE=InnoDB"</span>).AutoMigrate(&User{})
|
db.Set(<span class="hljs-string">"gorm:table_options"</span>, <span class="hljs-string">"ENGINE=InnoDB"</span>).AutoMigrate(&User{})
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="has-table">Has Table</h3>
|
<h3 id="has-table">Has Table</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Check if model `User`'s table has been created or not</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Check model `User`'s table exists or not</span>
|
||||||
db.HasTable(&User{})
|
db.HasTable(&User{})
|
||||||
|
|
||||||
<span class="hljs-comment">// Check table `users` exists or not</span>
|
<span class="hljs-comment">// Check table `users` exists or not</span>
|
||||||
db.HasTable(<span class="hljs-string">"users"</span>)
|
db.HasTable(<span class="hljs-string">"users"</span>)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="create-table">Create Table</h3>
|
<h3 id="create-table">Create Table</h3>
|
||||||
<pre><code class="lang-go">db.CreateTable(&User{})
|
<pre><code class="lang-go"><span class="hljs-comment">// Create table for model `User`</span>
|
||||||
|
db.CreateTable(&User{})
|
||||||
|
|
||||||
db.Set(<span class="hljs-string">"gorm:table_options"</span>, <span class="hljs-string">"ENGINE=InnoDB"</span>).CreateTable(&User{})
|
|
||||||
<span class="hljs-comment">// will append "ENGINE=InnoDB" to the SQL statement when creating table `users`</span>
|
<span class="hljs-comment">// will append "ENGINE=InnoDB" to the SQL statement when creating table `users`</span>
|
||||||
|
db.Set(<span class="hljs-string">"gorm:table_options"</span>, <span class="hljs-string">"ENGINE=InnoDB"</span>).CreateTable(&User{})
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="drop-table">Drop table</h3>
|
<h3 id="drop-table">Drop table</h3>
|
||||||
<pre><code class="lang-go">db.DropTable(&User{})
|
<pre><code class="lang-go"><span class="hljs-comment">// Drop model `User`'s table</span>
|
||||||
|
db.DropTable(&User{})
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Drop table `users</span>
|
||||||
|
db.DropTable(<span class="hljs-string">"users"</span>)
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Drop model's `User`'s table and table `products`</span>
|
||||||
|
db.DropTableIfExists(&User{}, <span class="hljs-string">"products"</span>)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="modifycolumn">ModifyColumn</h3>
|
<h3 id="modifycolumn">ModifyColumn</h3>
|
||||||
<p>Change column's type</p>
|
<p>Modify column's type to given value</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// change column description's data type to `text` for model `User`'s table</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// change column description's data type to `text` for model `User`</span>
|
||||||
db.Model(&User{}).ModifyColumn(<span class="hljs-string">"description"</span>, <span class="hljs-string">"text"</span>)
|
db.Model(&User{}).ModifyColumn(<span class="hljs-string">"description"</span>, <span class="hljs-string">"text"</span>)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="dropcolumn">DropColumn</h3>
|
<h3 id="dropcolumn">DropColumn</h3>
|
||||||
<pre><code class="lang-go">db.Model(&User{}).DropColumn(<span class="hljs-string">"description"</span>)
|
<pre><code class="lang-go"><span class="hljs-comment">// Drop column description from model `User`</span>
|
||||||
|
db.Model(&User{}).DropColumn(<span class="hljs-string">"description"</span>)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="add-foreign-key">Add Foreign Key</h3>
|
<h3 id="add-foreign-key">Add Foreign Key</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Add foreign key</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Add foreign key</span>
|
||||||
@ -709,16 +745,16 @@ db.Model(&User{}).ModifyColumn(<span class="hljs-string">"description&q
|
|||||||
db.Model(&User{}).AddForeignKey(<span class="hljs-string">"city_id"</span>, <span class="hljs-string">"cities(id)"</span>, <span class="hljs-string">"RESTRICT"</span>, <span class="hljs-string">"RESTRICT"</span>)
|
db.Model(&User{}).AddForeignKey(<span class="hljs-string">"city_id"</span>, <span class="hljs-string">"cities(id)"</span>, <span class="hljs-string">"RESTRICT"</span>, <span class="hljs-string">"RESTRICT"</span>)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="indexes">Indexes</h3>
|
<h3 id="indexes">Indexes</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Add index</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Add index for columns `name` with given name `idx_user_name`</span>
|
||||||
db.Model(&User{}).AddIndex(<span class="hljs-string">"idx_user_name"</span>, <span class="hljs-string">"name"</span>)
|
db.Model(&User{}).AddIndex(<span class="hljs-string">"idx_user_name"</span>, <span class="hljs-string">"name"</span>)
|
||||||
|
|
||||||
<span class="hljs-comment">// Multiple column index</span>
|
<span class="hljs-comment">// Add index for columns `name`, `age` with given name `idx_user_name_age`</span>
|
||||||
db.Model(&User{}).AddIndex(<span class="hljs-string">"idx_user_name_age"</span>, <span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>)
|
db.Model(&User{}).AddIndex(<span class="hljs-string">"idx_user_name_age"</span>, <span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>)
|
||||||
|
|
||||||
<span class="hljs-comment">// Add unique index</span>
|
<span class="hljs-comment">// Add unique index</span>
|
||||||
db.Model(&User{}).AddUniqueIndex(<span class="hljs-string">"idx_user_name"</span>, <span class="hljs-string">"name"</span>)
|
db.Model(&User{}).AddUniqueIndex(<span class="hljs-string">"idx_user_name"</span>, <span class="hljs-string">"name"</span>)
|
||||||
|
|
||||||
<span class="hljs-comment">// Multiple column unique index</span>
|
<span class="hljs-comment">// Add unique index for multiple columns</span>
|
||||||
db.Model(&User{}).AddUniqueIndex(<span class="hljs-string">"idx_user_name_age"</span>, <span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>)
|
db.Model(&User{}).AddUniqueIndex(<span class="hljs-string">"idx_user_name_age"</span>, <span class="hljs-string">"name"</span>, <span class="hljs-string">"age"</span>)
|
||||||
|
|
||||||
<span class="hljs-comment">// Remove index</span>
|
<span class="hljs-comment">// Remove index</span>
|
||||||
|
117
development.html
117
development.html
@ -5,8 +5,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="The most notable component of Gorm isgorm.DB, which hold database connection. It could be initialized like this:">
|
<meta name="description" content="Gorm use chainable API, *gorm.DB is the bridge of chains, for each chain API, it will create a new relation.">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +69,8 @@
|
|||||||
data-level="6"
|
data-level="6"
|
||||||
data-chapter-title="Development"
|
data-chapter-title="Development"
|
||||||
data-filepath="development.md"
|
data-filepath="development.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -178,12 +178,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -481,12 +481,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -496,11 +496,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -532,11 +547,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -585,7 +615,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Development</a>
|
<a href="." >Development</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -595,34 +625,38 @@
|
|||||||
<div class="page-inner">
|
<div class="page-inner">
|
||||||
<section class="normal markdown-section">
|
<section class="normal markdown-section">
|
||||||
|
|
||||||
<h1 id="gorm-development">Gorm Development</h1>
|
<h1 id="development">Development</h1>
|
||||||
<!-- toc -->
|
<!-- toc -->
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#architecture">Architecture</a></li>
|
<li><a href="#architecture">Architecture</a></li>
|
||||||
<li><a href="#callbacks">Callbacks</a><ul>
|
<li><a href="#write-plugins">Write Plugins</a><ul>
|
||||||
<li><a href="#register-a-new-callback">Register a new callback</a></li>
|
<li><a href="#register-a-new-callback">Register a new callback</a></li>
|
||||||
<li><a href="#delete-an-existing-callback">Delete an existing callback</a></li>
|
<li><a href="#delete-an-existing-callback">Delete an existing callback</a></li>
|
||||||
<li><a href="#replace-an-existing-callback">Replace an existing callback</a></li>
|
<li><a href="#replace-an-existing-callback">Replace an existing callback</a></li>
|
||||||
<li><a href="#register-callback-orders">Register callback orders</a></li>
|
<li><a href="#register-callback-orders">Register callback orders</a></li>
|
||||||
<li><a href="#callback-api">Callback API</a></li>
|
<li><a href="#pre-defined-callbacks">Pre-Defined Callbacks</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- toc stop -->
|
<!-- toc stop -->
|
||||||
<h2 id="architecture">Architecture</h2>
|
<h2 id="architecture">Architecture</h2>
|
||||||
<p>The most notable component of Gorm is<code>gorm.DB</code>, which hold database connection. It could be initialized like this:</p>
|
<p>Gorm use chainable API, <code>*gorm.DB</code> is the bridge of chains, for each chain API, it will create a new relation.</p>
|
||||||
<pre><code>db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
|
<pre><code class="lang-go">db, err := gorm.Open(<span class="hljs-string">"postgres"</span>, <span class="hljs-string">"user=gorm dbname=gorm sslmode=disable"</span>)
|
||||||
</code></pre><p>Gorm has chainable API, <code>gorm.DB</code> is the bridge of chains, it save related information and pass it to the next chain.</p>
|
|
||||||
<p>Lets use below code to explain how it works:</p>
|
|
||||||
<pre><code>db.Where("name = ?", "jinzhu").Find(&users)
|
|
||||||
|
|
||||||
// equivalent code
|
<span class="hljs-comment">// create a new relation</span>
|
||||||
newdb := db.Where("name =?", "jinzhu")
|
db = db.Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"jinzhu"</span>)
|
||||||
newdb.Find(&user)
|
|
||||||
</code></pre><p><code>newdb</code> is <code>db</code>'s clone, in addition, it contains search conditions from the <code>Where</code> method.
|
<span class="hljs-comment">// create another new relation</span>
|
||||||
<code>Find</code> is a query method, it creates a <code>Scope</code> instance, and pass it as argument to query callbacks.</p>
|
db = db.Where(<span class="hljs-string">"age = ?"</span>, <span class="hljs-number">20</span>)
|
||||||
<p>There are four kinds of callbacks corresponds to sql's CURD: create callbacks, update callbacks, query callbacks, delete callbacks.</p>
|
</code></pre>
|
||||||
<h2 id="callbacks">Callbacks</h2>
|
<p>When we start to perform any operations, GROM will create a new <code>*gorm.Scope</code> instance based on current <code>*gorm.DB</code></p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-comment">// perform a querying operation</span>
|
||||||
|
db.First(&user)
|
||||||
|
</code></pre>
|
||||||
|
<p>And based on current operation's type, it will call registered <code>creating</code>, <code>updating</code>, <code>querying</code>, <code>deleting</code> or <code>row_querying</code> callbacks to run the operation.</p>
|
||||||
|
<p>For above example, will call <code>querying</code> callbacks, refer <a href="callbacks.html#querying-an-object">Querying Callbacks</a></p>
|
||||||
|
<h2 id="write-plugins">Write Plugins</h2>
|
||||||
|
<p>GORM itself is powered by <code>Callbacks</code>, so you could fully customize GORM as you want</p>
|
||||||
<h3 id="register-a-new-callback">Register a new callback</h3>
|
<h3 id="register-a-new-callback">Register a new callback</h3>
|
||||||
<pre><code>func updateCreated(scope *Scope) {
|
<pre><code>func updateCreated(scope *Scope) {
|
||||||
if scope.HasColumn("Created") {
|
if scope.HasColumn("Created") {
|
||||||
@ -645,13 +679,28 @@ db.Callback().Query().After("gorm:query").Register("my_plugin:aft
|
|||||||
db.Callback().Delete().After("gorm:delete").Register("my_plugin:after_delete", afterDelete)
|
db.Callback().Delete().After("gorm:delete").Register("my_plugin:after_delete", afterDelete)
|
||||||
db.Callback().Update().Before("gorm:update").Register("my_plugin:before_update", beforeUpdate)
|
db.Callback().Update().Before("gorm:update").Register("my_plugin:before_update", beforeUpdate)
|
||||||
db.Callback().Create().Before("gorm:create").After("gorm:before_create").Register("my_plugin:before_create", beforeCreate)
|
db.Callback().Create().Before("gorm:create").After("gorm:before_create").Register("my_plugin:before_create", beforeCreate)
|
||||||
</code></pre><h3 id="callback-api">Callback API</h3>
|
</code></pre><h3 id="predefined-callbacks">Pre-Defined Callbacks</h3>
|
||||||
<p>Gorm is powered by callbacks, so you could refer below links to learn how to write callbacks</p>
|
<p>GORM has defiend callbacks to perform its CRUD operations, check them out before start write your plugins</p>
|
||||||
<p><a href="https://github.com/jinzhu/gorm/blob/master/callback_create.go" target="_blank">Create callbacks</a></p>
|
<ul>
|
||||||
<p><a href="https://github.com/jinzhu/gorm/blob/master/callback_update.go" target="_blank">Update callbacks</a></p>
|
<li><p><a href="https://github.com/jinzhu/gorm/blob/master/callback_create.go" target="_blank">Create callbacks</a></p>
|
||||||
<p><a href="https://github.com/jinzhu/gorm/blob/master/callback_query.go" target="_blank">Query callbacks</a></p>
|
</li>
|
||||||
<p><a href="https://github.com/jinzhu/gorm/blob/master/callback_delete.go" target="_blank">Delete callbacks</a></p>
|
<li><p><a href="https://github.com/jinzhu/gorm/blob/master/callback_update.go" target="_blank">Update callbacks</a></p>
|
||||||
<p>View <a href="https://github.com/jinzhu/gorm/blob/master/scope.go" target="_blank">https://github.com/jinzhu/gorm/blob/master/scope.go</a> for all available API</p>
|
</li>
|
||||||
|
<li><p><a href="https://github.com/jinzhu/gorm/blob/master/callback_query.go" target="_blank">Query callbacks</a></p>
|
||||||
|
</li>
|
||||||
|
<li><p><a href="https://github.com/jinzhu/gorm/blob/master/callback_delete.go" target="_blank">Delete callbacks</a></p>
|
||||||
|
</li>
|
||||||
|
<li><p>Row Query callbacks</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>Row Query callbacks will be called when run <code>Row</code> or <code>Rows</code>, by default there is no registered callbacks for it, you could register a new one like:</p>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">func</span> updateTableName(scope *gorm.Scope) {
|
||||||
|
scope.Search.Table(scope.TableName() + <span class="hljs-string">"_draft"</span>) <span class="hljs-comment">// append `_draft` to table name</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Callback().RowQuery().Register(<span class="hljs-string">"publish:update_table_name"</span>, updateTableName)
|
||||||
|
</code></pre>
|
||||||
|
<p>View <a href="https://godoc.org/github.com/jinzhu/gorm" target="_blank">https://godoc.org/github.com/jinzhu/gorm</a> to view all available API</p>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@ -667,7 +716,7 @@ db.Callback().Create().Before("gorm:create").After("gorm:before_c
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<a href="development.html" class="navigation navigation-next " aria-label="Next page: Write Plugins">
|
<a href="development.html" class="navigation navigation-next " aria-label="Next page: Architecture">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
|
|||||||
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
||||||
//// user -> User{Name: "non_existing", Age: 20}
|
//// user -> User{Name: "non_existing", Age: 20}
|
||||||
|
|
||||||
db.Where(User{Name: "noexisting_user"}).Attrs("age", 20).FirstOrInit(&user)
|
db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)
|
||||||
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
||||||
//// user -> User{Name: "non_existing", Age: 20}
|
//// user -> User{Name: "non_existing", Age: 20}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- Markdown parser is now using CommonMark
|
- Markdown parser is now using CommonMark
|
||||||
- Root folder for the book can be specified in a `.gitbook` file
|
- Root folder for the book can be specified in a `.gitbook` file
|
||||||
- Multi-lingual books share assets folder
|
- Multi-lingual books share assets folder
|
||||||
- YAML front matter is parsed and page's description can be specified in it
|
- YAML front matter is parsed and can extend page's properties
|
||||||
- Fix `uk` translation
|
- Fix `uk` translation
|
||||||
|
|
||||||
## 2.6.7
|
## 2.6.7
|
||||||
|
24
gitbook/book.js
Normal file
24
gitbook/book.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
var pkg = require('./package.json');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Documentation for GitBook is stored under "docs"
|
||||||
|
root: './docs',
|
||||||
|
title: 'GitBook Documentation',
|
||||||
|
|
||||||
|
// Enforce use of GitBook v3
|
||||||
|
gitbook: pkg.version,
|
||||||
|
|
||||||
|
// Use the "official" theme
|
||||||
|
plugins: ['theme-official', 'sitemap'],
|
||||||
|
theme: 'official',
|
||||||
|
|
||||||
|
variables: {
|
||||||
|
version: pkg.version
|
||||||
|
},
|
||||||
|
|
||||||
|
pluginsConfig: {
|
||||||
|
sitemap: {
|
||||||
|
hostname: 'https://docs.gitbook.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -1,10 +1,12 @@
|
|||||||
# GitBook Format Documentation
|
# GitBook Format Documentation
|
||||||
|
|
||||||
> This documentation is for GitBook version **{{ book.version }}**
|
This document aims to be a comprehensive guide to GitBook. It contains the full documentation for version **{{ book.version }}**. Help for GitBook.com specific questions can be found at [help.gitbook.com](https://help.gitbook.com).
|
||||||
|
|
||||||
GitBook is a command line tool (and Node.js library) for building beautiful books using GitHub/Git and Markdown (or AsciiDoc). Here is an example: [Learn Javascript](https://www.gitbook.com/book/GitBookIO/javascript). This documentation has been generated using GitBook.
|
### What is GitBook?
|
||||||
|
|
||||||
GitBook can output your content as a website ([customizable](themes.md) and [extensibles](plugins.md)) or as an ebook (PDF, ePub or Mobi).
|
GitBook is a command line tool (and Node.js library) for building beautiful books using GitHub/Git and Markdown (or AsciiDoc). . This documentation has been generated using GitBook.
|
||||||
|
|
||||||
|
GitBook can output your content as a website ([customizable](themes/README.md) and [extensibles](plugins/README.md)) or as an ebook (PDF, ePub or Mobi).
|
||||||
|
|
||||||
[GitBook.com](https://www.gitbook.com) is the online platform to create and host books built using the GitBook format. It offers hosting, collaboration features and an [easy-to-use editor](https://www.gitbook.com/editor).
|
[GitBook.com](https://www.gitbook.com) is the online platform to create and host books built using the GitBook format. It offers hosting, collaboration features and an [easy-to-use editor](https://www.gitbook.com/editor).
|
||||||
|
|
||||||
@ -12,9 +14,11 @@ GitBook can output your content as a website ([customizable](themes.md) and [ext
|
|||||||
|
|
||||||
We're always happy to help out with your books or any other questions you might have. You can ask a question on the following contact form at [gitbook.com/contact](https://www.gitbook.com/contact) or signal an issue on [GitHub](https://github.com/GitbookIO/gitbook).
|
We're always happy to help out with your books or any other questions you might have. You can ask a question on the following contact form at [gitbook.com/contact](https://www.gitbook.com/contact) or signal an issue on [GitHub](https://github.com/GitbookIO/gitbook).
|
||||||
|
|
||||||
|
Check out the [GitBook Community Slack Channel](https://slack.gitbook.com), Stay updated by following [@GitBookIO](https://twitter.com/GitBookIO) on Twitter or [GitBook](https://www.facebook.com/gitbookcom) on Facebook.
|
||||||
|
|
||||||
### FAQ
|
### FAQ
|
||||||
|
|
||||||
There are questions that are asked quite often, [check this out before creating an issue](faq.md).
|
Some questions are frequently asked. If you have a problem you should [check this out](faq.md) first.
|
||||||
|
|
||||||
### Contribute to this documentation
|
### Contribute to this documentation
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ Just like for markdown, GitBook is using some special files to extract structure
|
|||||||
|
|
||||||
### README.adoc
|
### README.adoc
|
||||||
|
|
||||||
This is the main entry of your book: the introduction. This file is **non optional**.
|
This is the main entry of your book: the introduction. This file is **required**.
|
||||||
|
|
||||||
### SUMMARY.adoc
|
### SUMMARY.adoc
|
||||||
|
|
||||||
This file defines the list of chapters and subchapters. Just like [for markdown](./pages.md), the `SUMMARY.adoc`'s format is simply a list of links, the name of the link is used as the chapter's name, and the target is a path to that chapter's file.
|
This file defines the list of chapters and subchapters. Just like in Markdown, the `SUMMARY.adoc`'s format is simply a list of links, the name of the link is used as the chapter's name, and the target is a path to that chapter's file.
|
||||||
|
|
||||||
Subchapters are defined simply by adding a nested list to a parent chapter.
|
Subchapters are defined simply by adding a nested list to a parent chapter.
|
||||||
|
|
||||||
@ -51,10 +51,15 @@ This file is used to define terms. [See the glossary section](./lexicon.md).
|
|||||||
= Glossary
|
= Glossary
|
||||||
|
|
||||||
== Magic
|
== Magic
|
||||||
Sufficiently advanced technology, beyond the understanding of the observer producing a sense of wonder.
|
|
||||||
|
Sufficiently advanced technology, beyond the understanding of the
|
||||||
|
observer producing a sense of wonder.
|
||||||
|
|
||||||
== PHP
|
== PHP
|
||||||
An atrocious language, invented for the sole purpose of inflicting pain and suffering amongst the programming wizards of this world.
|
|
||||||
```
|
A popular web programming language, used by many large websites such
|
||||||
|
as Facebook. Rasmus Lerdorf originally created PHP in 1994 to power
|
||||||
|
his personal homepage (PHP originally stood for "Personal Home Page"
|
||||||
|
but now stands for "PHP: Hypertext Preprocessor"). ```
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,20 +1,36 @@
|
|||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
GitBook allows you to customize your book using a flexible configuration. These options are specified in a `book.json` file.
|
GitBook allows you to customize your book using a flexible configuration. These options are specified in a `book.json` file. For authors unfamiliar with the JSON syntax, you can validate the syntax using tools such as [JSONlint](http://jsonlint.com).
|
||||||
|
|
||||||
### Configuration Settings
|
### General Settings
|
||||||
|
|
||||||
| Variable | Description |
|
| Variable | Description |
|
||||||
| -------- | ----------- |
|
| -------- | ----------- |
|
||||||
|
| `root` | Path to the root folder containing all the book's files, except `book.json`|
|
||||||
| `title` | Title of your book, default value is extracted from the README. On GitBook.com this field is pre-filled. |
|
| `title` | Title of your book, default value is extracted from the README. On GitBook.com this field is pre-filled. |
|
||||||
| `description` | Description of your book, default value is extracted from the README. On GitBook.com this field is pre-filled. |
|
| `description` | Description of your book, default value is extracted from the README. On GitBook.com this field is pre-filled. |
|
||||||
| `author` | Name of the author. On GitBook.com this field is pre-filled. |
|
| `author` | Name of the author. On GitBook.com this field is pre-filled. |
|
||||||
| `isbn` | ISBN of the book |
|
| `isbn` | ISBN of the book |
|
||||||
| `language` | ISO code of the book's language, default value is `en` |
|
| `language` | [ISO code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) of the book's language, default value is `en` |
|
||||||
| `direction` | `rtl` or `ltr`, default value depends on the value of `language` |
|
| `direction` | Text's direction. Can be `rtl` or `ltr`, the default value depends on the value of `language` |
|
||||||
| `gitbook` | [SemVer](http://semver.org) condition to validate which GitBook version should be used |
|
| `gitbook` | Version of GitBook that should be used. Uses the [SemVer](http://semver.org) specification and accepts conditions like `">= 3.0.0"` |
|
||||||
| `plugins` | List of plugins to load, See [the plugins section](plugins.md) for more details |
|
|
||||||
| `pluginsConfig` |Configuration for plugins, See [the plugins section](plugins.md) for more details |
|
### Plugins
|
||||||
|
|
||||||
|
Plugins and their configurations are specified in the `book.json`. See [the plugins section](plugins/README.md) for more details.
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `plugins` | List of plugins to load |
|
||||||
|
| `pluginsConfig` |Configuration for plugins |
|
||||||
|
|
||||||
|
### Theme
|
||||||
|
|
||||||
|
Since version 3.0.0, GitBook can use themes. See [the theming section](themes/README.md) for more details.
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `theme` | The theme to use for the book |
|
||||||
|
|
||||||
### PDF Options
|
### PDF Options
|
||||||
|
|
||||||
@ -30,8 +46,3 @@ PDF Output can be customized using a set of options in the `book.json`:
|
|||||||
| `pdf.margin.bottom` | Bottom margin (default is `56`) |
|
| `pdf.margin.bottom` | Bottom margin (default is `56`) |
|
||||||
| `pdf.margin.right` | Right margin (default is `62`) |
|
| `pdf.margin.right` | Right margin (default is `62`) |
|
||||||
| `pdf.margin.left` | Left margin (default is `62`) |
|
| `pdf.margin.left` | Left margin (default is `62`) |
|
||||||
|
|
||||||
### Plugins
|
|
||||||
|
|
||||||
Plugins and their configurations are specified in the `book.json`. See [the plugins section](plugins.md) for more details.
|
|
||||||
|
|
||||||
|
21
gitbook/docs/cover.md
Normal file
21
gitbook/docs/cover.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Cover
|
||||||
|
|
||||||
|
Covers are used for all the ebook formats, and to make books more elegant on GitBook.com.
|
||||||
|
|
||||||
|
To provide a cover, place a **cover.jpg** file at the root directory of your book. Adding a **cover_small.jpg** will specify a smaller version of the cover. The cover should be a **JPEG** file.
|
||||||
|
|
||||||
|
### Best Sizes
|
||||||
|
|
||||||
|
| | Big | Small |
|
||||||
|
|:-------------------:|:-----------:|:-----------------:|
|
||||||
|
| **File** | `cover.jpg` | `cover_small.jpg` |
|
||||||
|
| **Size(in pixels)** | 1800x2360 | 200x262 |
|
||||||
|
|
||||||
|
### Guidelines
|
||||||
|
|
||||||
|
A good cover respects the following guidelines:
|
||||||
|
|
||||||
|
* No border
|
||||||
|
* Clearly visible book title
|
||||||
|
* Any important text should be visible in the small version
|
||||||
|
|
@ -4,7 +4,7 @@ description: Real world examples of content published using GitBook.
|
|||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
More than 50,000 books have benn published on [GitBook.com](https://www.gitbook.com/explore).
|
More than 50,000 books have been published on [GitBook.com](https://www.gitbook.com/explore).
|
||||||
|
|
||||||
### Books
|
### Books
|
||||||
|
|
||||||
@ -17,11 +17,11 @@ More than 50,000 books have benn published on [GitBook.com](https://www.gitbook.
|
|||||||
|
|
||||||
### Research Papers
|
### Research Papers
|
||||||
|
|
||||||
- [TowCenter Collection](https://www.gitbook.com/@towcenter) by [Columbia Journalism School]()
|
- [TowCenter Collection](https://www.gitbook.com/@towcenter) by [Columbia Journalism School](http://www.journalism.columbia.edu/)
|
||||||
- [Block Relaxation Algorithms in Statistics](https://www.gitbook.com/@jandeleeuw) by Jan de Leeuw
|
- [Block Relaxation Algorithms in Statistics](https://www.gitbook.com/@jandeleeuw) by Jan de Leeuw
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
- [DuckDuckHack Documentation](http://docs.duckduckhack.com) by DuckDuckGo
|
- [DuckDuckHack Documentation](http://docs.duckduckhack.com) by [DuckDuckGo](https://duckduckgo.com/about)
|
||||||
- This documentation
|
- This documentation
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ Any text editor should work! But we advise using the [GitBook Editor](https://ww
|
|||||||
|
|
||||||
#### Should I use an `.html` or `.md` extensions in my links?
|
#### Should I use an `.html` or `.md` extensions in my links?
|
||||||
|
|
||||||
You should always use `.md` extensions for your relative links, GitBook will automatically replace these links by the right value when the pointing file is referenced in the Table of Contents.
|
You should always use paths and the `.md` extensions when linking to your files, GitBook will automatically replace these paths by the appropriate link when the pointing file is referenced in the Table of Contents.
|
||||||
|
|
||||||
#### Can I create a GitBook in a sub-directory of my repository?
|
#### Can I create a GitBook in a sub-directory of my repository?
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ GitBook supports math equations and TeX thanks to plugins. There are currently 2
|
|||||||
|
|
||||||
#### Can I customize/theme the output?
|
#### Can I customize/theme the output?
|
||||||
|
|
||||||
Yes, both the website and ebook outputs can be customized using [themes](themes.md).
|
Yes, both the website and ebook outputs can be customized using [themes](themes/README.md).
|
||||||
|
|
||||||
#### Can I add interactive content (videos, etc)?
|
#### Can I add interactive content (videos, etc)?
|
||||||
|
|
||||||
GitBook is very [extensible](plugins.md). You can use [existing plugins](https://plugins.gitbook.com) or create your own!
|
GitBook is very [extensible](plugins/README.md). You can use [existing plugins](https://plugins.gitbook.com) or create your own!
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
GitBook supports building books written in multiple languages. Each language should be a sub-directory following the normal GitBook format, and a file named `LANGS.md` should be present at the root of the repository with the following format:
|
GitBook supports building books written in multiple languages. Each language should be a sub-directory following the normal GitBook format, and a file named `LANGS.md` should be present at the root of the repository with the following format:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
|
# Languages
|
||||||
|
|
||||||
* [English](en/)
|
* [English](en/)
|
||||||
* [French](fr/)
|
* [French](fr/)
|
||||||
* [Español](es/)
|
* [Español](es/)
|
||||||
@ -12,4 +14,4 @@ GitBook supports building books written in multiple languages. Each language sho
|
|||||||
|
|
||||||
When a language book (ex: `en`) has a `book.json`, its configuration will extend the main configuration.
|
When a language book (ex: `en`) has a `book.json`, its configuration will extend the main configuration.
|
||||||
|
|
||||||
The only exception is plugins, plugins are specify globally relative to the book, and language specific plugins can not be specified.
|
The only exception is plugins, plugins are specified globally, and language specific plugins cannot be specified.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Glossary
|
# Glossary
|
||||||
|
|
||||||
Allows you to specify terms and their respective definitions to be displayed as annotations. Based on those terms, gitbook will automatically build an index and highlight those terms in pages.
|
Allows you to specify terms and their respective definitions to be displayed as annotations. Based on those terms, GitBook will automatically build an index and highlight those terms in pages.
|
||||||
|
|
||||||
The `GLOSSARY.md` format is very simple :
|
The `GLOSSARY.md` format is very simple :
|
||||||
|
|
||||||
@ -9,5 +9,6 @@ The `GLOSSARY.md` format is very simple :
|
|||||||
Definition for this term
|
Definition for this term
|
||||||
|
|
||||||
# Another term
|
# Another term
|
||||||
With it's definition, this can contain bold text and all other kinds of inline markup ...
|
With it's definition, this can contain bold text
|
||||||
|
and all other kinds of inline markup ...
|
||||||
```
|
```
|
@ -1,12 +1,12 @@
|
|||||||
# Pages and Summary
|
# Pages and Summary
|
||||||
|
|
||||||
GitBook uses a `SUMMARY.md` file to define the structure of chapters and subchapters of the book. The `SUMMARY.md` file is used to generate the book's table of contents.
|
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
|
|
||||||
The `SUMMARY.md`'s format is simply a list of links, the title of the link is used as the chapter's title, and the target is a path to that chapter's file.
|
GitBook uses a `SUMMARY.md` file to define the structure of chapters and subchapters of the book. The `SUMMARY.md` file is used to generate the book's table of contents.
|
||||||
|
|
||||||
Subchapters are defined simply by adding a nested list to a parent chapter.
|
The format of `SUMMARY.md` is just a list of links. The link's title is used as the chapter's title, and the link's target is a path to that chapter's file.
|
||||||
|
|
||||||
|
Adding a nested list to a parent chapter will create subchapters.
|
||||||
|
|
||||||
##### Simple example
|
##### Simple example
|
||||||
|
|
||||||
@ -21,23 +21,50 @@ Subchapters are defined simply by adding a nested list to a parent chapter.
|
|||||||
* [Better tools for authors](part2/better_tools.md)
|
* [Better tools for authors](part2/better_tools.md)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Each chapter has a dedicated page (`part#/README.md`) and is split into subchapters.
|
||||||
|
|
||||||
##### Example with subchapters split into parts
|
##### Example with subchapters split into parts
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
### Part 1
|
### Part I
|
||||||
|
|
||||||
* [Writing is nice](part1/writing.md)
|
* [Writing is nice](part1/writing.md)
|
||||||
* [GitBook is nice](part1/gitbook.md)
|
* [GitBook is nice](part1/gitbook.md)
|
||||||
|
|
||||||
### Part 2
|
### Part II
|
||||||
|
|
||||||
* [We love feedback](part2/feedback_please.md)
|
* [We love feedback](part2/feedback_please.md)
|
||||||
* [Better tools for authors](part2/better_tools.md)
|
* [Better tools for authors](part2/better_tools.md)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Front Matter
|
Here, parts are just groups of chapters and do not have dedicated pages, but will show in the navigation for example.
|
||||||
|
|
||||||
|
### Pages
|
||||||
|
|
||||||
|
#### Markdown syntax
|
||||||
|
|
||||||
|
Most of the files for GitBook use the Markdown syntax by default. GitBook infers your pages's structure from it. The syntax used is similar to the [GitHub Flavored Markdown syntax](https://guides.github.com/features/mastering-markdown/). One can also opt for the [AsciiDoc syntax](asciidoc.md).
|
||||||
|
|
||||||
|
##### Example of a chapter file
|
||||||
|
|
||||||
|
``` markdown
|
||||||
|
# Title of the chapter
|
||||||
|
|
||||||
|
This is a great introduction.
|
||||||
|
|
||||||
|
## Section 1
|
||||||
|
|
||||||
|
Markdown will dictates _most_ of your **book's structure**
|
||||||
|
|
||||||
|
## Section 2
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Front Matter
|
||||||
|
|
||||||
Pages can contain an optional front matter. It can be used to define the page's description. The front matter must be the first thing in the file and must take the form of valid YAML set between triple-dashed lines. Here is a basic example:
|
Pages can contain an optional front matter. It can be used to define the page's description. The front matter must be the first thing in the file and must take the form of valid YAML set between triple-dashed lines. Here is a basic example:
|
||||||
|
|
||||||
@ -47,4 +74,7 @@ description: This is a short description of my page
|
|||||||
---
|
---
|
||||||
|
|
||||||
# The content of my page
|
# The content of my page
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The front matter can define variables of your own, they will be added to the [page variable](templating/variables.md) so you can use them in your templating.
|
||||||
|
28
gitbook/docs/plugins/README.md
Normal file
28
gitbook/docs/plugins/README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Plugins
|
||||||
|
|
||||||
|
Plugins are the best way to extend GitBook functionalities (ebook and website). There exist plugins to do a lot of things: bring math formulas display support, track visits using Google Analytic, etc.
|
||||||
|
|
||||||
|
### How to find plugins?
|
||||||
|
|
||||||
|
Plugins can be easily searched on [plugins.gitbook.com](https://plugins.gitbook.com).
|
||||||
|
|
||||||
|
|
||||||
|
### How to install a plugin?
|
||||||
|
|
||||||
|
Once you find a plugin that you want to install, you need to add it to your `book.json`:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"plugins": ["myPlugin", "anotherPlugin"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also specify a specific version using: `"myPlugin@0.3.1"`. By default GitBook will resolve the latest version of the plugin compatbile with the current GitBook version.
|
||||||
|
|
||||||
|
### GitBook.com
|
||||||
|
|
||||||
|
Plugins are automatically installed on [GitBook.com](https://www.gitbook.com). Locally, run `gitbook install` to install and prepare all plugins for your books.
|
||||||
|
|
||||||
|
### Configuring plugins
|
||||||
|
|
||||||
|
Plugins specific configurations are stored in `pluginsConfig`. You have to refer to the documentation of the plugin itself for details about the available options.
|
63
gitbook/docs/plugins/create.md
Normal file
63
gitbook/docs/plugins/create.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Create and publish a plugin
|
||||||
|
|
||||||
|
A GitBook plugin is a node package published on NPM that follow a defined convention.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
#### package.json
|
||||||
|
|
||||||
|
The `package.json` is a manifest format for describing **Node.js modules**. GitBook plugins are built on top of Node modules. It declares dependencies, version, ownership, and other information required to run a plugin in GitBook. This document describes the schema in detail.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"name": "gitbook-plugin-mytest",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "This is my first GitBook plugin",
|
||||||
|
"engines": {
|
||||||
|
"gitbook": ">1.x.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can learn more about `package.json` from the [NPM documentation](https://docs.npmjs.com/files/package.json).
|
||||||
|
|
||||||
|
The **package name** must begin with `gitbook-plugin-` and the **package engines** should contains `gitbook`.
|
||||||
|
|
||||||
|
#### index.js
|
||||||
|
|
||||||
|
The `index.js` is main entry point of your plugin runtime:
|
||||||
|
|
||||||
|
```js
|
||||||
|
module.exports = {
|
||||||
|
// Map of hooks
|
||||||
|
hooks: {},
|
||||||
|
|
||||||
|
// Map of new blocks
|
||||||
|
blocks: {},
|
||||||
|
|
||||||
|
// Map of new filters
|
||||||
|
filters: {}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Publish your plugin
|
||||||
|
|
||||||
|
GitBook plugins can be published on [NPM](https://www.npmjs.com).
|
||||||
|
|
||||||
|
To publish a new plugin, you need to create an account on [npmjs.com](https://www.npmjs.com) then publish it from the command line:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm publish
|
||||||
|
```
|
||||||
|
|
||||||
|
## Private plugins
|
||||||
|
|
||||||
|
Private plugins can be hosted on GitHub and included using `git` urls:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"myplugin@git+https://github.com/MyCompany/mygitbookplugin.git#1.0.0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
0
gitbook/docs/plugins/hooks.md
Normal file
0
gitbook/docs/plugins/hooks.md
Normal file
22
gitbook/docs/plugins/testing.md
Normal file
22
gitbook/docs/plugins/testing.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Testing your plugin
|
||||||
|
|
||||||
|
### Testing your plugin locally
|
||||||
|
|
||||||
|
Testing your plugin on your book before plushing it is possible using [npm link](https://docs.npmjs.com/cli/link).
|
||||||
|
|
||||||
|
In the plugin's folder, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm link
|
||||||
|
```
|
||||||
|
|
||||||
|
The nin your book's folder:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm link gitbook-plugin-<plugin's name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unit testing on Travis
|
||||||
|
|
||||||
|
[gitbook-tester](https://github.com/todvora/gitbook-tester) makes it easy to write **Node.js/Mocha** unit tests for your plugins. Using [Travis.org](https://travis.org), tests can be run on each commits/tags.
|
||||||
|
|
@ -4,7 +4,7 @@ Getting GitBook installed and ready-to-go should only take a few minutes.
|
|||||||
|
|
||||||
### GitBook.com
|
### GitBook.com
|
||||||
|
|
||||||
[GitBook.com](https://www.gitbook.com) is an easy to use solution to write, publish and host books. It's best and easier solution for publishing your content and collaborate on it.
|
[GitBook.com](https://www.gitbook.com) is an easy to use solution to write, publish and host books. It is the easiest solution for publishing your content and collaborating on it.
|
||||||
|
|
||||||
It integrates well with the [GitBook Editor](https://www.gitbook.com/editor).
|
It integrates well with the [GitBook Editor](https://www.gitbook.com/editor).
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ It integrates well with the [GitBook Editor](https://www.gitbook.com/editor).
|
|||||||
|
|
||||||
##### Requirements
|
##### Requirements
|
||||||
|
|
||||||
Installing GitBook is easy and straight-forward, but there are a few requirements you’ll need to make sure your system has before you start.
|
Installing GitBook is easy and straightforward. Your system just needs to meet these two requirements:
|
||||||
|
|
||||||
* NodeJS (v4.0.0 and above are adviced)
|
* NodeJS (v4.0.0 and above are adviced)
|
||||||
* Windows, Linux, Unix, or Mac OS X
|
* Windows, Linux, Unix, or Mac OS X
|
||||||
@ -25,7 +25,7 @@ The best way to install GitBook is via **NPM**. At the terminal prompt, simply r
|
|||||||
$ npm install gitbook-cli -g
|
$ npm install gitbook-cli -g
|
||||||
```
|
```
|
||||||
|
|
||||||
`gitbook-cli` is an utility to install and use multiple versions of GitBook on the same system. It will automatically install the required version to build a book.
|
`gitbook-cli` is an utility to install and use multiple versions of GitBook on the same system. It will automatically install the required version of GitBook to build a book.
|
||||||
|
|
||||||
##### Create a book
|
##### Create a book
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ Preview and serve your book using:
|
|||||||
$ gitbook serve
|
$ gitbook serve
|
||||||
```
|
```
|
||||||
|
|
||||||
or build the static website using:
|
Or build the static website using:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ gitbook build
|
$ gitbook build
|
||||||
@ -51,7 +51,7 @@ $ gitbook build
|
|||||||
|
|
||||||
##### Install pre-releases
|
##### Install pre-releases
|
||||||
|
|
||||||
`gitbook-cli` makes it easy to install and test other versions of GitBook with your book:
|
`gitbook-cli` makes it easy to download and install other versions of GitBook to test with your book:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ gitbook fetch beta
|
$ gitbook fetch beta
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
# Directory structure
|
# Directory Structure
|
||||||
|
|
||||||
GitBook uses a very simple and obvious directory sttructure:
|
GitBook uses a simple directory structure. All Markdown/Asciidoc files listed in the [SUMMARY](pages.md) will be transformed as HTML. Multi-Lingual books have a slightly [different structure](languages.md).
|
||||||
|
|
||||||
|
A basic GitBook usually looks something like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
@ -21,19 +23,19 @@ An overview of what each of these does:
|
|||||||
| -------- | ----------- |
|
| -------- | ----------- |
|
||||||
| `book.json` | Stores [configuration](config.md) data (__optional__) |
|
| `book.json` | Stores [configuration](config.md) data (__optional__) |
|
||||||
| `README.md` | Preface / Introduction for your book (**required**) |
|
| `README.md` | Preface / Introduction for your book (**required**) |
|
||||||
| `SUMMARY.md` | Table of Contents |
|
| `SUMMARY.md` | Table of Contents (See [Pages](pages.md)) (__optional__) |
|
||||||
|
| `GLOSSARY.md` | Lexicon / List of terms to annotate (See [Glossary](lexicon.md)) (__optional__) |
|
||||||
|
|
||||||
### Static files and Images
|
### Static files and Images
|
||||||
|
|
||||||
A static file is a file that is not listed in the `SUMMARY.md`. All static files, not [ignored](#ignore), are copied to the output.
|
A static file is a file that is not listed in the `SUMMARY.md`. All static files, unless [ignored](#ignore), are copied to the output.
|
||||||
|
|
||||||
### Ignoring files & folders {#ignore}
|
### Ignoring files & folders {#ignore}
|
||||||
|
|
||||||
GitBook will read the `.gitignore`, `.bookignore` and `.ignore` files to get a list of files and folders to skip.
|
GitBook will read the `.gitignore`, `.bookignore` and `.ignore` files to get a list of files and folders to skip.
|
||||||
The format inside those files, follows the same convention as `.gitignore`:
|
The format inside those files, follows the same convention as `.gitignore`:
|
||||||
|
|
||||||
```markdown
|
```
|
||||||
# This is a comment
|
# This is a comment
|
||||||
|
|
||||||
# Ignore the file test.md
|
# Ignore the file test.md
|
||||||
@ -43,20 +45,22 @@ test.md
|
|||||||
bin/*
|
bin/*
|
||||||
```
|
```
|
||||||
|
|
||||||
### Project documentation / Sub-directory {#subdirectory}
|
### Project integration with subdirectory {#subdirectory}
|
||||||
|
|
||||||
For project documentaiton, it sometimes better to use a diretcory (like `docs/`) to store the prject's documentation. You can use a `.gitbook` file to indicate to GitBook in which folder the book is stored:
|
For software projects, you can use a subdirectory (like `docs/`) to store the book for the project's documentation. You can configure the [`root` option](config.md) to indicate the folder where GitBook can find the book's files:
|
||||||
|
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
├── .gitbook
|
├── book.json
|
||||||
└── docs/
|
└── docs/
|
||||||
├── README.md
|
├── README.md
|
||||||
└── SUMMARY.md
|
└── SUMMARY.md
|
||||||
```
|
```
|
||||||
|
|
||||||
With `.gitbook` containing:
|
With `book.json` containing:
|
||||||
|
|
||||||
```
|
```
|
||||||
./docs/
|
{
|
||||||
|
"root": "./docs"
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
89
gitbook/docs/templating/README.md
Normal file
89
gitbook/docs/templating/README.md
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Templating
|
||||||
|
|
||||||
|
GitBook uses the [Nunjucks templating language](https://mozilla.github.io/nunjucks/) to process pages and theme's templates.
|
||||||
|
|
||||||
|
The Nunjucks syntax is very similar to **Jinja2** or **Liquid**. Its syntax uses surrounding braces `{ }` to mark content that needs to be processed.
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
|
||||||
|
A variable looks up a value from the template context. If you wanted to simply display a variable, you would use the `{{ variable }}` syntax. For example :
|
||||||
|
|
||||||
|
```twig
|
||||||
|
My name is {{ name }}, nice to meet you
|
||||||
|
```
|
||||||
|
|
||||||
|
This looks up username from the context and displays it. Variable names can have dots in them which lookup properties, just like JavaScript. You can also use the square bracket syntax.
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{{ foo.bar }}
|
||||||
|
{{ foo["bar"] }}
|
||||||
|
```
|
||||||
|
|
||||||
|
If a value is undefined, nothing is displayed. The following all output nothing if foo is undefined: `{{ foo }}`, `{{ foo.bar }}`, `{{ foo.bar.baz }}`.
|
||||||
|
|
||||||
|
GitBook provides a set of [predefined variables](variables.md) from the context.
|
||||||
|
|
||||||
|
### Filters
|
||||||
|
|
||||||
|
Filters are essentially functions that can be applied to variables. They are called with a pipe operator (`|`) and can take arguments.
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{{ foo | title }}
|
||||||
|
{{ foo | join(",") }}
|
||||||
|
{{ foo | replace("foo", "bar") | capitalize }}
|
||||||
|
```
|
||||||
|
|
||||||
|
The third example shows how you can chain filters. It would display "Bar", by first replacing "foo" with "bar" and then capitalizing it.
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
|
||||||
|
##### if
|
||||||
|
|
||||||
|
`if` tests a condition and lets you selectively display content. It behaves exactly as JavaScript's `if` behaves.
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{% if variable %}
|
||||||
|
It is true
|
||||||
|
{% endif %}
|
||||||
|
```
|
||||||
|
|
||||||
|
If variable is defined and evaluates to true, "It is true" will be displayed. Otherwise, nothing will be.
|
||||||
|
|
||||||
|
You can specify alternate conditions with `elif` and `else`:
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{% if hungry %}
|
||||||
|
I am hungry
|
||||||
|
{% elif tired %}
|
||||||
|
I am tired
|
||||||
|
{% else %}
|
||||||
|
I am good!
|
||||||
|
{% endif %}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### for
|
||||||
|
|
||||||
|
`for` iterates over arrays and dictionaries.
|
||||||
|
|
||||||
|
```twig
|
||||||
|
# Chapters about GitBook
|
||||||
|
|
||||||
|
{% for article in glossary.terms['gitbook'].articles %}
|
||||||
|
* [{{ article.title }}]({{ article.path }})
|
||||||
|
{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### set
|
||||||
|
|
||||||
|
`set` lets you create/modify a variable.
|
||||||
|
|
||||||
|
```twig
|
||||||
|
{% set softwareVersion = "1.0.0" %}
|
||||||
|
|
||||||
|
Current version is {{ softwareVersion }}.
|
||||||
|
[Download it](website.com/download/{{ softwareVersion }})
|
||||||
|
```
|
||||||
|
|
||||||
|
##### include and block
|
||||||
|
|
||||||
|
Inclusion and inheritance is detailled in the [Content References](conrefs.md) section.
|
55
gitbook/docs/templating/conrefs.md
Normal file
55
gitbook/docs/templating/conrefs.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Content References
|
||||||
|
|
||||||
|
Content referencing (conref) is a convenient mechanism to reuse content from other files or books.
|
||||||
|
|
||||||
|
### Importing local files
|
||||||
|
|
||||||
|
Importing an other file's content is easy using the `include` tag:
|
||||||
|
|
||||||
|
```
|
||||||
|
{% include "./test.md" %}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Importing file from another book
|
||||||
|
|
||||||
|
GitBook can also resolve the include path by using git:
|
||||||
|
|
||||||
|
```
|
||||||
|
{% include "git+https://github.com/GitbookIO/documentation.git/README.md#0.0.1" %}
|
||||||
|
```
|
||||||
|
|
||||||
|
The format of git url is:
|
||||||
|
|
||||||
|
```
|
||||||
|
git+https://user@hostname/owner/project.git/file#commit-ish
|
||||||
|
```
|
||||||
|
|
||||||
|
The real git url part should finish with `.git`, the filename to import is extracted after the `.git` till the fragment of the url.
|
||||||
|
|
||||||
|
The `commit-ish` can be any tag, sha, or branch which can be supplied as an argument to `git checkout`. The default is `master`.
|
||||||
|
|
||||||
|
### Inheritance
|
||||||
|
|
||||||
|
Template inheritance is a way to make it easy to reuse templates. When writing a template, you can define "blocks" that child templates can override. The inheritance chain can be as long as you like.
|
||||||
|
|
||||||
|
`block` defines a section on the template and identifies it with a name. Base templates can specify blocks and child templates can override them with new content.
|
||||||
|
|
||||||
|
```
|
||||||
|
{% extends "./mypage.md" %}
|
||||||
|
|
||||||
|
{% block pageContent %}
|
||||||
|
# This is my page content
|
||||||
|
{% endblock %}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the file `mypage.md`, you should specify the blocks that can be extended:
|
||||||
|
|
||||||
|
```
|
||||||
|
{% block pageContent %}
|
||||||
|
This is the default content
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
{% import "./LICENSE" %}
|
||||||
|
```
|
64
gitbook/docs/templating/variables.md
Normal file
64
gitbook/docs/templating/variables.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Variables
|
||||||
|
|
||||||
|
The following is a reference of the available data during book's parsing and theme generation.
|
||||||
|
|
||||||
|
### Global Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `book` | Book-wide information + configuration settings from `book.json`. See below for details. |
|
||||||
|
| `gitbook` | GitBook specific information |
|
||||||
|
| `page` | Current page specific information |
|
||||||
|
| `file` | File associated with the current page specific information |
|
||||||
|
| `summary` | Information about the table of contents |
|
||||||
|
| `languages` | List of languages for multi-lingual books |
|
||||||
|
| `config` | Dump of the `book.json` |
|
||||||
|
|
||||||
|
### Book Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `book.[CONFIGURATION_DATA]` | All the `variables` set via the `book.json` are available through the book variable. |
|
||||||
|
| `book.language` | Current language for a multilingual book |
|
||||||
|
|
||||||
|
### GitBook Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `gitbook.time` | The current time (when you run the `gitbook` command) . |
|
||||||
|
| `gitbook.version` | Version of GitBook used to generate the book |
|
||||||
|
|
||||||
|
### File Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `file.path` | The path to the raw page |
|
||||||
|
| `file.mtime` | Modified Time. Last time the file was modified |
|
||||||
|
| `file.type` | The name of the parser used to compile this file (ex: `markdown`, `asciidoc`, etc) |
|
||||||
|
|
||||||
|
#### Page Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `page.title` | Title of the page |
|
||||||
|
| `page.previous` | Previous page in the Table of Contents (can be `null`) |
|
||||||
|
| `page.next` | Next page in the Table of Contents (can be `null`) |
|
||||||
|
| `page.dir` | Text direction, based on configuration or detected from content (`rtl` or `ltr`) |
|
||||||
|
|
||||||
|
#### Table of Contents Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `summary.parts` | List of sections in the Table of Contents |
|
||||||
|
|
||||||
|
The whole table of contents (`SUMMARY.md`) can be accessed:
|
||||||
|
|
||||||
|
`summary.parts[0].articles[0].title` will return the title of the first article.
|
||||||
|
|
||||||
|
#### Multi-lingual book Variable
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `languages.list` | List of languages for this book |
|
||||||
|
|
||||||
|
Languages are defined by `{ id: 'en', title: 'English' }`.
|
26
gitbook/docs/themes/README.md
vendored
Normal file
26
gitbook/docs/themes/README.md
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Theming
|
||||||
|
|
||||||
|
Since version 3.0.0, GitBook can be easily themed. Books are using by default the [theme-default](https://github.com/GitbookIO/theme-default).
|
||||||
|
|
||||||
|
The theme to use is specified in the [book's configuration](config.md) using key `theme`.
|
||||||
|
|
||||||
|
> **Caution**: Custom theming can block some plugins from working correctly.
|
||||||
|
|
||||||
|
### Structure of a theme
|
||||||
|
|
||||||
|
A theme is a folder containing templates and assets. All the templates are optionnal, since theme are always extending the default theme.
|
||||||
|
|
||||||
|
| Folder | Description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `_layouts` | Main folder containing all the templates |
|
||||||
|
| `_layouts/website/page.html` | Template for a normal page |
|
||||||
|
| `_layouts/ebook/page.html` | Template for a normal page during ebook generation (PDF< ePub, Mobi) |
|
||||||
|
|
||||||
|
|
||||||
|
### Extend/Customize theme in a book
|
||||||
|
|
||||||
|
Authors can extend the templates of a theme directly from the book source (without creating an external theme). Templates will be resolved in the `_layouts` folder of the book first, then in
|
||||||
|
|
||||||
|
### Publish a theme
|
||||||
|
|
||||||
|
Themes are published as plugins ([see related docs](../plugins/README.md)) with a `theme-` prefix. For example the theme `awesome` will be loaded from the `theme-awesome` plugin, and then from the `gitbook-plugin-theme-awesome` NPM package.
|
@ -1,12 +1,10 @@
|
|||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var url = require('url');
|
|
||||||
|
|
||||||
var location = require('../utils/location');
|
var location = require('../utils/location');
|
||||||
var error = require('../utils/error');
|
var error = require('../utils/error');
|
||||||
var BackboneFile = require('./file');
|
var BackboneFile = require('./file');
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An article represent an entry in the Summary.
|
An article represent an entry in the Summary.
|
||||||
It's defined by a title, a reference, and children articles,
|
It's defined by a title, a reference, and children articles,
|
||||||
@ -33,13 +31,13 @@ function TOCArticle(def, parent) {
|
|||||||
|
|
||||||
// Path can be a relative path or an url, or nothing
|
// Path can be a relative path or an url, or nothing
|
||||||
this.ref = def.path;
|
this.ref = def.path;
|
||||||
if (this.ref) {
|
if (this.ref && !this.isExternal()) {
|
||||||
var parts = url.parse(this.ref);
|
var parts = this.ref.split('#');
|
||||||
|
this.path = (parts.length > 1? parts.slice(0, -1).join('#') : this.ref);
|
||||||
|
this.anchor = (parts.length > 1? '#' + _.last(parts) : null);
|
||||||
|
|
||||||
if (!this.isExternal()) {
|
// Normalize path to remove ('./', etc)
|
||||||
this.path = parts.pathname;
|
this.path = location.normalize(this.path);
|
||||||
this.anchor = parts.hash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.articles = _.map(def.articles || [], function(article) {
|
this.articles = _.map(def.articles || [], function(article) {
|
||||||
@ -264,6 +262,17 @@ Summary.prototype.find = function(filter) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Flatten the list of articles
|
||||||
|
Summary.prototype.flatten = function() {
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
this.walk(function(article) {
|
||||||
|
result.push(article);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// Return the first TOCArticle for a specific page (or path)
|
// Return the first TOCArticle for a specific page (or path)
|
||||||
Summary.prototype.getArticle = function(page) {
|
Summary.prototype.getArticle = function(page) {
|
||||||
if (!_.isString(page)) page = page.path;
|
if (!_.isString(page)) page = page.path;
|
||||||
|
@ -13,6 +13,7 @@ var error = require('./utils/error');
|
|||||||
var Promise = require('./utils/promise');
|
var Promise = require('./utils/promise');
|
||||||
var Logger = require('./utils/logger');
|
var Logger = require('./utils/logger');
|
||||||
var parsers = require('./parsers');
|
var parsers = require('./parsers');
|
||||||
|
var initBook = require('./init');
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -92,7 +93,27 @@ function Book(opts) {
|
|||||||
// List of page in the book
|
// List of page in the book
|
||||||
this.pages = {};
|
this.pages = {};
|
||||||
|
|
||||||
|
// Deprecation for templates
|
||||||
|
Object.defineProperty(this, 'options', {
|
||||||
|
get: function () {
|
||||||
|
this.log.warn.ln('"options" property is deprecated, use config.get(key) instead');
|
||||||
|
var cfg = this.config.dump();
|
||||||
|
error.deprecateField(cfg, 'book', (this.output? this.output.name : null), '"options.generator" property is deprecated, use "output.name" instead');
|
||||||
|
|
||||||
|
// options.generator
|
||||||
|
cfg.generator = this.output? this.output.name : null;
|
||||||
|
|
||||||
|
// options.output
|
||||||
|
cfg.output = this.output? this.output.root() : null;
|
||||||
|
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
_.bindAll(this);
|
_.bindAll(this);
|
||||||
|
|
||||||
|
// Loop for template filters/blocks
|
||||||
|
error.deprecateField(this, 'book', this, '"book" property is deprecated, use "this" directly instead');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return templating context for the book
|
// Return templating context for the book
|
||||||
@ -108,7 +129,16 @@ Book.prototype.getContext = function() {
|
|||||||
|
|
||||||
// Parse and prepare the configuration, fail if invalid
|
// Parse and prepare the configuration, fail if invalid
|
||||||
Book.prototype.prepareConfig = function() {
|
Book.prototype.prepareConfig = function() {
|
||||||
return this.config.load();
|
var that = this;
|
||||||
|
|
||||||
|
return this.config.load()
|
||||||
|
.then(function() {
|
||||||
|
var rootFolder = that.config.get('root');
|
||||||
|
if (!rootFolder) return;
|
||||||
|
|
||||||
|
that.originalRoot = that.root;
|
||||||
|
that.root = path.resolve(that.root, rootFolder);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolve a path in the book source
|
// Resolve a path in the book source
|
||||||
@ -329,29 +359,29 @@ Book.prototype.isInLanguageBook = function(filename) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Locate a book in a folder
|
// ----- DEPRECATED METHODS
|
||||||
// - Read the ".gitbook" is exists
|
|
||||||
// - Try the folder itself
|
|
||||||
// - Try a "docs" folder
|
|
||||||
Book.locate = function(fs, root) {
|
|
||||||
return fs.readAsString(path.join(root, '.gitbook'))
|
|
||||||
.then(function(content) {
|
|
||||||
return path.join(root, content);
|
|
||||||
}, function() {
|
|
||||||
// .gitbook doesn't exists, fall back to the root folder
|
|
||||||
return Promise(root);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Locate and setup a book
|
Book.prototype.contentLink = error.deprecateMethod(function(s) {
|
||||||
Book.setup = function(fs, root, opts) {
|
return this.output.toURL(s);
|
||||||
return Book.locate(fs, root)
|
}, '.contentLink() is deprecated, use ".output.toURL()" instead');
|
||||||
.then(function(_root) {
|
|
||||||
return new Book(_.extend(opts || {}, {
|
Book.prototype.contentPath = error.deprecateMethod(function(s) {
|
||||||
root: _root,
|
return this.output.toURL(s);
|
||||||
fs: fs
|
}, '.contentPath() is deprecated, use ".output.toURL()" instead');
|
||||||
}));
|
|
||||||
});
|
Book.prototype.isSubBook = error.deprecateMethod(function() {
|
||||||
|
return this.isLanguageBook();
|
||||||
|
}, '.isSubBook() is deprecated, use ".isLanguageBook()" instead');
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize a book
|
||||||
|
Book.init = function(fs, root, opts) {
|
||||||
|
var book = new Book(_.extend(opts || {}, {
|
||||||
|
root: root,
|
||||||
|
fs: fs
|
||||||
|
}));
|
||||||
|
|
||||||
|
return initBook(book);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,12 +42,13 @@ var FORMATS = {
|
|||||||
function bookCmd(fn) {
|
function bookCmd(fn) {
|
||||||
return function(args, kwargs) {
|
return function(args, kwargs) {
|
||||||
var input = path.resolve(args[0] || process.cwd());
|
var input = path.resolve(args[0] || process.cwd());
|
||||||
return Book.setup(nodeFS, input, {
|
var book = new Book({
|
||||||
|
fs: nodeFS,
|
||||||
|
root: input,
|
||||||
logLevel: kwargs.log
|
logLevel: kwargs.log
|
||||||
})
|
|
||||||
.then(function(book) {
|
|
||||||
return fn(book, args.slice(1), kwargs);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return fn(book, args.slice(1), kwargs);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ function ebookCmd(format) {
|
|||||||
return fs.tmpDir()
|
return fs.tmpDir()
|
||||||
.then(function(dir) {
|
.then(function(dir) {
|
||||||
var ext = '.'+format;
|
var ext = '.'+format;
|
||||||
var outputFile = path.resolve(process.cwd(), args[1] || ('book' + ext));
|
var outputFile = path.resolve(process.cwd(), args[0] || ('book' + ext));
|
||||||
var output = new EBookOutput(book, {
|
var output = new EBookOutput(book, {
|
||||||
root: dir,
|
root: dir,
|
||||||
format: format
|
format: format
|
||||||
|
@ -14,6 +14,17 @@ var watch = require('./watch');
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
commands: [
|
commands: [
|
||||||
|
{
|
||||||
|
name: 'init [book]',
|
||||||
|
description: 'setup and create files for chapters',
|
||||||
|
options: [
|
||||||
|
helper.options.log
|
||||||
|
],
|
||||||
|
exec: function(args) {
|
||||||
|
var input = path.resolve(args[0] || process.cwd());
|
||||||
|
return Book.init(helper.nodeFS, input);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'parse [book]',
|
name: 'parse [book]',
|
||||||
@ -119,26 +130,27 @@ module.exports = {
|
|||||||
|
|
||||||
// Generate the book
|
// Generate the book
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return Book.setup(helper.nodeFS, input, {
|
var book = new Book({
|
||||||
'logLevel': kwargs.log
|
fs: helper.nodeFS,
|
||||||
})
|
root: input,
|
||||||
.then(function(book) {
|
logLevel: kwargs.log
|
||||||
return book.parse()
|
});
|
||||||
.then(function() {
|
|
||||||
// Add livereload plugin
|
|
||||||
book.config.set('plugins',
|
|
||||||
book.config.get('plugins')
|
|
||||||
.concat([
|
|
||||||
{ name: 'livereload' }
|
|
||||||
])
|
|
||||||
);
|
|
||||||
|
|
||||||
var Out = helper.FORMATS[kwargs.format];
|
return book.parse()
|
||||||
var output = new Out(book);
|
.then(function() {
|
||||||
|
// Add livereload plugin
|
||||||
|
book.config.set('plugins',
|
||||||
|
book.config.get('plugins')
|
||||||
|
.concat([
|
||||||
|
{ name: 'livereload' }
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
return output.generate()
|
var Out = helper.FORMATS[kwargs.format];
|
||||||
.thenResolve(output);
|
var output = new Out(book);
|
||||||
});
|
|
||||||
|
return output.generate()
|
||||||
|
.thenResolve(output);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -64,8 +64,9 @@ Server.prototype.start = function(dir, port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send file
|
// Send file
|
||||||
send(req, url.parse(req.url).pathname)
|
send(req, url.parse(req.url).pathname, {
|
||||||
.root(dir)
|
root: dir
|
||||||
|
})
|
||||||
.on('error', error)
|
.on('error', error)
|
||||||
.on('directory', redirect)
|
.on('directory', redirect)
|
||||||
.pipe(res);
|
.pipe(res);
|
||||||
|
@ -54,7 +54,7 @@ Config.prototype.load = function() {
|
|||||||
throw new Error('GitBook version doesn\'t satisfy version required by the book: '+that.options.gitbook);
|
throw new Error('GitBook version doesn\'t satisfy version required by the book: '+that.options.gitbook);
|
||||||
}
|
}
|
||||||
if (that.options.gitbook != '*' && !semver.satisfies(semver.inc(gitbook.version, 'patch'), that.options.gitbook)) {
|
if (that.options.gitbook != '*' && !semver.satisfies(semver.inc(gitbook.version, 'patch'), that.options.gitbook)) {
|
||||||
that.log.warn.ln('gitbook version specified in your book.json might be too strict for future patches, \''+(_.first(gitbook.version.split('.'))+'.x.x')+'\' is more adequate');
|
that.log.warn.ln('gitbook version specified in your book.json might be too strict for future patches, \'>='+(_.first(gitbook.version.split('.'))+'.x.x')+'\' is more adequate');
|
||||||
}
|
}
|
||||||
|
|
||||||
that.options.plugins = plugins.toList(that.options.plugins);
|
that.options.plugins = plugins.toList(that.options.plugins);
|
||||||
|
@ -4,13 +4,13 @@ module.exports = {
|
|||||||
'title': 'GitBook Configuration',
|
'title': 'GitBook Configuration',
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'title': {
|
'root': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'title': 'Title of the book, default is extracted from README'
|
'title': 'Path fro the root folder containing the book\'s content'
|
||||||
},
|
},
|
||||||
'title': {
|
'title': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'title': 'Description of the book, default is extracted from README'
|
'title': 'Title of the book, default is extracted from README'
|
||||||
},
|
},
|
||||||
'isbn': {
|
'isbn': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
|
67
gitbook/lib/init.js
Normal file
67
gitbook/lib/init.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var fs = require('./utils/fs');
|
||||||
|
var Promise = require('./utils/promise');
|
||||||
|
|
||||||
|
// Initialize folder structure for a book
|
||||||
|
// Read SUMMARY to created the right chapter
|
||||||
|
function initBook(book) {
|
||||||
|
var extensionToUse = '.md';
|
||||||
|
|
||||||
|
book.log.info.ln('init book at', book.root);
|
||||||
|
return fs.mkdirp(book.root)
|
||||||
|
.then(function() {
|
||||||
|
return book.config.load();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
book.log.info.ln('detect structure from SUMMARY (if it exists)');
|
||||||
|
return book.summary.load();
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
var summary = book.summary.path || 'SUMMARY.md';
|
||||||
|
var articles = book.summary.flatten();
|
||||||
|
|
||||||
|
// Use extension of summary
|
||||||
|
extensionToUse = path.extname(summary);
|
||||||
|
|
||||||
|
// Readme doesn't have a path
|
||||||
|
if (!articles[0].path) {
|
||||||
|
articles[0].path = 'README' + extensionToUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary doesn't exists? create one
|
||||||
|
if (!book.summary.path) {
|
||||||
|
articles.push({
|
||||||
|
title: 'Summary',
|
||||||
|
path: 'SUMMARY'+extensionToUse
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create files that don't exist
|
||||||
|
return Promise.serie(articles, function(article) {
|
||||||
|
if (!article.path) return;
|
||||||
|
|
||||||
|
var absolutePath = book.resolve(article.path);
|
||||||
|
|
||||||
|
return fs.exists(absolutePath)
|
||||||
|
.then(function(exists) {
|
||||||
|
if(exists) {
|
||||||
|
book.log.info.ln('found', article.path);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
book.log.info.ln('create', article.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.mkdirp(path.dirname(absolutePath))
|
||||||
|
.then(function() {
|
||||||
|
return fs.writeFile(absolutePath, '# '+article.title+'\n\n');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
book.log.info.ln('initialization is finished');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = initBook;
|
@ -24,6 +24,7 @@ function Output(book, opts, parent) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.book = book;
|
this.book = book;
|
||||||
|
book.output = this;
|
||||||
this.log = this.book.log;
|
this.log = this.book.log;
|
||||||
|
|
||||||
// Create plugins manager
|
// Create plugins manager
|
||||||
@ -146,6 +147,7 @@ Output.prototype.prepare = function() {
|
|||||||
'.ignore',
|
'.ignore',
|
||||||
'.bookignore',
|
'.bookignore',
|
||||||
'node_modules',
|
'node_modules',
|
||||||
|
'_layouts',
|
||||||
|
|
||||||
// The configuration file should not be copied in the output
|
// The configuration file should not be copied in the output
|
||||||
this.book.config.path,
|
this.book.config.path,
|
||||||
@ -183,7 +185,7 @@ Output.prototype.onRelativeLink = function(currentPage, href) {
|
|||||||
href = currentPage.relative(href);
|
href = currentPage.relative(href);
|
||||||
|
|
||||||
// Replace .md by .html
|
// Replace .md by .html
|
||||||
href = this.outputUrl(href);
|
href = this.toURL(href);
|
||||||
}
|
}
|
||||||
|
|
||||||
return href;
|
return href;
|
||||||
@ -261,7 +263,7 @@ Output.prototype.outputPath = function(filename, ext) {
|
|||||||
|
|
||||||
// Filename for output
|
// Filename for output
|
||||||
// /test/index.html -> /test/
|
// /test/index.html -> /test/
|
||||||
Output.prototype.outputUrl = function(filename, ext) {
|
Output.prototype.toURL = function(filename, ext) {
|
||||||
var href = this.outputPath(filename, ext);
|
var href = this.outputPath(filename, ext);
|
||||||
|
|
||||||
if (path.basename(href) == 'index.html' && this.opts.directoryIndex) {
|
if (path.basename(href) == 'index.html' && this.opts.directoryIndex) {
|
||||||
|
@ -114,7 +114,7 @@ EbookOutput.prototype.locateCover = function() {
|
|||||||
|
|
||||||
// Cover doesn't exist and multilingual?
|
// Cover doesn't exist and multilingual?
|
||||||
if (!fs.existsSync(cover)) {
|
if (!fs.existsSync(cover)) {
|
||||||
if (this.parent) return this.parent.locateCover()
|
if (this.parent) return this.parent.locateCover();
|
||||||
else return undefined;
|
else return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ JSONOutput.prototype.onPage = function(page) {
|
|||||||
delete json.config;
|
delete json.config;
|
||||||
|
|
||||||
// Specify JSON output version
|
// Specify JSON output version
|
||||||
json.version = '2';
|
json.version = '3';
|
||||||
|
|
||||||
return that.writeFile(
|
return that.writeFile(
|
||||||
page.withExtension('.json'),
|
page.withExtension('.json'),
|
||||||
|
@ -117,7 +117,7 @@ WebsiteOutput.prototype.prepare = function() {
|
|||||||
|
|
||||||
// Transform a '.md' into a '.html' (README -> index)
|
// Transform a '.md' into a '.html' (README -> index)
|
||||||
that.env.addFilter('contentURL', function(s) {
|
that.env.addFilter('contentURL', function(s) {
|
||||||
return location.normalize(that.outputUrl(s));
|
return that.toURL(s);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Relase path to an asset
|
// Relase path to an asset
|
||||||
|
@ -23,12 +23,13 @@ function Page(book, filename) {
|
|||||||
this.book = book;
|
this.book = book;
|
||||||
this.log = this.book.log;
|
this.log = this.book.log;
|
||||||
|
|
||||||
|
// Map of attributes from YAML frontmatter
|
||||||
|
// Description is also extracted by default from content
|
||||||
|
this.attributes = {};
|
||||||
|
|
||||||
// Current content
|
// Current content
|
||||||
this.content = '';
|
this.content = '';
|
||||||
|
|
||||||
// Short description for the page
|
|
||||||
this.description = '';
|
|
||||||
|
|
||||||
// Relative path to the page
|
// Relative path to the page
|
||||||
this.path = location.normalize(filename);
|
this.path = location.normalize(filename);
|
||||||
|
|
||||||
@ -122,16 +123,15 @@ Page.prototype.getContext = function() {
|
|||||||
mtime: this.mtime,
|
mtime: this.mtime,
|
||||||
type: this.type
|
type: this.type
|
||||||
},
|
},
|
||||||
page: {
|
page: _.extend({}, this.attributes, {
|
||||||
title: article? article.title : null,
|
title: article? article.title : null,
|
||||||
description: this.description,
|
|
||||||
next: next? next.getContext() : null,
|
next: next? next.getContext() : null,
|
||||||
previous: prev? prev.getContext() : null,
|
previous: prev? prev.getContext() : null,
|
||||||
level: article? article.level : null,
|
level: article? article.level : null,
|
||||||
depth: article? article.depth : 0,
|
depth: article? article.depth : 0,
|
||||||
content: this.content,
|
content: this.content,
|
||||||
dir: dir
|
dir: dir
|
||||||
}
|
})
|
||||||
},
|
},
|
||||||
gitbook.getContext(),
|
gitbook.getContext(),
|
||||||
this.book.getContext(),
|
this.book.getContext(),
|
||||||
@ -165,8 +165,8 @@ Page.prototype.toHTML = function(output) {
|
|||||||
.then(function() {
|
.then(function() {
|
||||||
var parsed = fm(that.content);
|
var parsed = fm(that.content);
|
||||||
|
|
||||||
// Extend page with the fontmatter attribute
|
// Extract attributes
|
||||||
that.description = parsed.attributes.description || '';
|
that.attributes = parsed.attributes;
|
||||||
|
|
||||||
// Keep only the body
|
// Keep only the body
|
||||||
that.update(parsed.body);
|
that.update(parsed.body);
|
||||||
@ -223,8 +223,8 @@ Page.prototype.toHTML = function(output) {
|
|||||||
|
|
||||||
// Extract description from page's content if no frontmatter
|
// Extract description from page's content if no frontmatter
|
||||||
onDescription: function(description) {
|
onDescription: function(description) {
|
||||||
if (that.description) return;
|
if (that.attributes.description) return;
|
||||||
that.description = description;
|
that.attributes.description = description;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Convert glossary entries to annotations
|
// Convert glossary entries to annotations
|
||||||
|
@ -7,19 +7,7 @@ var error = require('../utils/error');
|
|||||||
*/
|
*/
|
||||||
function pluginCtx(plugin) {
|
function pluginCtx(plugin) {
|
||||||
var book = plugin.book;
|
var book = plugin.book;
|
||||||
var ctx = {
|
var ctx = book;
|
||||||
config: book.config,
|
|
||||||
log: plugin.log,
|
|
||||||
|
|
||||||
// Paths
|
|
||||||
resolve: book.resolve
|
|
||||||
};
|
|
||||||
|
|
||||||
// Deprecation
|
|
||||||
error.deprecateField(ctx, 'options', book.config.dump(), '"options" property is deprecated, use config.get(key) instead');
|
|
||||||
|
|
||||||
// Loop for template filters/blocks
|
|
||||||
error.deprecateField(ctx, 'book', ctx, '"book" property is deprecated, use "this" directly instead');
|
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,6 @@ BookPlugin.prototype._getResources = function(base) {
|
|||||||
.then(function() {
|
.then(function() {
|
||||||
if (that._resources[base]) return that._resources[base];
|
if (that._resources[base]) return that._resources[base];
|
||||||
|
|
||||||
base = base;
|
|
||||||
var book = that.content[base];
|
var book = that.content[base];
|
||||||
|
|
||||||
// Compatibility with version 1.x.x
|
// Compatibility with version 1.x.x
|
||||||
|
@ -87,7 +87,7 @@ function installPlugin(book, plugin, version) {
|
|||||||
throw new Error('Found no satisfactory version for plugin "' + plugin + '"');
|
throw new Error('Found no satisfactory version for plugin "' + plugin + '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
book.log.info.ln('install plugin' + plugin +'" from npm ('+npnName+') with version', version);
|
book.log.info.ln('install plugin "' + plugin +'" from npm ('+npnName+') with version', version);
|
||||||
return Promise.nfcall(npmi, {
|
return Promise.nfcall(npmi, {
|
||||||
'name': npnName,
|
'name': npnName,
|
||||||
'version': version,
|
'version': version,
|
||||||
|
@ -202,7 +202,7 @@ TemplateEngine.prototype.addBlock = function(name, block) {
|
|||||||
lastBlockArgs = parser.parseSignature(null, true);
|
lastBlockArgs = parser.parseSignature(null, true);
|
||||||
parser.advanceAfterBlockEnd(lastBlockName);
|
parser.advanceAfterBlockEnd(lastBlockName);
|
||||||
}
|
}
|
||||||
} while (lastBlockName != block.end)
|
} while (lastBlockName != block.end);
|
||||||
|
|
||||||
parser.advanceAfterBlockEnd();
|
parser.advanceAfterBlockEnd();
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var childProcess = require('child_process');
|
var childProcess = require('child_process');
|
||||||
var spawn = require("spawn-cmd").spawn;
|
var spawn = require('spawn-cmd').spawn;
|
||||||
var Promise = require('./promise');
|
var Promise = require('./promise');
|
||||||
|
|
||||||
// Execute a command
|
// Execute a command
|
||||||
|
@ -27,7 +27,7 @@ function isAnchor(href) {
|
|||||||
|
|
||||||
// Normalize a path to be a link
|
// Normalize a path to be a link
|
||||||
function normalize(s) {
|
function normalize(s) {
|
||||||
return s.replace(/\\/g, '/');
|
return path.normalize(s).replace(/\\/g, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert relative to absolute path
|
// Convert relative to absolute path
|
||||||
|
@ -1,93 +1,92 @@
|
|||||||
{
|
{
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "3.0.0-pre.1",
|
"version": "3.0.0-pre.5",
|
||||||
"homepage": "https://www.gitbook.com",
|
"homepage": "https://www.gitbook.com",
|
||||||
"description": "Library and cmd utility to generate GitBooks",
|
"description": "Library and cmd utility to generate GitBooks",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"q": "1.0.1",
|
"bash-color": "0.0.3",
|
||||||
"lodash": "3.10.1",
|
"cheerio": "0.20.0",
|
||||||
"graceful-fs": "4.1.3",
|
"chokidar": "1.4.3",
|
||||||
"resolve": "0.6.3",
|
"cp": "0.2.0",
|
||||||
"mkdirp": "0.5.1",
|
"cpr": "1.0.0",
|
||||||
"error": "7.0.2",
|
"crc": "3.4.0",
|
||||||
"gitbook-markdown": "1.0.3",
|
"deprecated": "0.0.1",
|
||||||
"gitbook-asciidoc": "1.0.2",
|
"destroy": "1.0.4",
|
||||||
"gitbook-plugin-highlight": "1.0.3",
|
"direction": "0.1.5",
|
||||||
"gitbook-plugin-sharing": "1.0.1",
|
"dom-serializer": "0.1.0",
|
||||||
"gitbook-plugin-search": "1.1.0",
|
"error": "7.0.2",
|
||||||
"gitbook-plugin-fontsettings": "1.0.2",
|
"escape-string-regexp": "1.0.5",
|
||||||
"gitbook-plugin-theme-default": "1.0.0-pre.4",
|
"eslint": "^2.2.0",
|
||||||
"nunjucks": "2.3.0",
|
"front-matter": "2.0.6",
|
||||||
"nunjucks-autoescape": "1.0.0",
|
"gitbook-asciidoc": "1.0.2",
|
||||||
"nunjucks-filter": "1.0.0",
|
"gitbook-markdown": "1.0.3",
|
||||||
"semver": "5.0.1",
|
"gitbook-plugin-fontsettings": "1.0.2",
|
||||||
"npmi": "0.1.1",
|
"gitbook-plugin-highlight": "2.0.0",
|
||||||
"cheerio": "0.19.0",
|
"gitbook-plugin-livereload": "0.0.1",
|
||||||
"gitbook-plugin-livereload": "0.0.1",
|
"gitbook-plugin-search": "1.2.0",
|
||||||
"chokidar": "~1.0.5",
|
"gitbook-plugin-sharing": "1.0.1",
|
||||||
"send": "0.2.0",
|
"gitbook-plugin-theme-default": "1.0.0-pre.5",
|
||||||
"tiny-lr": "0.2.1",
|
"github-slugid": "1.0.0",
|
||||||
"tmp": "0.0.28",
|
"graceful-fs": "4.1.3",
|
||||||
"crc": "3.2.1",
|
"i18n-t": "1.0.0",
|
||||||
"bash-color": "0.0.3",
|
"ignore": "3.0.3",
|
||||||
"urijs": "1.17.0",
|
"json-schema-defaults": "0.1.1",
|
||||||
"request": "2.69.0",
|
"jsonschema": "1.1.0",
|
||||||
"npm": "2.4.1",
|
"juice": "1.10.0",
|
||||||
"dom-serializer": "0.1.0",
|
"lodash": "3.10.1",
|
||||||
"spawn-cmd": "0.0.2",
|
"merge-defaults": "0.2.1",
|
||||||
"escape-string-regexp": "1.0.3",
|
"mkdirp": "0.5.1",
|
||||||
"juice": "1.9.0",
|
"moment": "2.11.2",
|
||||||
"jsonschema": "1.1.0",
|
"npm": "3.7.5",
|
||||||
"json-schema-defaults": "0.1.1",
|
"npmi": "1.0.1",
|
||||||
"merge-defaults": "0.2.1",
|
"nunjucks": "2.3.0",
|
||||||
"github-slugid": "1.0.0",
|
"nunjucks-autoescape": "1.0.1",
|
||||||
"destroy": "1.0.4",
|
"q": "1.4.1",
|
||||||
"ignore": "2.2.19",
|
"request": "2.69.0",
|
||||||
"deprecated": "0.0.1",
|
"resolve": "0.6.3",
|
||||||
"rmdir": "1.2.0",
|
"rmdir": "1.2.0",
|
||||||
"cp": "0.2.0",
|
"semver": "5.1.0",
|
||||||
"cpr": "1.0.0",
|
"send": "0.13.1",
|
||||||
"direction": "0.1.5",
|
"spawn-cmd": "0.0.2",
|
||||||
"moment": "2.11.2",
|
"tiny-lr": "0.2.1",
|
||||||
"i18n-t": "1.0.0",
|
"tmp": "0.0.28",
|
||||||
"front-matter": "2.0.6",
|
"urijs": "1.17.1"
|
||||||
"spawn-cmd": "0.0.2"
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "2.2.0",
|
||||||
|
"mocha": "2.4.5",
|
||||||
|
"should": "8.2.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "node_modules/.bin/mocha --reporter spec --bail --timeout 15000 ./test/all.js",
|
||||||
|
"lint": "eslint ."
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/GitbookIO/gitbook.git"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"gitbook": "./bin/gitbook.js"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"git",
|
||||||
|
"book",
|
||||||
|
"gitbook"
|
||||||
|
],
|
||||||
|
"author": "FriendCode Inc. <contact@gitbook.com>",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/GitbookIO/gitbook/issues"
|
||||||
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Aaron O'Mullan",
|
||||||
|
"email": "aaron@gitbook.com"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
{
|
||||||
"eslint": "1.5.0",
|
"name": "Samy Pessé",
|
||||||
"mocha": "2.4.5",
|
"email": "samy@gitbook.com"
|
||||||
"should": "8.2.2"
|
}
|
||||||
},
|
]
|
||||||
"scripts": {
|
|
||||||
"test": "node_modules/.bin/mocha --reporter spec --bail --timeout 15000 ./test/all.js",
|
|
||||||
"lint": "eslint ."
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/GitbookIO/gitbook.git"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"gitbook": "./bin/gitbook.js"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"git",
|
|
||||||
"book",
|
|
||||||
"gitbook"
|
|
||||||
],
|
|
||||||
"author": "FriendCode Inc. <contact@gitbook.com>",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/GitbookIO/gitbook/issues"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Aaron O'Mullan",
|
|
||||||
"email": "aaron@gitbook.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Samy Pessé",
|
|
||||||
"email": "samy@gitbook.com"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
// Module API
|
||||||
|
require('./exports');
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
require('./location');
|
require('./location');
|
||||||
require('./paths');
|
require('./paths');
|
||||||
@ -25,3 +28,6 @@ require('./assets-inliner');
|
|||||||
require('./output-json');
|
require('./output-json');
|
||||||
require('./output-website');
|
require('./output-website');
|
||||||
require('./output-ebook');
|
require('./output-ebook');
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
require('./init');
|
||||||
|
@ -1,18 +1,31 @@
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var cheerio = require('cheerio');
|
var cheerio = require('cheerio');
|
||||||
var should = require('should');
|
var should = require('should');
|
||||||
|
|
||||||
// Assertions to test if an Output has generated a file
|
// Assertions to test if an Output has generated a file
|
||||||
should.Assertion.add('file', function(file, description) {
|
should.Assertion.add('file', function(file, description) {
|
||||||
|
var rootFolder;
|
||||||
|
if (_.isFunction(this.obj.root)) {
|
||||||
|
rootFolder = this.obj.root();
|
||||||
|
} else {
|
||||||
|
rootFolder = this.obj;
|
||||||
|
}
|
||||||
|
|
||||||
this.params = {
|
this.params = {
|
||||||
actual: this.obj.root(),
|
actual: rootFolder,
|
||||||
operator: 'have file ' + file,
|
operator: 'have file ' + file,
|
||||||
message: description
|
message: description
|
||||||
};
|
};
|
||||||
|
|
||||||
this.obj.should.have.property('resolve').which.is.a.Function;
|
if (_.isFunction(this.obj.resolve)) {
|
||||||
this.assert(fs.existsSync(this.obj.resolve(file)));
|
file = this.obj.resolve(file);
|
||||||
|
} else {
|
||||||
|
file = path.resolve(rootFolder, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.assert(fs.existsSync(file));
|
||||||
});
|
});
|
||||||
|
|
||||||
should.Assertion.add('html', function(rules, description) {
|
should.Assertion.add('html', function(rules, description) {
|
||||||
|
@ -46,7 +46,7 @@ describe('Configuration', function() {
|
|||||||
return mock.setupDefaultBook()
|
return mock.setupDefaultBook()
|
||||||
.then(function(_book) {
|
.then(function(_book) {
|
||||||
book = _book;
|
book = _book;
|
||||||
return book.config.load();
|
return book.prepareConfig();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ describe('Configuration', function() {
|
|||||||
})
|
})
|
||||||
.then(function(_book) {
|
.then(function(_book) {
|
||||||
book = _book;
|
book = _book;
|
||||||
return book.config.load();
|
return book.prepareConfig();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ describe('Configuration', function() {
|
|||||||
})
|
})
|
||||||
.then(function(_book) {
|
.then(function(_book) {
|
||||||
book = _book;
|
book = _book;
|
||||||
return book.config.load();
|
return book.prepareConfig();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
12
gitbook/test/exports.js
Normal file
12
gitbook/test/exports.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
var should = require('should');
|
||||||
|
var gitbook = require('../');
|
||||||
|
|
||||||
|
describe('Exports', function() {
|
||||||
|
it('should export the Book class', function() {
|
||||||
|
should(gitbook.Book).be.a.Function();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should export the list of commands', function() {
|
||||||
|
should(gitbook.commands).be.an.Array();
|
||||||
|
});
|
||||||
|
});
|
@ -7,7 +7,7 @@ describe('Glossary', function() {
|
|||||||
'GLOSSARY.md': ''
|
'GLOSSARY.md': ''
|
||||||
})
|
})
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
return book.config.load()
|
return book.prepareConfig()
|
||||||
|
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return book.glossary.load();
|
return book.glossary.load();
|
||||||
@ -27,7 +27,7 @@ describe('Glossary', function() {
|
|||||||
})
|
})
|
||||||
.then(function(_book) {
|
.then(function(_book) {
|
||||||
book = _book;
|
book = _book;
|
||||||
return book.config.load();
|
return book.prepareConfig();
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return book.glossary.load();
|
return book.glossary.load();
|
||||||
|
57
gitbook/test/init.js
Normal file
57
gitbook/test/init.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
var Book = require('../lib/book');
|
||||||
|
var mock = require('./mock');
|
||||||
|
|
||||||
|
describe('Init', function() {
|
||||||
|
|
||||||
|
it('should create file according to summary', function() {
|
||||||
|
return mock.setupFS({
|
||||||
|
'SUMMARY.md': '# Summary\n\n'
|
||||||
|
+ '* [Hello](hello.md)\n'
|
||||||
|
+ '* [Hello 2](hello 2.md)\n'
|
||||||
|
})
|
||||||
|
.then(function(rootFolder) {
|
||||||
|
return Book.init(mock.fs, rootFolder, {
|
||||||
|
log: function() {}
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
rootFolder.should.have.file('SUMMARY.md');
|
||||||
|
rootFolder.should.have.file('README.md');
|
||||||
|
rootFolder.should.have.file('hello.md');
|
||||||
|
rootFolder.should.have.file('hello 2.md');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create file subfolder', function() {
|
||||||
|
return mock.setupFS({
|
||||||
|
'SUMMARY.md': '# Summary\n\n'
|
||||||
|
+ '* [Hello](test/hello.md)\n'
|
||||||
|
+ '* [Hello 2](test/test2/world.md)\n'
|
||||||
|
})
|
||||||
|
.then(function(rootFolder) {
|
||||||
|
return Book.init(mock.fs, rootFolder, {
|
||||||
|
log: function() {}
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
rootFolder.should.have.file('README.md');
|
||||||
|
rootFolder.should.have.file('SUMMARY.md');
|
||||||
|
rootFolder.should.have.file('test/hello.md');
|
||||||
|
rootFolder.should.have.file('test/test2/world.md');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create SUMMARY if non-existant', function() {
|
||||||
|
return mock.setupFS({})
|
||||||
|
.then(function(rootFolder) {
|
||||||
|
return Book.init(mock.fs, rootFolder, {
|
||||||
|
log: function() {}
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
rootFolder.should.have.file('SUMMARY.md');
|
||||||
|
rootFolder.should.have.file('README.md');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -6,7 +6,7 @@ describe('Langs', function() {
|
|||||||
'LANGS.md': ''
|
'LANGS.md': ''
|
||||||
})
|
})
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
return book.config.load()
|
return book.prepareConfig()
|
||||||
|
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return book.langs.load();
|
return book.langs.load();
|
||||||
|
@ -1,27 +1,33 @@
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var should = require('should');
|
||||||
|
|
||||||
var Book = require('../').Book;
|
|
||||||
var mock = require('./mock');
|
var mock = require('./mock');
|
||||||
|
|
||||||
describe('Locate', function() {
|
describe('Locate', function() {
|
||||||
it('should use root folder if no .gitbook', function() {
|
it('should use root folder if no .gitbook', function() {
|
||||||
return mock.setupFS({
|
return mock.setupBook({
|
||||||
'README.md': '# Hello'
|
'README.md': '# Hello'
|
||||||
})
|
})
|
||||||
.then(function(root) {
|
.then(function(book) {
|
||||||
return Book.locate(mock.fs, root)
|
return book.prepareConfig()
|
||||||
.should.be.fulfilledWith(root);
|
.then(function() {
|
||||||
|
should(book.originalRoot).not.be.ok();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use resolve using .gitbook', function() {
|
it('should use resolve using book.js root property', function() {
|
||||||
return mock.setupFS({
|
return mock.setupBook({
|
||||||
'README.md': '# Hello',
|
'README.md': '# Hello',
|
||||||
'.gitbook': './docs'
|
'docs/README.md': '# Hello Book',
|
||||||
|
'book.json': { root: './docs' }
|
||||||
})
|
})
|
||||||
.then(function(root) {
|
.then(function(book) {
|
||||||
return Book.locate(mock.fs, root)
|
return book.prepareConfig()
|
||||||
.should.be.fulfilledWith(path.resolve(root, 'docs'));
|
.then(function() {
|
||||||
|
should(book.originalRoot).be.ok();
|
||||||
|
book.root.should.equal(path.resolve(book.originalRoot, 'docs'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ describe('Page', function() {
|
|||||||
'README.md': ' # Hello World\n\nThis is a description',
|
'README.md': ' # Hello World\n\nThis is a description',
|
||||||
'heading.md': '# Hello\n\n## World',
|
'heading.md': '# Hello\n\n## World',
|
||||||
'description.md': '# This is a title\n\nThis is the short description.\n\nNot this one.',
|
'description.md': '# This is a title\n\nThis is the short description.\n\nNot this one.',
|
||||||
'frontmatter.md': '---\ndescription: Hello World\n---\n\n# This is a title\n\nThis is not the description',
|
'frontmatter/description.md': '---\ndescription: Hello World\n---\n\n# This is a title\n\nThis is not the description',
|
||||||
|
'frontmatter/var.md': '---\ntest: Hello World\n---\n\n{{ page.test }}',
|
||||||
|
|
||||||
'links.md': '[link](hello.md) [link 2](variables/page/next.md) [readme](README.md)',
|
'links.md': '[link](hello.md) [link 2](variables/page/next.md) [readme](README.md)',
|
||||||
'links/relative.md': '[link](../hello.md) [link 2](/variables/page/next.md) [readme](../README.md)',
|
'links/relative.md': '[link](../hello.md) [link 2](/variables/page/next.md) [readme](../README.md)',
|
||||||
@ -131,23 +132,32 @@ describe('Page', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Description', function() {
|
describe('Description', function() {
|
||||||
it('should extratc page description from content', function() {
|
it('should extract page description from content', function() {
|
||||||
var page = book.addPage('description.md');
|
var page = book.addPage('description.md');
|
||||||
|
|
||||||
return page.toHTML(output)
|
return page.toHTML(output)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
page.description.should.equal('This is the short description.');
|
page.attributes.description.should.equal('This is the short description.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Font-Matter', function() {
|
describe('Font-Matter', function() {
|
||||||
it('should extratc page description from front matter', function() {
|
it('should extract page description from front matter', function() {
|
||||||
var page = book.addPage('frontmatter.md');
|
var page = book.addPage('frontmatter/description.md');
|
||||||
|
|
||||||
return page.toHTML(output)
|
return page.toHTML(output)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
page.description.should.equal('Hello World');
|
page.attributes.description.should.equal('Hello World');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extend page attributes with custom properties', function() {
|
||||||
|
var page = book.addPage('frontmatter/var.md');
|
||||||
|
|
||||||
|
return page.toHTML(output)
|
||||||
|
.then(function() {
|
||||||
|
page.content.should.equal('<p>Hello World</p>\n');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,23 @@ describe('Plugins', function() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
return book.config.load()
|
return book.prepareConfig()
|
||||||
|
.then(function() {
|
||||||
|
var plugins = new PluginsManager(book);
|
||||||
|
return plugins.install();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.should.be.fulfilledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly install dependencies from GitHub', function() {
|
||||||
|
return mock.setupBook({
|
||||||
|
'book.json': {
|
||||||
|
plugins: ['ga@git+https://github.com/GitbookIO/plugin-ga#master']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function(book) {
|
||||||
|
return book.prepareConfig()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var plugins = new PluginsManager(book);
|
var plugins = new PluginsManager(book);
|
||||||
return plugins.install();
|
return plugins.install();
|
||||||
@ -90,7 +106,7 @@ describe('Plugins', function() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function(book2) {
|
.then(function(book2) {
|
||||||
return book2.config.load()
|
return book2.prepareConfig()
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var plugin = new BookPlugin(book2, 'test-config');
|
var plugin = new BookPlugin(book2, 'test-config');
|
||||||
return plugin.load(PLUGINS_ROOT);
|
return plugin.load(PLUGINS_ROOT);
|
||||||
|
@ -6,7 +6,7 @@ describe('Readme', function() {
|
|||||||
'README.md': ''
|
'README.md': ''
|
||||||
})
|
})
|
||||||
.then(function(book) {
|
.then(function(book) {
|
||||||
return book.config.load()
|
return book.prepareConfig()
|
||||||
|
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return book.readme.load();
|
return book.readme.load();
|
||||||
|
@ -59,6 +59,34 @@ describe('Summary / Table of contents', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Unicode summary', function() {
|
||||||
|
var book;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
return mockSummary({
|
||||||
|
'SUMMARY.md': '# Summary\n\n'
|
||||||
|
+ '* [Hello](./hello world.md)\n'
|
||||||
|
+ '* [Spanish](./Descripción del problema.md)\n\n'
|
||||||
|
+ '* [Chinese](读了这本书.md)\n\n'
|
||||||
|
})
|
||||||
|
.then(function(_book) {
|
||||||
|
book = _book;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept article with spaces', function() {
|
||||||
|
should(book.summary.getArticle('hello world.md')).be.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept article with chinese filename', function() {
|
||||||
|
should(book.summary.getArticle('读了这本书.md')).be.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept article with accents', function() {
|
||||||
|
should(book.summary.getArticle('Descripción del problema.md')).be.ok();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Non-empty summary list', function() {
|
describe('Non-empty summary list', function() {
|
||||||
var book;
|
var book;
|
||||||
|
|
||||||
|
113
index.html
113
index.html
@ -6,7 +6,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="The fantastic ORM library for Golang, aims to be developer friendly.">
|
<meta name="description" content="The fantastic ORM library for Golang, aims to be developer friendly.">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -67,8 +67,8 @@
|
|||||||
data-level="0"
|
data-level="0"
|
||||||
data-chapter-title="Getting Started with GORM"
|
data-chapter-title="Getting Started with GORM"
|
||||||
data-filepath="README.md"
|
data-filepath="README.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -176,12 +176,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -479,12 +479,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -494,11 +494,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -530,11 +545,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -583,7 +613,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Getting Started with GORM</a>
|
<a href="." >Getting Started with GORM</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -595,53 +625,64 @@
|
|||||||
|
|
||||||
<h1 id="gorm">GORM</h1>
|
<h1 id="gorm">GORM</h1>
|
||||||
<p>The fantastic ORM library for Golang, aims to be developer friendly.</p>
|
<p>The fantastic ORM library for Golang, aims to be developer friendly.</p>
|
||||||
<p><a href="https://app.wercker.com/project/bykey/0cb7bb1039e21b74f8274941428e0921" target="_blank"><img src="https:/app.wercker.com/status/0cb7bb1039e21b74f8274941428e0921/s/master" alt="wercker status" title="wercker status"></a>
|
<p><a href="https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank"><img src="https:/badges.gitter.im/Join%20Chat.svg" alt="Join the chat at https://gitter.im/jinzhu/gorm"></a>
|
||||||
<a href="https://godoc.org/github.com/jinzhu/gorm" target="_blank"><img src="https:/godoc.org/github.com/jinzhu/gorm?status.svg" alt="GoDoc"></a>
|
<a href="https://app.wercker.com/project/bykey/0cb7bb1039e21b74f8274941428e0921" target="_blank"><img src="https:/app.wercker.com/status/0cb7bb1039e21b74f8274941428e0921/s/master" alt="wercker status" title="wercker status"></a>
|
||||||
<a href="https://gitter.im/jinzhu/gorm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank"><img src="https:/badges.gitter.im/Join%20Chat.svg" alt="Join the chat at https://gitter.im/jinzhu/gorm"></a></p>
|
<a href="https://godoc.org/github.com/jinzhu/gorm" target="_blank"><img src="https:/godoc.org/github.com/jinzhu/gorm?status.svg" alt="GoDoc"></a></p>
|
||||||
<h2 id="overview">Overview</h2>
|
<h2 id="overview">Overview</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Full-Featured ORM (almost)</li>
|
<li>Full-Featured ORM (almost)</li>
|
||||||
<li>Chainable API</li>
|
<li>Associations (Has One, Has Many, Belongs To, Many To Many, Polymorphism)</li>
|
||||||
<li>Auto Migrations</li>
|
|
||||||
<li>Relations (Has One, Has Many, Belongs To, Many To Many, Polymorphism)</li>
|
|
||||||
<li>Callbacks (Before/After Create/Save/Update/Delete/Find)</li>
|
<li>Callbacks (Before/After Create/Save/Update/Delete/Find)</li>
|
||||||
<li>Preloading (eager loading)</li>
|
<li>Preloading (eager loading)</li>
|
||||||
<li>Transactions</li>
|
<li>Transactions</li>
|
||||||
<li>Embed Anonymous Struct</li>
|
<li>Composite Primary Key</li>
|
||||||
<li>Soft Deletes</li>
|
<li>SQL Builder</li>
|
||||||
<li>Customizable Logger</li>
|
<li>Auto Migrations</li>
|
||||||
<li>Iteration Support via Rows</li>
|
<li>Logger</li>
|
||||||
|
<li>Extendable, write Plugins based on GORM callbacks</li>
|
||||||
<li>Every feature comes with tests</li>
|
<li>Every feature comes with tests</li>
|
||||||
<li>Developer Friendly</li>
|
<li>Developer Friendly</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2 id="install">Install</h2>
|
<h2 id="install">Install</h2>
|
||||||
<pre><code>go get -u github.com/jinzhu/gorm
|
<pre><code class="lang-sh">go get -u github.com/jinzhu/gorm
|
||||||
</code></pre><h2 id="upgrading">Upgrading</h2>
|
</code></pre>
|
||||||
<p><a href="changelog.html">Change Log</a></p>
|
<h2 id="upgrading-to-v10">Upgrading To V1.0</h2>
|
||||||
<h2 id="basic-usage">Basic Usage</h2>
|
<ul>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Product <span class="hljs-keyword">struct</span> {
|
<li><a href="changelog.html">CHANGELOG</a></li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="quick-start">Quick Start</h2>
|
||||||
|
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main
|
||||||
|
|
||||||
|
<span class="hljs-keyword">import</span> (
|
||||||
|
<span class="hljs-string">"github.com/jinzhu/gorm"</span>
|
||||||
|
_ <span class="hljs-string">"github.com/jinzhu/gorm/dialects/sqlite"</span>
|
||||||
|
)
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> Product <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Code <span class="hljs-typename">string</span>
|
Code <span class="hljs-keyword">string</span>
|
||||||
Price <span class="hljs-typename">uint</span>
|
Price <span class="hljs-keyword">uint</span>
|
||||||
}
|
|
||||||
|
|
||||||
<span class="hljs-keyword">var</span> db *gorm.DB
|
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> init() {
|
|
||||||
<span class="hljs-keyword">var</span> err error
|
|
||||||
db, err = gorm.Open(<span class="hljs-string">"sqlite"</span>, <span class="hljs-string">"test.db"</span>)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> main() {
|
<span class="hljs-keyword">func</span> main() {
|
||||||
|
db, err := gorm.Open(<span class="hljs-string">"sqlite"</span>, <span class="hljs-string">"test.db"</span>)
|
||||||
|
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
|
||||||
|
<span class="hljs-built_in">panic</span>(<span class="hljs-string">"faield to connect database"</span>)
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Create</span>
|
||||||
db.Create(&Product{Code: <span class="hljs-string">"L1212"</span>, Price: <span class="hljs-number">1000</span>})
|
db.Create(&Product{Code: <span class="hljs-string">"L1212"</span>, Price: <span class="hljs-number">1000</span>})
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Read</span>
|
||||||
<span class="hljs-keyword">var</span> product Product
|
<span class="hljs-keyword">var</span> product Product
|
||||||
db.First(&product, <span class="hljs-number">1</span>) <span class="hljs-comment">// find product with id 1</span>
|
db.First(&product, <span class="hljs-number">1</span>) <span class="hljs-comment">// find product with id 1</span>
|
||||||
db.First(&product, <span class="hljs-string">"code = ?"</span>, <span class="hljs-string">"L1212"</span>) <span class="hljs-comment">// find product with code l1212</span>
|
db.First(&product, <span class="hljs-string">"code = ?"</span>, <span class="hljs-string">"L1212"</span>) <span class="hljs-comment">// find product with code l1212</span>
|
||||||
|
|
||||||
db.Model(&product).Update(<span class="hljs-string">"Price"</span>, <span class="hljs-number">2000</span>) <span class="hljs-comment">// update product's price to 2000</span>
|
<span class="hljs-comment">// Update - update product's price to 2000</span>
|
||||||
|
db.Model(&product).Update(<span class="hljs-string">"Price"</span>, <span class="hljs-number">2000</span>)
|
||||||
|
|
||||||
db.Delete(&product) <span class="hljs-comment">// delete product</span>
|
<span class="hljs-comment">// Delete - delete product</span>
|
||||||
|
db.Delete(&product)
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h1 id="author">Author</h1>
|
<h1 id="author">Author</h1>
|
||||||
|
151
models.html
151
models.html
@ -5,8 +5,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
<meta name="description" content="Gorm has defined struct gorm.Model, which could be embeded in your models, it will add fields ID, CreatedAt, UpdatedAt, DeletedAt to your model">
|
<meta name="description" content="Base model definition gorm.Model, including fields ID, CreatedAt, UpdatedAt, DeletedAt, you could embed it in your model, or only write those fields you wa">
|
||||||
<meta name="generator" content="GitBook 3.0.0-pre.1">
|
<meta name="generator" content="GitBook 3.0.0-pre.5">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -69,8 +69,8 @@
|
|||||||
data-level="2"
|
data-level="2"
|
||||||
data-chapter-title="Models"
|
data-chapter-title="Models"
|
||||||
data-filepath="models.md"
|
data-filepath="models.md"
|
||||||
data-basepath=""
|
data-basepath="."
|
||||||
data-revision="Wed Mar 02 2016 08:53:45 GMT+0800 (CST)"
|
data-revision="Tue Mar 08 2016 12:18:21 GMT+0800 (CST)"
|
||||||
data-innerlanguage="">
|
data-innerlanguage="">
|
||||||
|
|
||||||
|
|
||||||
@ -178,12 +178,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="2.2" data-path="models.html">
|
<li class="chapter " data-level="2.2" data-path="models.html">
|
||||||
|
|
||||||
<a href="models.html#conventions-overriding-conventions">
|
<a href="models.html#conventions">
|
||||||
|
|
||||||
|
|
||||||
<b>2.2.</b>
|
<b>2.2.</b>
|
||||||
|
|
||||||
Naming Conventions & Overriding
|
Conventions & Overriding
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -481,12 +481,12 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
<li class="chapter " data-level="5.4" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#compose-primary-key">
|
<a href="advanced.html#generic-database-interface-sqldb">
|
||||||
|
|
||||||
|
|
||||||
<b>5.4.</b>
|
<b>5.4.</b>
|
||||||
|
|
||||||
Composite Primary Key
|
Generic database interface sql.DB
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@ -496,11 +496,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
<li class="chapter " data-level="5.5" data-path="advanced.html">
|
||||||
|
|
||||||
<a href="advanced.html#logger">
|
<a href="advanced.html#compose-primary-key">
|
||||||
|
|
||||||
|
|
||||||
<b>5.5.</b>
|
<b>5.5.</b>
|
||||||
|
|
||||||
|
Composite Primary Key
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="5.6" data-path="advanced.html">
|
||||||
|
|
||||||
|
<a href="advanced.html#logger">
|
||||||
|
|
||||||
|
|
||||||
|
<b>5.6.</b>
|
||||||
|
|
||||||
Overriding Logger
|
Overriding Logger
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -532,11 +547,26 @@
|
|||||||
|
|
||||||
<li class="chapter " data-level="6.1" data-path="development.html">
|
<li class="chapter " data-level="6.1" data-path="development.html">
|
||||||
|
|
||||||
<a href="development.html#callbacks">
|
<a href="development.html#architecture">
|
||||||
|
|
||||||
|
|
||||||
<b>6.1.</b>
|
<b>6.1.</b>
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="chapter " data-level="6.2" data-path="development.html">
|
||||||
|
|
||||||
|
<a href="development.html#write-plugins">
|
||||||
|
|
||||||
|
|
||||||
|
<b>6.2.</b>
|
||||||
|
|
||||||
Write Plugins
|
Write Plugins
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
@ -585,7 +615,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<h1>
|
<h1>
|
||||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||||
<a href="" >Models</a>
|
<a href="." >Models</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -599,7 +629,7 @@
|
|||||||
<!-- toc -->
|
<!-- toc -->
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#model-defination">Model Defination</a></li>
|
<li><a href="#model-defination">Model Defination</a></li>
|
||||||
<li><a href="#conventions-overriding-conventions">Conventions & Overriding Conventions</a><ul>
|
<li><a href="#conventions">Conventions</a><ul>
|
||||||
<li><a href="#gormmodel-struct"><code>gorm.Model</code> struct</a></li>
|
<li><a href="#gormmodel-struct"><code>gorm.Model</code> struct</a></li>
|
||||||
<li><a href="#table-name-is-the-pluralized-version-of-struct-name">Table name is the pluralized version of struct name</a></li>
|
<li><a href="#table-name-is-the-pluralized-version-of-struct-name">Table name is the pluralized version of struct name</a></li>
|
||||||
<li><a href="#column-name-is-the-snake-case-of-fields-name">Column name is the snake case of field's name</a></li>
|
<li><a href="#column-name-is-the-snake-case-of-fields-name">Column name is the snake case of field's name</a></li>
|
||||||
@ -613,34 +643,84 @@
|
|||||||
<!-- toc stop -->
|
<!-- toc stop -->
|
||||||
<h2 id="model-defination">Model Defination</h2>
|
<h2 id="model-defination">Model Defination</h2>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Birthday time.Time
|
Birthday time.Time
|
||||||
Age <span class="hljs-typename">int</span>
|
Age <span class="hljs-keyword">int</span>
|
||||||
Name <span class="hljs-typename">string</span> <span class="hljs-string">`sql:"size:255"`</span> <span class="hljs-comment">// Default size for string is 255, you could reset it with this tag</span>
|
Name <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"size:255"`</span> <span class="hljs-comment">// Default size for string is 255, reset it with this tag</span>
|
||||||
Num <span class="hljs-typename">int</span> <span class="hljs-string">`sql:"AUTO_INCREMENT"`</span>
|
Num <span class="hljs-keyword">int</span> <span class="hljs-string">`gorm:"AUTO_INCREMENT"`</span>
|
||||||
IgnoreMe <span class="hljs-typename">int</span> <span class="hljs-string">`sql:"-"`</span> <span class="hljs-comment">// Ignore this field</span>
|
|
||||||
|
CreditCard CreditCard <span class="hljs-comment">// One-To-One relationship (has one - use CreditCard's UserID as foreign key)</span>
|
||||||
|
Emails []Email <span class="hljs-comment">// One-To-Many relationship (has many - use Email's UserID as foreign key)</span>
|
||||||
|
|
||||||
|
BillingAddress Address <span class="hljs-comment">// One-To-One relationship (belongs to - use BillingAddressID as foreign key)</span>
|
||||||
|
BillingAddressID sql.NullInt64
|
||||||
|
|
||||||
|
ShippingAddress Address <span class="hljs-comment">// One-To-One relationship (belongs to - use ShippingAddressID as foreign key)</span>
|
||||||
|
ShippingAddressID <span class="hljs-keyword">int</span>
|
||||||
|
|
||||||
|
IgnoreMe <span class="hljs-keyword">int</span> <span class="hljs-string">`gorm:"-"`</span> <span class="hljs-comment">// Ignore this field</span>
|
||||||
|
Languages []Language <span class="hljs-string">`gorm:"many2many:user_languages;"`</span> <span class="hljs-comment">// Many-To-Many relationship, 'user_languages' is join table</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> Email <span class="hljs-keyword">struct</span> {
|
||||||
|
ID <span class="hljs-keyword">int</span>
|
||||||
|
UserID <span class="hljs-keyword">int</span> <span class="hljs-string">`gorm:"index"`</span> <span class="hljs-comment">// Foreign key (belongs to), tag `index` will create index for this column</span>
|
||||||
|
Email <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"type:varchar(100);unique_index"`</span> <span class="hljs-comment">// `type` set sql type, `unique_index` will create unique index for this column</span>
|
||||||
|
Subscribed <span class="hljs-keyword">bool</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> Address <span class="hljs-keyword">struct</span> {
|
||||||
|
ID <span class="hljs-keyword">int</span>
|
||||||
|
Address1 <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"not null;unique"`</span> <span class="hljs-comment">// Set field as not nullable and unique</span>
|
||||||
|
Address2 <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"type:varchar(100);unique"`</span>
|
||||||
|
Post sql.NullString <span class="hljs-string">`gorm:"not null"`</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> Language <span class="hljs-keyword">struct</span> {
|
||||||
|
ID <span class="hljs-keyword">int</span>
|
||||||
|
Name <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"index:idx_name_code"`</span> <span class="hljs-comment">// Create index with name, and will create combined index if find other fields defined same name</span>
|
||||||
|
Code <span class="hljs-keyword">string</span> <span class="hljs-string">`gorm:"index:idx_name_code"`</span> <span class="hljs-comment">// `unique_index` also works</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-keyword">type</span> CreditCard <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
UserID <span class="hljs-keyword">uint</span>
|
||||||
|
Number <span class="hljs-keyword">string</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2 id="conventions--overriding-conventions">Conventions & Overriding Conventions</h2>
|
<h2 id="conventions">Conventions</h2>
|
||||||
<h3 id="gormmodel-struct"><code>gorm.Model</code> struct</h3>
|
<h3 id="gormmodel-struct"><code>gorm.Model</code> struct</h3>
|
||||||
<p>Gorm has defined struct <code>gorm.Model</code>, which could be embeded in your models, it will add fields <code>ID</code>, <code>CreatedAt</code>, <code>UpdatedAt</code>, <code>DeletedAt</code> to your model</p>
|
<p>Base model definition <code>gorm.Model</code>, including fields <code>ID</code>, <code>CreatedAt</code>, <code>UpdatedAt</code>, <code>DeletedAt</code>, you could embed it in your model, or only write those fields you want</p>
|
||||||
<pre><code class="lang-go"><span class="hljs-comment">// Model's definition</span>
|
<pre><code class="lang-go"><span class="hljs-comment">// Base Model's definition</span>
|
||||||
<span class="hljs-keyword">type</span> Model <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Model <span class="hljs-keyword">struct</span> {
|
||||||
ID <span class="hljs-typename">uint</span> <span class="hljs-string">`gorm:"primary_key"`</span>
|
ID <span class="hljs-keyword">uint</span> <span class="hljs-string">`gorm:"primary_key"`</span>
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
DeletedAt *time.Time
|
DeletedAt *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Add fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`</span>
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
gorm.Model
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Only need field `ID`, `CreatedAt`</span>
|
||||||
|
<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
|
ID <span class="hljs-keyword">uint</span>
|
||||||
|
CreatedAt time.Time
|
||||||
|
Name <span class="hljs-keyword">string</span>
|
||||||
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="table-name-is-the-pluralized-version-of-struct-name">Table name is the pluralized version of struct name</h3>
|
<h3 id="table-name-is-the-pluralized-version-of-struct-name">Table name is the pluralized version of struct name</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {} <span class="hljs-comment">// default table name is `users`</span>
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {} <span class="hljs-comment">// default table name is `users`</span>
|
||||||
|
|
||||||
<span class="hljs-comment">// set User's table name to be `profiles</span>
|
<span class="hljs-comment">// set User's table name to be `profiles</span>
|
||||||
<span class="hljs-keyword">type</span> (User) TableName() <span class="hljs-typename">string</span> {
|
<span class="hljs-keyword">type</span> (User) TableName() <span class="hljs-keyword">string</span> {
|
||||||
<span class="hljs-keyword">return</span> <span class="hljs-string">"profiles"</span>
|
<span class="hljs-keyword">return</span> <span class="hljs-string">"profiles"</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-keyword">func</span> (u User) TableName() <span class="hljs-typename">string</span> {
|
<span class="hljs-keyword">func</span> (u User) TableName() <span class="hljs-keyword">string</span> {
|
||||||
<span class="hljs-keyword">if</span> u.Role == <span class="hljs-string">"admin"</span> {
|
<span class="hljs-keyword">if</span> u.Role == <span class="hljs-string">"admin"</span> {
|
||||||
<span class="hljs-keyword">return</span> <span class="hljs-string">"admin_users"</span>
|
<span class="hljs-keyword">return</span> <span class="hljs-string">"admin_users"</span>
|
||||||
} <span class="hljs-keyword">else</span> {
|
} <span class="hljs-keyword">else</span> {
|
||||||
@ -649,33 +729,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-comment">// Disable table name's pluralization globally</span>
|
<span class="hljs-comment">// Disable table name's pluralization globally</span>
|
||||||
db.SingularTable(<span class="hljs-constant">true</span>) <span class="hljs-comment">// if set this to true, `User`'s default table name will be `user`, table name setted with `TableName` won't be affected</span>
|
db.SingularTable(<span class="hljs-literal">true</span>) <span class="hljs-comment">// if set this to true, `User`'s default table name will be `user`, table name setted with `TableName` won't be affected</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="column-name-is-the-snake-case-of-fields-name">Column name is the snake case of field's name</h3>
|
<h3 id="column-name-is-the-snake-case-of-fields-name">Column name is the snake case of field's name</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
ID <span class="hljs-typename">uint</span> <span class="hljs-comment">// column name will be `id`</span>
|
ID <span class="hljs-keyword">uint</span> <span class="hljs-comment">// column name will be `id`</span>
|
||||||
Name <span class="hljs-typename">string</span> <span class="hljs-comment">// column name will be `name`</span>
|
Name <span class="hljs-keyword">string</span> <span class="hljs-comment">// column name will be `name`</span>
|
||||||
Birthday time.Time <span class="hljs-comment">// column name will be `birthday`</span>
|
Birthday time.Time <span class="hljs-comment">// column name will be `birthday`</span>
|
||||||
CreatedAt time.Time <span class="hljs-comment">// column name will be `created_at`</span>
|
CreatedAt time.Time <span class="hljs-comment">// column name will be `created_at`</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<span class="hljs-comment">// Overriding Column Name</span>
|
||||||
<span class="hljs-keyword">type</span> Animal <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Animal <span class="hljs-keyword">struct</span> {
|
||||||
AnimalId <span class="hljs-typename">int64</span> <span class="hljs-string">`gorm:"column:beast_id"`</span> <span class="hljs-comment">// set column name to `beast_id`</span>
|
AnimalId <span class="hljs-keyword">int64</span> <span class="hljs-string">`gorm:"column:beast_id"`</span> <span class="hljs-comment">// set column name to `beast_id`</span>
|
||||||
Birthday time.Time <span class="hljs-string">`gorm:"column:day_of_the_beast"`</span> <span class="hljs-comment">// set column name to `day_of_the_beast`</span>
|
Birthday time.Time <span class="hljs-string">`gorm:"column:day_of_the_beast"`</span> <span class="hljs-comment">// set column name to `day_of_the_beast`</span>
|
||||||
Age <span class="hljs-typename">int64</span> <span class="hljs-string">`gorm:"column:age_of_the_beast"`</span> <span class="hljs-comment">// set column name to `age_of_the_beast`</span>
|
Age <span class="hljs-keyword">int64</span> <span class="hljs-string">`gorm:"column:age_of_the_beast"`</span> <span class="hljs-comment">// set column name to `age_of_the_beast`</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="field-id-as-primary-key">Field <code>ID</code> as primary key</h3>
|
<h3 id="field-id-as-primary-key">Field <code>ID</code> as primary key</h3>
|
||||||
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
<pre><code class="lang-go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
|
||||||
ID <span class="hljs-typename">uint</span> <span class="hljs-comment">// field named `ID` is the default primary key for `User`</span>
|
ID <span class="hljs-keyword">uint</span> <span class="hljs-comment">// field named `ID` will be the default primary field</span>
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span class="hljs-comment">// your could also use tag `primary_key` to set other field as primary key</span>
|
<span class="hljs-comment">// Set a field to be primary field with tag `primary_key`</span>
|
||||||
<span class="hljs-keyword">type</span> Animal <span class="hljs-keyword">struct</span> {
|
<span class="hljs-keyword">type</span> Animal <span class="hljs-keyword">struct</span> {
|
||||||
AnimalId <span class="hljs-typename">int64</span> <span class="hljs-string">`gorm:"primary_key"`</span> <span class="hljs-comment">// set AnimalId to be primary key</span>
|
AnimalId <span class="hljs-keyword">int64</span> <span class="hljs-string">`gorm:"primary_key"`</span> <span class="hljs-comment">// set AnimalId to be primary key</span>
|
||||||
Name <span class="hljs-typename">string</span>
|
Name <span class="hljs-keyword">string</span>
|
||||||
Age <span class="hljs-typename">int64</span>
|
Age <span class="hljs-keyword">int64</span>
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="field-createdat-used-to-store-records-created-time">Field <code>CreatedAt</code> used to store record's created time</h3>
|
<h3 id="field-createdat-used-to-store-records-created-time">Field <code>CreatedAt</code> used to store record's created time</h3>
|
||||||
@ -691,7 +772,7 @@ db.Model(&user).Update(<span class="hljs-string">"CreatedAt"</span
|
|||||||
db.Model(&user).Update(<span class="hljs-string">"name"</span>, <span class="hljs-string">"jinzhu"</span>) <span class="hljs-comment">// will set `UpdatedAt` to current time</span>
|
db.Model(&user).Update(<span class="hljs-string">"name"</span>, <span class="hljs-string">"jinzhu"</span>) <span class="hljs-comment">// will set `UpdatedAt` to current time</span>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="use-deletedat-to-store-records-deleted-time-if-field-exists">Use <code>DeletedAt</code> to store record's deleted time if field exists</h3>
|
<h3 id="use-deletedat-to-store-records-deleted-time-if-field-exists">Use <code>DeletedAt</code> to store record's deleted time if field exists</h3>
|
||||||
<p>Delete records having <code>DeletedAt</code> field, it won't delete the record from database, but will set field <code>DeletedAt</code>'s value to current time.</p>
|
<p>Delete records having <code>DeletedAt</code> field, it won't be deleted from database, but only set field <code>DeletedAt</code>'s value to current time, and the record is not findable when querying, refer <a href="curd.html#soft-delete">Soft Delete</a></p>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
1
search_index.json
Normal file
1
search_index.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user