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 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