ru.Bee 1.4.0 → 1.5.0
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 +4 -4
- data/lib/app/views/apples_.erb +1 -0
- data/lib/rubee.rb +55 -15
- data/lib/tests/rubee_generator_test.rb +190 -0
- data/lib/tests/rubeeapp_test.rb +3 -8
- data/lib/tests/test.db +0 -0
- data/lib/tests/user_model_test.rb +5 -1
- data/readme.md +187 -65
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bf3fb103ba0d1e81af5f77b6ec12395bf0d9701dac0f67fab585cd2c87ebb38
|
4
|
+
data.tar.gz: 3d8356ee2225e738b94ce1b9338597b1bd49ca103f3e55df3261c7cb2f45b71c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1160be8ac7aa5397c5fe0d33411f4111f47338fab92253eec0d8f566528e6819d1b3fa6dff579cd7b23b201fb671f2119f79fe459eaa131bd23b748a7a88d473
|
7
|
+
data.tar.gz: 0705de64ac2b5a78cb547d41d5386d323d80db13e2acac26d9e84137a1308699c074f60328efe75f01fdedcf99e7729557449d305506e11dc40d17a4a6d6b3db
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>apples_ View</h1>
|
data/lib/rubee.rb
CHANGED
@@ -34,7 +34,7 @@ module Rubee
|
|
34
34
|
route = Router.route_for(request)
|
35
35
|
# if react is the view so we would like to delegate not cauth by rubee routes to it.
|
36
36
|
if Rubee::Configuration.react[:on] && !route
|
37
|
-
index = File.read
|
37
|
+
index = File.read(File.join(Rubee::APP_ROOT, Rubee::LIB, 'app/views', 'index.html'))
|
38
38
|
return [200, { 'content-type' => 'text/html' }, [index]]
|
39
39
|
end
|
40
40
|
# if not found return 404
|
@@ -213,9 +213,9 @@ module Rubee
|
|
213
213
|
end
|
214
214
|
|
215
215
|
class Generator
|
216
|
-
def initialize(model_name,
|
216
|
+
def initialize(model_name, model_attributes, controller_name, action_name, **options)
|
217
217
|
@model_name = model_name&.downcase
|
218
|
-
@
|
218
|
+
@model_attributes = model_attributes || []
|
219
219
|
@plural_name = controller_name.to_s.gsub('Controller', '').downcase.to_s
|
220
220
|
@action_name = action_name
|
221
221
|
@controller_name = controller_name
|
@@ -240,7 +240,7 @@ module Rubee
|
|
240
240
|
|
241
241
|
content = <<~RUBY
|
242
242
|
class #{@model_name.capitalize} < Rubee::SequelObject
|
243
|
-
attr_accessor
|
243
|
+
#{'attr_accessor' + @model_attributes.map { |hash| ":#{hash[:name]}" }.join(', ') unless @model_attributes.empty?}
|
244
244
|
end
|
245
245
|
RUBY
|
246
246
|
|
@@ -271,17 +271,17 @@ module Rubee
|
|
271
271
|
if @react[:view_name]
|
272
272
|
view_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "app/views/#{@react[:view_name]}")
|
273
273
|
content = <<~JS
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
274
|
+
import React, { useEffect, useState } from "react";
|
275
|
+
// 1. Add your logic that fetches data
|
276
|
+
// 2. Do not forget to add respective react route
|
277
|
+
export function User() {
|
278
|
+
|
279
|
+
return (
|
280
|
+
<div>
|
281
|
+
<h2>#{@react[:view_name]} view</h2>
|
282
|
+
</div>
|
283
|
+
);
|
284
|
+
}
|
285
285
|
JS
|
286
286
|
else
|
287
287
|
view_file = File.join(Rubee::APP_ROOT, Rubee::LIB, "app/views/#{@plural_name}_#{@action_name}.erb")
|
@@ -311,6 +311,11 @@ module Rubee
|
|
311
311
|
content = <<~RUBY
|
312
312
|
class Create#{@plural_name.capitalize}
|
313
313
|
def call
|
314
|
+
return if Rubee::SequelObject::DB.tables.include?(:#{@plural_name})
|
315
|
+
|
316
|
+
Rubee::SequelObject::DB.create_table(:#{@plural_name}) do
|
317
|
+
#{@model_attributes.map { |attribute| generate_sequel_schema(attribute) }.join("\n\t\t\t")}
|
318
|
+
end
|
314
319
|
end
|
315
320
|
end
|
316
321
|
RUBY
|
@@ -318,5 +323,40 @@ module Rubee
|
|
318
323
|
File.open(db_file, 'w') { |file| file.write(content) }
|
319
324
|
color_puts("DB file for #{@plural_name} created", color: :green)
|
320
325
|
end
|
326
|
+
|
327
|
+
def generate_sequel_schema(attribute)
|
328
|
+
type = attribute[:type]
|
329
|
+
name = if attribute[:name].is_a?(Array)
|
330
|
+
attribute[:name].map { |nom| ":#{nom}" }.join(", ").prepend('[') + ']'
|
331
|
+
else
|
332
|
+
":#{attribute[:name]}"
|
333
|
+
end
|
334
|
+
table = attribute[:table] || 'replace_with_table_name'
|
335
|
+
options = attribute[:options] || {}
|
336
|
+
|
337
|
+
lookup_hash = {
|
338
|
+
primary: "primary_key #{name}",
|
339
|
+
string: "String #{name}",
|
340
|
+
text: "String #{name}, text: true",
|
341
|
+
integer: "Integer #{name}",
|
342
|
+
date: "Date #{name}",
|
343
|
+
datetime: "DateTime #{name}",
|
344
|
+
time: "Time #{name}",
|
345
|
+
boolean: "TrueClass #{name}",
|
346
|
+
bigint: "Bignum #{name}",
|
347
|
+
decimal: "BigDecimal #{name}",
|
348
|
+
foreign_key: "foreign_key #{name}, :#{table}",
|
349
|
+
index: "index #{name}",
|
350
|
+
unique: "unique #",
|
351
|
+
}
|
352
|
+
|
353
|
+
statement = lookup_hash[type.to_sym]
|
354
|
+
|
355
|
+
options.keys.each do |key|
|
356
|
+
statement += ", #{key}: '#{options[key]}'"
|
357
|
+
end
|
358
|
+
|
359
|
+
statement
|
360
|
+
end
|
321
361
|
end
|
322
362
|
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
describe 'Rubee::Generator' do
|
4
|
+
describe 'generates Sequel schema lines' do
|
5
|
+
after do
|
6
|
+
File.delete('lib/app/models/apple.rb') if File.exist?('lib/app/models/apple.rb')
|
7
|
+
File.delete('lib/db/create_apples.rb') if File.exist?('lib/db/create_apples.rb')
|
8
|
+
end
|
9
|
+
it 'for string with just name' do
|
10
|
+
generator = Rubee::Generator.new(nil, nil, nil, nil)
|
11
|
+
|
12
|
+
attribute = { name: 'something', type: :string }
|
13
|
+
|
14
|
+
text = generator.send(:generate_sequel_schema, attribute)
|
15
|
+
|
16
|
+
_(text).must_equal('String :something')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'for string name and options' do
|
20
|
+
generator = Rubee::Generator.new(nil, nil, nil, nil)
|
21
|
+
|
22
|
+
attribute = { name: 'something', type: :string, options: { curse: 'squirrel' } }
|
23
|
+
|
24
|
+
text = generator.send(:generate_sequel_schema, attribute)
|
25
|
+
|
26
|
+
_(text).must_equal("String :something, curse: 'squirrel'")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'generates Sequel file' do
|
31
|
+
after do
|
32
|
+
File.delete('lib/app/models/apple.rb') if File.exist?('lib/app/models/apple.rb')
|
33
|
+
File.delete('lib/db/create_apples.rb') if File.exist?('lib/db/create_apples.rb')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'not without a model' do
|
37
|
+
generator = Rubee::Generator.new(nil, nil, nil, nil)
|
38
|
+
generator.call
|
39
|
+
|
40
|
+
_(File.exist?('lib/db/create_apples.rb')).must_equal false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'with a model only' do
|
44
|
+
generator = Rubee::Generator.new('apple', nil, 'apples', nil)
|
45
|
+
generator.call
|
46
|
+
|
47
|
+
_(File.exist?('lib/db/create_apples.rb')).must_equal true
|
48
|
+
|
49
|
+
lines = File.readlines('lib/db/create_apples.rb').map(&:chomp).join("\n")
|
50
|
+
|
51
|
+
_(lines.include?('class CreateApples')).must_equal true
|
52
|
+
_(lines.include?('def call')).must_equal true
|
53
|
+
_(lines.include?('return if Rubee::SequelObject::DB.tables.include?(:apples)')).must_equal true
|
54
|
+
_(lines.include?('Rubee::SequelObject::DB.create_table(:apples) do')).must_equal true
|
55
|
+
_(lines.include?('String')).must_equal false
|
56
|
+
_(lines.include?('end')).must_equal true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'with a model with attributes' do
|
60
|
+
generator = Rubee::Generator.new('apple', [{ name: 'title', type: :string }, {name: 'content', type: :text }], 'apples', nil)
|
61
|
+
generator.call
|
62
|
+
|
63
|
+
_(File.exist?('lib/db/create_apples.rb')).must_equal true
|
64
|
+
|
65
|
+
lines = File.readlines('lib/db/create_apples.rb').map(&:chomp).join("\n")
|
66
|
+
|
67
|
+
_(lines.include?('class CreateApples')).must_equal true
|
68
|
+
_(lines.include?('def call')).must_equal true
|
69
|
+
_(lines.include?('return if Rubee::SequelObject::DB.tables.include?(:apples)')).must_equal true
|
70
|
+
_(lines.include?('Rubee::SequelObject::DB.create_table(:apples) do')).must_equal true
|
71
|
+
_(lines.include?('String :title')).must_equal true
|
72
|
+
_(lines.include?('String :content, text: true')).must_equal true
|
73
|
+
_(lines.include?('end')).must_equal true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'with a model with different attributes' do
|
77
|
+
generator = Rubee::Generator.new('apple', [{name: 'id', type: :bigint}, {name: 'colour', type: :string }, {name: 'weight', type: :integer }], 'apples', nil)
|
78
|
+
generator.call
|
79
|
+
|
80
|
+
_(File.exist?('lib/db/create_apples.rb')).must_equal true
|
81
|
+
|
82
|
+
lines = File.readlines('lib/db/create_apples.rb').map(&:chomp).join("\n")
|
83
|
+
|
84
|
+
_(lines.include?('class CreateApples')).must_equal true
|
85
|
+
_(lines.include?('def call')).must_equal true
|
86
|
+
_(lines.include?('return if Rubee::SequelObject::DB.tables.include?(:apples)')).must_equal true
|
87
|
+
_(lines.include?('Rubee::SequelObject::DB.create_table(:apples) do')).must_equal true
|
88
|
+
_(lines.include?('Bignum :id')).must_equal true
|
89
|
+
_(lines.include?('String :colour')).must_equal true
|
90
|
+
_(lines.include?('Integer :weight')).must_equal true
|
91
|
+
_(lines.include?('end')).must_equal true
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'with a model with an attribute with multiple names' do
|
95
|
+
generator = Rubee::Generator.new('apple', [{ name: ['blue_id', 'shoe_id'], type: :foreign_key, table: 'blue_and_shoe_join_tb' }], 'apples', nil)
|
96
|
+
generator.call
|
97
|
+
|
98
|
+
_(File.exist?('lib/db/create_apples.rb')).must_equal true
|
99
|
+
|
100
|
+
lines = File.readlines('lib/db/create_apples.rb').map(&:chomp).join("\n")
|
101
|
+
|
102
|
+
_(lines.include?('class CreateApples')).must_equal true
|
103
|
+
_(lines.include?('def call')).must_equal true
|
104
|
+
_(lines.include?('return if Rubee::SequelObject::DB.tables.include?(:apples)')).must_equal true
|
105
|
+
_(lines.include?('Rubee::SequelObject::DB.create_table(:apples) do')).must_equal true
|
106
|
+
_(lines.include?('foreign_key [:blue_id, :shoe_id]')).must_equal true
|
107
|
+
_(lines.include?(':blue_and_shoe_join_tb')).must_equal true
|
108
|
+
_(lines.include?('end')).must_equal true
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'with a model with a foreign_key without table' do
|
112
|
+
generator = Rubee::Generator.new('apple', [{ name: 'blue_id', type: :foreign_key }], 'apples', nil)
|
113
|
+
generator.call
|
114
|
+
|
115
|
+
_(File.exist?('lib/db/create_apples.rb')).must_equal true
|
116
|
+
|
117
|
+
lines = File.readlines('lib/db/create_apples.rb').map(&:chomp).join("\n")
|
118
|
+
|
119
|
+
_(lines.include?('class CreateApples')).must_equal true
|
120
|
+
_(lines.include?('def call')).must_equal true
|
121
|
+
_(lines.include?('return if Rubee::SequelObject::DB.tables.include?(:apples)')).must_equal true
|
122
|
+
_(lines.include?('Rubee::SequelObject::DB.create_table(:apples) do')).must_equal true
|
123
|
+
_(lines.include?('foreign_key :blue_id')).must_equal true
|
124
|
+
_(lines.include?(':replace_with_table_name')).must_equal true
|
125
|
+
_(lines.include?('end')).must_equal true
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'generates Model file' do
|
130
|
+
after do
|
131
|
+
File.delete('lib/app/models/apple.rb') if File.exist?('lib/app/models/apple.rb')
|
132
|
+
File.delete('lib/db/create_apples.rb') if File.exist?('lib/db/create_apples.rb')
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'not without a model' do
|
136
|
+
generator = Rubee::Generator.new(nil, nil, nil, nil)
|
137
|
+
generator.call
|
138
|
+
|
139
|
+
_(File.exist?('lib/app/models/apple.rb')).must_equal false
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'with a model only' do
|
143
|
+
generator = Rubee::Generator.new('apple', nil, 'apples', nil)
|
144
|
+
generator.call
|
145
|
+
|
146
|
+
_(File.exist?('lib/app/models/apple.rb')).must_equal true
|
147
|
+
|
148
|
+
lines = File.readlines('lib/app/models/apple.rb').map(&:chomp).join("\n")
|
149
|
+
|
150
|
+
_(lines.include?('class Apple < Rubee::SequelObject')).must_equal true
|
151
|
+
_(lines.include?('attr_accessor')).must_equal false
|
152
|
+
_(lines.include?('end')).must_equal true
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'with a model with attributes' do
|
156
|
+
generator = Rubee::Generator.new('apple', [{ name: 'title', type: :string }, {name: 'content', type: :text }], 'apples', nil)
|
157
|
+
generator.call
|
158
|
+
|
159
|
+
_(File.exist?('lib/app/models/apple.rb')).must_equal true
|
160
|
+
|
161
|
+
lines = File.readlines('lib/app/models/apple.rb').map(&:chomp).join("\n")
|
162
|
+
|
163
|
+
_(lines.include?('class Apple < Rubee::SequelObject')).must_equal true
|
164
|
+
_(lines.include?('attr_accessor')).must_equal true
|
165
|
+
_(lines.include?(':title, :content')).must_equal true
|
166
|
+
_(lines.include?('end')).must_equal true
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'with a model with different attributes' do
|
170
|
+
generator = Rubee::Generator.new('apple', [{name: 'id', type: :bigInt}, {name: 'colour', type: :string }, {name: 'weight', type: :integer }], 'apples', nil)
|
171
|
+
generator.call
|
172
|
+
|
173
|
+
_(File.exist?('lib/app/models/apple.rb')).must_equal true
|
174
|
+
|
175
|
+
lines = File.readlines('lib/app/models/apple.rb').map(&:chomp).join("\n")
|
176
|
+
|
177
|
+
_(lines.include?('class Apple < Rubee::SequelObject')).must_equal true
|
178
|
+
_(lines.include?('attr_accessor')).must_equal true
|
179
|
+
_(lines.include?(':id, :colour, :weight')).must_equal true
|
180
|
+
_(lines.include?('end')).must_equal true
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe 'generates View file' do
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
describe 'generates Controller file' do
|
189
|
+
end
|
190
|
+
end
|
data/lib/tests/rubeeapp_test.rb
CHANGED
@@ -7,14 +7,6 @@ class RubeeAppTest < Minitest::Test
|
|
7
7
|
Rubee::Application.instance
|
8
8
|
end
|
9
9
|
|
10
|
-
def setup
|
11
|
-
Rubee::Configuration.setup(env = :test) { _1.react = { on: false, env: } }
|
12
|
-
end
|
13
|
-
|
14
|
-
def teardown
|
15
|
-
Rubee::Configuration.setup(env = :test) { _1.react = { on: false, env: } }
|
16
|
-
end
|
17
|
-
|
18
10
|
def test_welcome_route
|
19
11
|
get('/')
|
20
12
|
|
@@ -30,10 +22,13 @@ class RubeeAppTest < Minitest::Test
|
|
30
22
|
|
31
23
|
def test_react_home
|
32
24
|
Rubee::Configuration.setup(env = :test) { _1.react = { on: true, env: } }
|
25
|
+
|
33
26
|
get('/home')
|
34
27
|
|
35
28
|
assert_equal(200, last_response.status)
|
36
29
|
assert_includes(last_response.body, '<div id="app">')
|
37
30
|
assert_includes(last_response.body, 'bundle.js')
|
31
|
+
|
32
|
+
Rubee::Configuration.setup(env = :test) { _1.react = { on: false, env: } }
|
38
33
|
end
|
39
34
|
end
|
data/lib/tests/test.db
CHANGED
Binary file
|
@@ -153,9 +153,13 @@ describe 'User model' do
|
|
153
153
|
User.destroy_all(cascade: true)
|
154
154
|
end
|
155
155
|
|
156
|
+
before do
|
157
|
+
User.destroy_all(cascade: true)
|
158
|
+
end
|
159
|
+
|
156
160
|
describe 'when there are records' do
|
157
161
|
it 'returns all records' do
|
158
|
-
skip "This is Flaky test that blcoks dev, need to be fixed"
|
162
|
+
# skip "This is Flaky test that blcoks dev, need to be fixed"
|
159
163
|
user = User.new(email: 'ok-test@test.com', password: '123')
|
160
164
|
user2 = User.new(email: 'ok-test2@test.com', password: '123')
|
161
165
|
user.save
|
data/readme.md
CHANGED
@@ -24,10 +24,9 @@ All greaet features are yet to come!
|
|
24
24
|
- **Contract driven**: Define your API contracts in a simple, declarative manner. And generate the files for you.
|
25
25
|
- **Fast**: Optimized for speed, providing a quick response to requests. Everything is relative, I know!
|
26
26
|
- **Rack**: Rack backed. All Rack api is available for integration.
|
27
|
-
- **Router**: Router driven - generates all required files from the routes.
|
28
27
|
- **Databases**: Sqlite3, Postgres, Mysql and many more supported by sequel gem.
|
29
28
|
- **Views**: Json, ERB and plain HTML and ..
|
30
|
-
- **React**
|
29
|
+
- **React** is supported out of the box as a rubee view
|
31
30
|
- **Bundlable** Charge your ruBee with any gem you need and update your project with bundle.
|
32
31
|
- **ORM** All models are natively ORM objects, however you can use it as a blueurpint for any datasources.
|
33
32
|
- **Authentificatable** Add JWT authentification easily to any controller action.
|
@@ -51,8 +50,7 @@ cd my_project
|
|
51
50
|
3. Install dependencies
|
52
51
|
|
53
52
|
***Prerequisites***<br />
|
54
|
-
|
55
|
-
Aside that, make sure:
|
53
|
+
Make sure:
|
56
54
|
**Ruby** language (3+) is installed
|
57
55
|
**Bundler** is installed
|
58
56
|
|
@@ -67,35 +65,46 @@ rubee start
|
|
67
65
|
|
68
66
|
5. Open your browser and go to http://localhost:7000
|
69
67
|
|
70
|
-
##
|
71
|
-
1. Add the routes to the routes.rb
|
68
|
+
## Run the tests
|
72
69
|
```bash
|
73
|
-
|
74
|
-
...
|
75
|
-
# draw the contract
|
76
|
-
router.get "/apples", to: "apples#index",
|
77
|
-
model: {
|
78
|
-
name: "apple",
|
79
|
-
attributes: [
|
80
|
-
{ name: 'id', type: :integer },
|
81
|
-
{ name: 'colour', type: :string },
|
82
|
-
{ name: 'weight', type: :integer }
|
83
|
-
]
|
84
|
-
}
|
85
|
-
end
|
70
|
+
rubee test
|
86
71
|
```
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
```
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
72
|
+
|
73
|
+
## Create API contract and generate files from the routes
|
74
|
+
1. Add the routes to the routes.rb
|
75
|
+
```ruby
|
76
|
+
Rubee::Router.draw do |router|
|
77
|
+
...
|
78
|
+
# draw the contract
|
79
|
+
router.get "/apples", to: "apples#index",
|
80
|
+
model: {
|
81
|
+
name: "apple",
|
82
|
+
attributes: [
|
83
|
+
{ name: 'id', type: :primary },
|
84
|
+
{ name: 'colour', type: :string },
|
85
|
+
{ name: 'weight', type: :integer }
|
86
|
+
]
|
87
|
+
}
|
88
|
+
end
|
89
|
+
```
|
90
|
+
2. generate the files
|
91
|
+
```bash
|
92
|
+
rubee generate get /apples
|
93
|
+
```
|
94
|
+
- This will generate the following files
|
95
|
+
```bash
|
96
|
+
./app/controllers/apples_controller.rb # Controller with respective action
|
97
|
+
./app/views/apples_index.erb # ERB view that is rendered by the controller right away
|
98
|
+
./app/models/apple.rb # Model that acts as ORM
|
99
|
+
./db/create_apples.rb # Database migration file needed for creating repsective table
|
100
|
+
```
|
101
|
+
|
102
|
+
3. Run the initial db migration
|
103
|
+
```bash
|
104
|
+
rubee db run:all
|
105
|
+
```
|
106
|
+
|
107
|
+
5. Fill the generated files with the logic you need and run the server again!
|
99
108
|
|
100
109
|
## Model
|
101
110
|
Model in ruBee is just simple ruby object that can be serilalized in the view
|
@@ -107,8 +116,8 @@ Here below is a simple example on how it can be used by rendering json from in m
|
|
107
116
|
#ApplesController
|
108
117
|
|
109
118
|
def show
|
110
|
-
#
|
111
|
-
apples = [Apple.new(colour: 'red', weight: '1lb'), Apple.new(colour: 'green', weight: '1lb')]
|
119
|
+
# In memory example
|
120
|
+
apples = [Apple.new(colour: 'red', weight: '1lb'), Apple.new(colour: 'green', weight: '1lb')]
|
112
121
|
apple = apples.find { |apple| apple.colour = params[:colour] }
|
113
122
|
|
114
123
|
response_with object: apple, type: :json
|
@@ -122,8 +131,8 @@ Just make sure Serializable module included in the target class.
|
|
122
131
|
attr_accessor :id, :colour, :weight
|
123
132
|
end
|
124
133
|
```
|
125
|
-
However, you can simply turn it to ORM object by extending database class.
|
126
|
-
|
134
|
+
However, you can simply turn it to ORM object by extending database class Rubee::SequelObject.
|
135
|
+
This one is already serializable and charged with hooks.
|
127
136
|
```Ruby
|
128
137
|
class Apple < Rubee::SequelObject
|
129
138
|
attr_accessor :id, :colour, :weight
|
@@ -131,7 +140,6 @@ However, you can simply turn it to ORM object by extending database class.
|
|
131
140
|
```
|
132
141
|
|
133
142
|
So in the controller you would need to query your target object now.
|
134
|
-
|
135
143
|
```ruby
|
136
144
|
#ApplesController
|
137
145
|
|
@@ -276,10 +284,138 @@ irb(main):010> .then { |dataset| Comment.serialize(dataset) }
|
|
276
284
|
This is recommended when you want to run one query and serialize it back to Rubee object only once.
|
277
285
|
So it may safe some resources.
|
278
286
|
|
287
|
+
## Routing
|
288
|
+
Rubee uses explicit routes. In the routes.rb yout can define routes for any of the main HTTP methods. You can also add any matched parameter denoted by a pair of `{ }` in the path of the route. Eg. `/path/to/{a_key}/somewhere`
|
289
|
+
|
290
|
+
### Routing methods
|
291
|
+
``` ruby
|
292
|
+
Rubee::Router.draw do |router|
|
293
|
+
router.get '/posts', to: 'posts#index'
|
294
|
+
router.post '/posts', to: 'posts#create'
|
295
|
+
router.patch '/posts/{id}', to: 'posts#update'
|
296
|
+
router.put '/posts/{id}', to: 'posts#update'
|
297
|
+
router.delete '/posts/{id}', to: 'posts#delete'
|
298
|
+
router.head '/posts', to: 'posts#index'
|
299
|
+
router.connect '/posts', to: 'posts#index'
|
300
|
+
router.options '/posts', to: 'posts#index'
|
301
|
+
router.trace '/posts', to: 'posts#index'
|
302
|
+
end
|
303
|
+
```
|
304
|
+
|
305
|
+
As you see above every route is set up as:\
|
306
|
+
`route.http_method path, to: "controller#action", model { ...optional }`
|
307
|
+
|
308
|
+
### Defining Model attributes in routes
|
309
|
+
One of Rubee's unique traits is where we can define our models for generation. You've seen above one possible way you can set up.
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
Rubee::Router.draw do |router|
|
313
|
+
...
|
314
|
+
# draw the contract
|
315
|
+
router.get "/apples", to: "apples#index",
|
316
|
+
model: {
|
317
|
+
name: "apple",
|
318
|
+
attributes: [
|
319
|
+
{ name: 'id', type: :primary },
|
320
|
+
{ name: 'colour', type: :string },
|
321
|
+
{ name: 'weight', type: :integer }
|
322
|
+
]
|
323
|
+
}
|
324
|
+
end
|
325
|
+
```
|
326
|
+
|
327
|
+
There are many other keys supported by us and Sequel to help generate your initial db files. Other supported attribute key types are:
|
328
|
+
``` ruby
|
329
|
+
[
|
330
|
+
{ name: 'key1', type: :primary},
|
331
|
+
{ name: 'key2', type: :string },
|
332
|
+
{ name: 'key3', type: :text },
|
333
|
+
{ name: 'key4', type: :integer },
|
334
|
+
{ name: 'key5', type: :date },
|
335
|
+
{ name: 'key6', type: :datetime },
|
336
|
+
{ name: 'key7', type: :time },
|
337
|
+
{ name: 'key8', type: :boolean },
|
338
|
+
{ name: 'key9', type: :bigint },
|
339
|
+
{ name: 'key10', type: :decimal },
|
340
|
+
{ name: 'key11', type: :foreign_key },
|
341
|
+
{ name: 'key12', type: :index },
|
342
|
+
{ name: 'key13', type: :unique }
|
343
|
+
]
|
344
|
+
```
|
345
|
+
Every attribute can have a set of options passed based on their related [Sequel schema definition](https://github.com/jeremyevans/sequel/blob/master/doc/schema_modification.rdoc).
|
346
|
+
|
347
|
+
An example of this would be for the type string: \
|
348
|
+
`{name: 'key', type: :string, options: { size: 50, fixed: true } }`
|
349
|
+
|
350
|
+
Gets translated to:\
|
351
|
+
`String :key, size: 50, fixed: true`
|
352
|
+
|
353
|
+
### Generation from routes
|
354
|
+
As long as you have a `{ model: 'something' }` passed to your given route you can use it to generate your initial model files. If only a `path` and a `to:` are defined will only generate a controller and a corresponding view.
|
355
|
+
|
356
|
+
To generate based on a get route for the path /apples:\
|
357
|
+
`rubee generate get /apples` or `rubee gen get /apples`\
|
358
|
+
|
359
|
+
To generate base on a patch request for the path /apples/{id}:\
|
360
|
+
`rubee generate patch /apples/{id}` or `rubee gen patch /apples/{id}`
|
361
|
+
|
279
362
|
|
363
|
+
Example:
|
364
|
+
```ruby
|
365
|
+
Rubee::Router.draw do |router|
|
366
|
+
...
|
367
|
+
# draw the contract
|
368
|
+
router.get "/apples", to: "apples#index"
|
369
|
+
end
|
370
|
+
```
|
371
|
+
Will Generate:
|
372
|
+
```bash
|
373
|
+
./app/controllers/apples_controller.rb # Controller with respective action
|
374
|
+
./app/views/apples_index.erb # ERB view that is rendered by the controller right away
|
375
|
+
```
|
376
|
+
|
377
|
+
Example 2:
|
378
|
+
```ruby
|
379
|
+
Rubee::Router.draw do |router|
|
380
|
+
...
|
381
|
+
# draw the contract
|
382
|
+
router.get "/apples", to: "apples#index", model: { name: 'apple' }
|
383
|
+
end
|
384
|
+
```
|
385
|
+
Will generate:
|
386
|
+
```bash
|
387
|
+
./app/controllers/apples_controller.rb # Controller with respective action
|
388
|
+
./app/views/apples_index.erb # ERB view that is rendered by the controller right away
|
389
|
+
./app/models/apple.rb # Model that acts as ORM
|
390
|
+
```
|
391
|
+
|
392
|
+
Example 3:
|
393
|
+
```ruby
|
394
|
+
Rubee::Router.draw do |router|
|
395
|
+
...
|
396
|
+
# draw the contract
|
397
|
+
router.get "/apples", to: "apples#index",
|
398
|
+
model: {
|
399
|
+
name: 'apple',
|
400
|
+
attributes: [
|
401
|
+
{ name: 'id', type: :primary },
|
402
|
+
{ name: 'colour', type: :string },
|
403
|
+
{ name: 'weight', type: :integer }
|
404
|
+
]
|
405
|
+
}
|
406
|
+
end
|
407
|
+
```
|
408
|
+
|
409
|
+
Will generate:
|
410
|
+
```bash
|
411
|
+
./app/controllers/apples_controller.rb # Controller with respective action
|
412
|
+
./app/models/apple.rb # Model that acts as ORM
|
413
|
+
./app/views/apples_index.erb # ERB view that is rendered by the controller right away
|
414
|
+
./db/create_items.rb # Database migration file needed for creating repsective table
|
415
|
+
```
|
280
416
|
|
281
417
|
## Views
|
282
|
-
View in ruBee is just a plain html/erb file that can be rendered from the controller.
|
418
|
+
View in ruBee is just a plain html/erb/react file that can be rendered from the controller.
|
283
419
|
|
284
420
|
## Templates over erb
|
285
421
|
|
@@ -369,7 +505,7 @@ end
|
|
369
505
|
# app/controllers/api/user_controller.rb
|
370
506
|
class Api::UserController < Rubee::BaseController
|
371
507
|
def index
|
372
|
-
response_with object: User.all
|
508
|
+
response_with object: User.all, type: :json
|
373
509
|
end
|
374
510
|
end
|
375
511
|
```
|
@@ -379,7 +515,7 @@ end
|
|
379
515
|
// app/views/app.tsx
|
380
516
|
<Router>
|
381
517
|
<Routes>
|
382
|
-
<Route path="/users" element={<
|
518
|
+
<Route path="/users" element={<Users />} />
|
383
519
|
<Route path="*" element={<NotFound />} />
|
384
520
|
</Routes>
|
385
521
|
</Router>
|
@@ -508,6 +644,8 @@ end
|
|
508
644
|
```bash
|
509
645
|
rubee start # start the server
|
510
646
|
rubee start_dev # start the server in dev mode, which restart server on changes
|
647
|
+
rubee react prepare # install react dependencies
|
648
|
+
rubee react watch # dev mode for react, works together with start_dev
|
511
649
|
rubee stop # stop the server
|
512
650
|
rubee restart # restart the server
|
513
651
|
```
|
@@ -519,6 +657,7 @@ rubee generate get /apples # generate controller view, model and migration if se
|
|
519
657
|
|
520
658
|
## Migraiton commands
|
521
659
|
```bash
|
660
|
+
rubee db run:all # run all migrations
|
522
661
|
rubee db run:create_apples # where create_apples is the name of the migration file, located in /db folder
|
523
662
|
rubee db structure # generate migration file for the database structure
|
524
663
|
```
|
@@ -526,6 +665,7 @@ rubee db structure # generate migration file for the database structure
|
|
526
665
|
## Rubee console
|
527
666
|
```bash
|
528
667
|
rubee console # start the console
|
668
|
+
# you can reload the console by typing reload, so it will pick up latest changes
|
529
669
|
```
|
530
670
|
|
531
671
|
## Testing
|
@@ -533,6 +673,7 @@ rubee console # start the console
|
|
533
673
|
rubee test # run all tests
|
534
674
|
rubee test auth_tokenable_test.rb # run specific tests
|
535
675
|
```
|
676
|
+
|
536
677
|
If you want to run any ruBee command within a specific ENV make sure you added it before a command.
|
537
678
|
For instance if you want to run console in test environment you need to run the following command
|
538
679
|
|
@@ -616,30 +757,11 @@ TestAsyncRunnner.new.perform_async(options: {"email"=> "new@new.com", "password"
|
|
616
757
|
|
617
758
|
### Contributing
|
618
759
|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
```bash
|
625
|
-
git clone https://github.com/your-username/rubee.git
|
626
|
-
```
|
627
|
-
|
628
|
-
3. Create a new branch for your feature or bug fix:
|
629
|
-
```bash
|
630
|
-
git checkout -b feature/your-feature-name
|
631
|
-
```
|
632
|
-
|
633
|
-
4. Make your changes and commit them with descriptive messages:
|
634
|
-
```bash
|
635
|
-
git commit -m "Add feature: [brief description of feature]"
|
636
|
-
```
|
637
|
-
|
638
|
-
5. Push your changes to your fork:
|
639
|
-
```bash
|
640
|
-
git push origin feature/your-feature-name
|
641
|
-
```
|
642
|
-
|
643
|
-
6. Submit a pull request to the main branch of the original repository.
|
760
|
+
If you are interested in contributing to ruBee,
|
761
|
+
please read the [Contributing](https://github.com/nucleom42/rubee/blob/main/CONTRIBUTING.md) guide.
|
762
|
+
Also feel free to open an [issue](https://github.com/nucleom42/rubee/issues) if you apot one.
|
763
|
+
Have an idea or you wnat to discuss something?
|
764
|
+
Please open a [discussion](https://github.com/nucleom42/rubee/discussions)
|
644
765
|
|
645
|
-
|
766
|
+
## License
|
767
|
+
This project is released under the MIT License.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ru.Bee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Saltykov
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- lib/app/controllers/welcome_controller.rb
|
45
45
|
- lib/app/models/user.rb
|
46
46
|
- lib/app/views/app.tsx
|
47
|
+
- lib/app/views/apples_.erb
|
47
48
|
- lib/app/views/index.html
|
48
49
|
- lib/app/views/layout.erb
|
49
50
|
- lib/app/views/utils/redirectToBackend.tsx
|
@@ -243,6 +244,7 @@ files:
|
|
243
244
|
- lib/tests/example_models/comment.rb
|
244
245
|
- lib/tests/example_models/post.rb
|
245
246
|
- lib/tests/example_models/user.rb
|
247
|
+
- lib/tests/rubee_generator_test.rb
|
246
248
|
- lib/tests/rubeeapp_test.rb
|
247
249
|
- lib/tests/test.db
|
248
250
|
- lib/tests/test_helper.rb
|