menilite 0.5.4 → 0.5.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/articles/getting-started.md +85 -0
- data/docs/articles/list.yaml +1 -0
- data/docs/articles/model.md +40 -0
- data/docs/css/milligram.min.css +11 -0
- data/docs/css/style.css +62 -0
- data/docs/index.html +113 -0
- data/docs/src/build.rb +21 -0
- data/docs/views/index.haml +22 -0
- data/lib/menilite/client/http.rb +17 -30
- data/lib/menilite/client/store.rb +29 -4
- data/lib/menilite/model.rb +11 -1
- data/lib/menilite/server/activerecord_store.rb +9 -1
- data/lib/menilite/server/router.rb +12 -0
- data/lib/menilite/server/serializer.rb +1 -1
- data/lib/menilite/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c317e28a8910d938484dbea1431a8ebac0e66a094641e6e80506f41dc5e18054
|
4
|
+
data.tar.gz: 5344962b1388ffbcba13d4edd3ada16037b18c6387d15493ad3ba2ef8eb59109
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df8013186d7e01816cb655e5d72773cc3b0de44a9cca2cd33dfe38f1fea45466cc8e201e763b997d8770243c5c55cdd27665a96d19d9d4df7a88c821a0a3b01f
|
7
|
+
data.tar.gz: c411bcd675aaabf4a4b86501a943cb18adf5c764cecff1075f9bcfe4bc14cb5ec28efbddcf0b9444d2651e9a14cfe2e79a504836c496cdc944e8079b6b64c1e6
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Getting started
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'menilite'
|
9
|
+
```
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install menilite
|
18
|
+
|
19
|
+
## How to use
|
20
|
+
|
21
|
+
You can generate the template project by [Silica](https://github.com/youchan/silica) to get started.
|
22
|
+
|
23
|
+
$ gem install silica
|
24
|
+
$ silica new your-app
|
25
|
+
$ cd your-app
|
26
|
+
$ bundle install
|
27
|
+
$ bundle exec rackup
|
28
|
+
|
29
|
+
## Model definition
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class User < Menilite::Model
|
33
|
+
field :name
|
34
|
+
field :password
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
Model definition is shared from the client side (compiled by Opal) and the server side (in MRI).
|
39
|
+
In this tiny example, `User` model has two string fields (`name` and `password`).
|
40
|
+
Field has a type and the type is set `string` as default.
|
41
|
+
You can specify another type by the following way, for example.
|
42
|
+
|
43
|
+
field :active, :boolean
|
44
|
+
|
45
|
+
## Action
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class User < Menilite::Model
|
49
|
+
action :signup, save: true do |password|
|
50
|
+
self.password = BCrypt::Password.create(password)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
Models can have actions. The action is executed on the server side and the client code call the action as a method.
|
56
|
+
|
57
|
+
on the client side
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
user = User.new(name: 'youchan')
|
61
|
+
user.auth('topsecret')
|
62
|
+
```
|
63
|
+
|
64
|
+
## Controller
|
65
|
+
|
66
|
+
Controllers can have actions too.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class ApplicationController < Menilite::Controller
|
70
|
+
action :login do |username, password|
|
71
|
+
user = User.find(name: username)
|
72
|
+
if user && user.auth(password)
|
73
|
+
session[:user_id] = user.id
|
74
|
+
else
|
75
|
+
raise 'login failed'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
The action of Controller is defined as a class method on the client side.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
ApplicationController.login('youchan', 'topsecret')
|
85
|
+
```
|
@@ -0,0 +1 @@
|
|
1
|
+
- getting-started.md
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Model
|
2
|
+
|
3
|
+
## How to make a model
|
4
|
+
|
5
|
+
### 1st step: Create a database migration
|
6
|
+
|
7
|
+
Create a database migration script of `ActiveRecord` to make a table for model.
|
8
|
+
|
9
|
+
```terminal
|
10
|
+
$ bundle exec rake db:create_migration create_user
|
11
|
+
```
|
12
|
+
|
13
|
+
Edit the migration file.
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
|
17
|
+
```
|
18
|
+
|
19
|
+
|
20
|
+
### User privilege
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
class UserPrivilege < Menilite::Privilege
|
24
|
+
def key
|
25
|
+
:user_privilege
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(user)
|
29
|
+
@user = user
|
30
|
+
end
|
31
|
+
|
32
|
+
def filter
|
33
|
+
{ user_id: @user.id }
|
34
|
+
end
|
35
|
+
|
36
|
+
def fields
|
37
|
+
{ user_id: @user.id }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/*!
|
2
|
+
* Milligram v1.3.0
|
3
|
+
* https://milligram.github.io
|
4
|
+
*
|
5
|
+
* Copyright (c) 2017 CJ Patoilo
|
6
|
+
* Licensed under the MIT license
|
7
|
+
*/
|
8
|
+
|
9
|
+
*,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#606c76;font-family:'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;font-size:1.6em;font-weight:300;letter-spacing:.01em;line-height:1.6}blockquote{border-left:0.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#9b4dca;border:0.1rem solid #9b4dca;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#9b4dca;border-color:#9b4dca}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#9b4dca}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#606c76;color:#606c76}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#9b4dca}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#9b4dca}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#606c76}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#9b4dca}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#f4f5f6;border-left:0.3rem solid #9b4dca;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #f4f5f6;margin:3.0rem 0}input[type='email'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:0.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem;width:100%}input[type='email']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,textarea:focus,select:focus{border-color:#9b4dca;outline:0}select{background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="#d1d1d1" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 29 14" width="29"><path fill="#9b4dca" d="M9.37727 3.625l5.08154 6.93523L19.54036 3.625"/></svg>')}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.container{margin:0 auto;max-width:112.0rem;padding:0 2.0rem;position:relative;width:100%}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{-ms-grid-row-align:center;align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}a{color:#9b4dca;text-decoration:none}a:focus,a:hover{color:#606c76}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;width:100%}td,th{border-bottom:0.1rem solid #e1e1e1;padding:1.2rem 1.5rem;text-align:left}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}img{max-width:100%}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right}
|
10
|
+
|
11
|
+
/*# sourceMappingURL=milligram.min.css.map */
|
data/docs/css/style.css
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
body {
|
2
|
+
margin: 0;
|
3
|
+
background-color: #eeeeee;
|
4
|
+
}
|
5
|
+
|
6
|
+
.header {
|
7
|
+
height: 52px;
|
8
|
+
background-color: #f0f0ff;
|
9
|
+
border-bottom: solid 1px #aaaaaa;
|
10
|
+
}
|
11
|
+
|
12
|
+
.header .header-content {
|
13
|
+
height: 100%;
|
14
|
+
margin: 0 auto;
|
15
|
+
width: 1024px;
|
16
|
+
}
|
17
|
+
|
18
|
+
svg.github-corner {
|
19
|
+
width: 52px;
|
20
|
+
height: 52px;
|
21
|
+
}
|
22
|
+
|
23
|
+
p.title {
|
24
|
+
height: 100%;
|
25
|
+
margin: 0;
|
26
|
+
padding-top: 8px;
|
27
|
+
font-size: 160%;
|
28
|
+
font-weight: 200;
|
29
|
+
}
|
30
|
+
|
31
|
+
.wrap-main {
|
32
|
+
margin: 0 auto;
|
33
|
+
width: 1024px;
|
34
|
+
background-color: #ffffff;
|
35
|
+
}
|
36
|
+
|
37
|
+
.wrap-2column {
|
38
|
+
display: flex;
|
39
|
+
height: calc(100vh - 52px);
|
40
|
+
}
|
41
|
+
|
42
|
+
.nav {
|
43
|
+
flex: 20%;
|
44
|
+
border-right: solid 1px #aaaaaa;
|
45
|
+
}
|
46
|
+
|
47
|
+
.nav ul {
|
48
|
+
list-style: none;
|
49
|
+
margin: 0;
|
50
|
+
}
|
51
|
+
|
52
|
+
.nav li {
|
53
|
+
border-bottom: solid 1px #aaaaaa;
|
54
|
+
padding: 1rem;
|
55
|
+
}
|
56
|
+
|
57
|
+
.content {
|
58
|
+
flex: 80%;
|
59
|
+
padding: 10px;
|
60
|
+
height: 100%;
|
61
|
+
overflow: scroll;
|
62
|
+
}
|
data/docs/index.html
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset='utf-8'>
|
5
|
+
<link href='css/milligram.min.css' rel='stylesheet'>
|
6
|
+
<link href='css/style.css' rel='stylesheet'>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div class='header'>
|
10
|
+
<div class='header-content'>
|
11
|
+
<p class='title'>menilite documentation</p>
|
12
|
+
</div>
|
13
|
+
<div class='corner-icon'>
|
14
|
+
<a href="https://github.com/youchan/menilite" class="github-corner" aria-label="View source on GitHub"><svg width="52" height="52" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<div class='wrap-main'>
|
18
|
+
<div class='wrap-2column'>
|
19
|
+
<div class='nav'>
|
20
|
+
<ul>
|
21
|
+
<li>Getting started</li>
|
22
|
+
</ul>
|
23
|
+
</div>
|
24
|
+
<div class='content'>
|
25
|
+
<div class='ch'><h1>Getting started</h1>
|
26
|
+
|
27
|
+
<h2>Installation</h2>
|
28
|
+
|
29
|
+
<p>Add this line to your application's Gemfile:</p>
|
30
|
+
|
31
|
+
<pre><code class="ruby">gem 'menilite'
|
32
|
+
</code></pre>
|
33
|
+
|
34
|
+
<p>And then execute:</p>
|
35
|
+
|
36
|
+
<pre><code>$ bundle
|
37
|
+
</code></pre>
|
38
|
+
|
39
|
+
<p>Or install it yourself as:</p>
|
40
|
+
|
41
|
+
<pre><code>$ gem install menilite
|
42
|
+
</code></pre>
|
43
|
+
|
44
|
+
<h2>How to use</h2>
|
45
|
+
|
46
|
+
<p>You can generate the template project by <a href="https://github.com/youchan/silica">Silica</a> to get started.</p>
|
47
|
+
|
48
|
+
<pre><code>$ gem install silica
|
49
|
+
$ silica new your-app
|
50
|
+
$ cd your-app
|
51
|
+
$ bundle install
|
52
|
+
$ bundle exec rackup
|
53
|
+
</code></pre>
|
54
|
+
|
55
|
+
<h2>Model definition</h2>
|
56
|
+
|
57
|
+
<pre><code class="ruby">class User < Menilite::Model
|
58
|
+
field :name
|
59
|
+
field :password
|
60
|
+
end
|
61
|
+
</code></pre>
|
62
|
+
|
63
|
+
<p>Model definition is shared from the client side (compiled by Opal) and the server side (in MRI).<br>
|
64
|
+
In this tiny example, <code>User</code> model has two string fields (<code>name</code> and <code>password</code>).<br>
|
65
|
+
Field has a type and the type is set <code>string</code> as default.<br>
|
66
|
+
You can specify another type by the following way, for example.</p>
|
67
|
+
|
68
|
+
<pre><code>field :active, :boolean
|
69
|
+
</code></pre>
|
70
|
+
|
71
|
+
<h2>Action</h2>
|
72
|
+
|
73
|
+
<pre><code class="ruby">class User < Menilite::Model
|
74
|
+
action :signup, save: true do |password|
|
75
|
+
self.password = BCrypt::Password.create(password)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
</code></pre>
|
79
|
+
|
80
|
+
<p>Models can have actions. The action is executed on the server side and the client code call the action as a method.</p>
|
81
|
+
|
82
|
+
<p>on the client side</p>
|
83
|
+
|
84
|
+
<pre><code class="ruby">user = User.new(name: 'youchan')
|
85
|
+
user.auth('topsecret')
|
86
|
+
</code></pre>
|
87
|
+
|
88
|
+
<h2>Controller</h2>
|
89
|
+
|
90
|
+
<p>Controllers can have actions too.</p>
|
91
|
+
|
92
|
+
<pre><code class="ruby">class ApplicationController < Menilite::Controller
|
93
|
+
action :login do |username, password|
|
94
|
+
user = User.find(name: username)
|
95
|
+
if user && user.auth(password)
|
96
|
+
session[:user_id] = user.id
|
97
|
+
else
|
98
|
+
raise 'login failed'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
</code></pre>
|
103
|
+
|
104
|
+
<p>The action of Controller is defined as a class method on the client side.</p>
|
105
|
+
|
106
|
+
<pre><code class="ruby">ApplicationController.login('youchan', 'topsecret')
|
107
|
+
</code></pre>
|
108
|
+
</div>
|
109
|
+
</div>
|
110
|
+
</div>
|
111
|
+
</div>
|
112
|
+
</body>
|
113
|
+
</html>
|
data/docs/src/build.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "haml"
|
2
|
+
require "psych"
|
3
|
+
require "redcarpet"
|
4
|
+
|
5
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
|
6
|
+
autolink: true,
|
7
|
+
tables: true,
|
8
|
+
fenced_code_blocks: true)
|
9
|
+
|
10
|
+
haml = File.read(File.expand_path("../views/index.haml", __dir__))
|
11
|
+
list = Psych.load_file(File.expand_path("../articles/list.yaml", __dir__))
|
12
|
+
|
13
|
+
titles, contents = list.each_with_object([[], []]) do |name, (titles, contents)|
|
14
|
+
md = File.read(File.expand_path("../articles/#{name}", __dir__))
|
15
|
+
titles << md.split("\n").first.sub(/^\# (.*)/, '\\1')
|
16
|
+
contents << markdown.render(md)
|
17
|
+
end
|
18
|
+
|
19
|
+
File.open(File.expand_path("../index.html", __dir__), "w") do |out|
|
20
|
+
out << Haml::Engine.new(haml, :format => :html5).render(Object.new, {titles: titles, contents: contents})
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%meta{charset: "utf-8"}
|
5
|
+
%link{rel:"stylesheet", href: "css/milligram.min.css"}
|
6
|
+
%link{rel:"stylesheet", href: "css/style.css"}
|
7
|
+
%body
|
8
|
+
.header
|
9
|
+
.header-content
|
10
|
+
%p.title menilite documentation
|
11
|
+
.corner-icon
|
12
|
+
!= '<a href="https://github.com/youchan/menilite" class="github-corner" aria-label="View source on GitHub"><svg width="52" height="52" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>'
|
13
|
+
.wrap-main
|
14
|
+
.wrap-2column
|
15
|
+
.nav
|
16
|
+
%ul
|
17
|
+
- titles.each do |title|
|
18
|
+
%li= title
|
19
|
+
.content
|
20
|
+
- contents.each do |content|
|
21
|
+
.ch!= content
|
22
|
+
|
data/lib/menilite/client/http.rb
CHANGED
@@ -2,45 +2,32 @@ module Menilite
|
|
2
2
|
module Http
|
3
3
|
class << self
|
4
4
|
def get_json(url, &block)
|
5
|
-
(
|
6
|
-
|
7
|
-
%x(
|
8
|
-
fetch(
|
9
|
-
url,
|
10
|
-
{
|
11
|
-
method: 'get',
|
12
|
-
headers: {
|
13
|
-
'Accept': 'application/json',
|
14
|
-
'Content-Type': 'application/json'
|
15
|
-
},
|
16
|
-
credentials: "same-origin",
|
17
|
-
}
|
18
|
-
).then(callback);
|
19
|
-
)
|
20
|
-
|
21
|
-
promise
|
5
|
+
request_json(url, :get, &block)
|
22
6
|
end
|
23
7
|
|
24
8
|
def post_json(url, data, &block)
|
9
|
+
request_json(url, :post, data, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def request_json(url, method, data=nil, &block)
|
25
13
|
(callback, promise) = prepare(url, &block)
|
26
14
|
|
15
|
+
params = {
|
16
|
+
method: method,
|
17
|
+
headers: {
|
18
|
+
'Accept': 'application/json',
|
19
|
+
'Content-Type': 'application/json'
|
20
|
+
},
|
21
|
+
credentials: "same-origin"
|
22
|
+
}
|
23
|
+
|
24
|
+
params[:body] = data.to_json if data
|
25
|
+
|
27
26
|
%x(
|
28
|
-
fetch(
|
29
|
-
url,
|
30
|
-
{
|
31
|
-
method: 'post',
|
32
|
-
headers: {
|
33
|
-
'Accept': 'application/json',
|
34
|
-
'Content-Type': 'application/json'
|
35
|
-
},
|
36
|
-
credentials: "same-origin",
|
37
|
-
body: #{data.to_json}
|
38
|
-
}
|
39
|
-
).then(callback);
|
27
|
+
fetch(url, params.$to_n()).then(callback);
|
40
28
|
)
|
41
29
|
|
42
30
|
promise
|
43
|
-
|
44
31
|
end
|
45
32
|
|
46
33
|
private
|
@@ -20,6 +20,14 @@ module Menilite
|
|
20
20
|
self[model_class][id]
|
21
21
|
end
|
22
22
|
|
23
|
+
def fetch(model_class, filter:)
|
24
|
+
@tables[model_class].find{|x| match_filter?(x, filter) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def match_filter?(model, filter)
|
28
|
+
filter.all? {|k, v| model[k] == v }
|
29
|
+
end
|
30
|
+
|
23
31
|
def save(model)
|
24
32
|
is_array = model.is_a?(Array)
|
25
33
|
models = is_array ? model : [ model ]
|
@@ -48,9 +56,11 @@ module Menilite
|
|
48
56
|
|
49
57
|
def fetch!(model_class, filter: nil, includes: nil, order: nil, &block)
|
50
58
|
tables = @tables
|
51
|
-
|
52
|
-
|
53
|
-
|
59
|
+
param_list = []
|
60
|
+
param_list << filter.map {|k,v| "#{k}=#{v}" } if filter
|
61
|
+
param_list << "order=#{[order].flatten.join(?,)}" if order
|
62
|
+
param_list << "includes=#{includes}" if includes
|
63
|
+
params = ?? + param_list.join(?&) if param_list.length > 0
|
54
64
|
Menilite::Http.get_json("api/#{model_class}#{params}") do
|
55
65
|
on :success do |json|
|
56
66
|
tables[model_class] = json.map {|value| [value[:id], Menilite::Deserializer.deserialize(model_class, value, includes)] }.to_h
|
@@ -64,7 +74,22 @@ module Menilite
|
|
64
74
|
end
|
65
75
|
end
|
66
76
|
|
67
|
-
def delete(
|
77
|
+
def delete(model_class, filter:, &block)
|
78
|
+
tables = @tables
|
79
|
+
Menilite::Http.request_json("api/#{model_class}", :delete, filter) do
|
80
|
+
on :success do |json|
|
81
|
+
res = json.map {|value| tables[model_class].delete(value[:id]) }
|
82
|
+
block.call res if block
|
83
|
+
end
|
84
|
+
|
85
|
+
on :failure do |res|
|
86
|
+
puts ">> Error: #{res.error}"
|
87
|
+
puts ">>>> delete: #{model.inspect}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete_all(mdoel_class)
|
68
93
|
@tables[model_class] = {}
|
69
94
|
end
|
70
95
|
|
data/lib/menilite/model.rb
CHANGED
@@ -81,6 +81,10 @@ module Menilite
|
|
81
81
|
self.save(&block)
|
82
82
|
end
|
83
83
|
|
84
|
+
def delete!(&block)
|
85
|
+
self.class.delete(self.id, &block)
|
86
|
+
end
|
87
|
+
|
84
88
|
def on(event, *field_names, &block)
|
85
89
|
field_names.each {|file_name| set_listener(event, file_name, &block) }
|
86
90
|
end
|
@@ -125,9 +129,14 @@ module Menilite
|
|
125
129
|
self.new(fields).save(&block)
|
126
130
|
end
|
127
131
|
|
132
|
+
def delete(id, &block)
|
133
|
+
self.init
|
134
|
+
store.delete(self, filter: {id: id}, &block)
|
135
|
+
end
|
136
|
+
|
128
137
|
def delete_all
|
129
138
|
self.init
|
130
|
-
store.
|
139
|
+
store.delete_all(self)
|
131
140
|
end
|
132
141
|
|
133
142
|
|
@@ -341,6 +350,7 @@ module Menilite
|
|
341
350
|
end
|
342
351
|
|
343
352
|
def convert_type(key, value)
|
353
|
+
return ["guid", value] if ["id", "guid"].include?(key.to_s)
|
344
354
|
field_info = self.field_info[key] || self.field_info[key.to_s.sub(/_id\z/,'').to_sym]
|
345
355
|
raise "no such field #{key} in #{self}" unless field_info
|
346
356
|
converted = case field_info.type
|
@@ -64,7 +64,15 @@ module Menilite
|
|
64
64
|
assoc.map {|ar| to_model(ar, model_class) } || []
|
65
65
|
end
|
66
66
|
|
67
|
-
def delete(model_class)
|
67
|
+
def delete(model_class, filter:)
|
68
|
+
assoc = @armodels[model_class].all
|
69
|
+
assoc = assoc.where(filter_condition(model_class, filter))
|
70
|
+
res = assoc.map {|ar| to_model(ar, model_class) } || []
|
71
|
+
assoc.delete_all
|
72
|
+
res
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete_all(model_class)
|
68
76
|
@armodels[model_class].delete_all
|
69
77
|
end
|
70
78
|
|
@@ -114,6 +114,18 @@ module Menilite
|
|
114
114
|
json Serializer.serialize(results, includes)
|
115
115
|
end
|
116
116
|
|
117
|
+
delete "/#{resource_name}" do
|
118
|
+
PrivilegeService.init
|
119
|
+
router.before_action_handlers(klass, 'delete').each {|h| self.instance_eval(&h[:proc]) }
|
120
|
+
params = JSON.parse(request.body.read)
|
121
|
+
results = klass.fetch(filter: params).map do |model|
|
122
|
+
model.delete
|
123
|
+
model
|
124
|
+
end
|
125
|
+
|
126
|
+
json Serializer.serialize(results)
|
127
|
+
end
|
128
|
+
|
117
129
|
klass.action_info.each do |name, action|
|
118
130
|
path = action.options[:save] || action.options[:class] ? "/#{resource_name}/#{action.name}" : "/#{resource_name}/#{action.name}/:id"
|
119
131
|
|
data/lib/menilite/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: menilite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- youchan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -84,6 +84,14 @@ files:
|
|
84
84
|
- Rakefile
|
85
85
|
- bin/console
|
86
86
|
- bin/setup
|
87
|
+
- docs/articles/getting-started.md
|
88
|
+
- docs/articles/list.yaml
|
89
|
+
- docs/articles/model.md
|
90
|
+
- docs/css/milligram.min.css
|
91
|
+
- docs/css/style.css
|
92
|
+
- docs/index.html
|
93
|
+
- docs/src/build.rb
|
94
|
+
- docs/views/index.haml
|
87
95
|
- lib/menilite.rb
|
88
96
|
- lib/menilite/client/deserializer.rb
|
89
97
|
- lib/menilite/client/http.rb
|