menilite 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcaa8393a0dd1330df681b904fe1119cb0626787d732cfdc208aff776002f69c
4
- data.tar.gz: '003830da5b448a2b248a753f11f5c18a3ea4a9cb78592faf3224ebb82e9a5261'
3
+ metadata.gz: c317e28a8910d938484dbea1431a8ebac0e66a094641e6e80506f41dc5e18054
4
+ data.tar.gz: 5344962b1388ffbcba13d4edd3ada16037b18c6387d15493ad3ba2ef8eb59109
5
5
  SHA512:
6
- metadata.gz: 6d15e0267c419226fecba30cf9962ce68bb065ff90b0f0a67b9412bbf85d44341e08b816e92d89d3418355a11b3599eb6987dcfe6a1090e13b42a7d7d2e2758b
7
- data.tar.gz: b7d68000678b4a96bb7335470bb4888a3f68f82a6434c3b66e71b6d8645acac5a9fd1e3766e97d2675c75313a5064fd123e4a28fbf2fc3d67180e6ca1ab4e34b
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 */
@@ -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
+ }
@@ -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&#39;s Gemfile:</p>
30
+
31
+ <pre><code class="ruby">gem &#39;menilite&#39;
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 &lt; 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 &lt; 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: &#39;youchan&#39;)
85
+ user.auth(&#39;topsecret&#39;)
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 &lt; Menilite::Controller
93
+ action :login do |username, password|
94
+ user = User.find(name: username)
95
+ if user &amp;&amp; user.auth(password)
96
+ session[:user_id] = user.id
97
+ else
98
+ raise &#39;login failed&#39;
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(&#39;youchan&#39;, &#39;topsecret&#39;)
107
+ </code></pre>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </body>
113
+ </html>
@@ -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
+
@@ -2,45 +2,32 @@ module Menilite
2
2
  module Http
3
3
  class << self
4
4
  def get_json(url, &block)
5
- (callback, promise) = prepare(url, &block)
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
- params = filter && (?? + filter.map {|k,v| "#{k}=#{v}" }.join(?&))
52
- params = (params ? params + ?& : ??) + "order=#{[order].flatten.join(?,)}" if order
53
- params = (params ? params + ?& : ??) + "includes=#{includes}" if includes
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(mdoel_class)
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
 
@@ -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.delete(self)
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
 
@@ -1,6 +1,6 @@
1
1
  module Menilite
2
2
  module Serializer
3
- def self.serialize(obj, includes)
3
+ def self.serialize(obj, includes=nil)
4
4
  case obj
5
5
  when Menilite::Model
6
6
  hash = obj.to_h
@@ -1,3 +1,3 @@
1
1
  module Menilite
2
- VERSION = "0.5.4"
2
+ VERSION = "0.5.5"
3
3
  end
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
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-03-21 00:00:00.000000000 Z
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