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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f60bb8f17e35447c9cedd635d719a6b0d988486f9fe04668e0e07763a99cb740
4
- data.tar.gz: a56dcac76060f5bb9ec71959ef4d21fa7c3e9b858eb6088e873e3ba50e4684f0
3
+ metadata.gz: 0bf3fb103ba0d1e81af5f77b6ec12395bf0d9701dac0f67fab585cd2c87ebb38
4
+ data.tar.gz: 3d8356ee2225e738b94ce1b9338597b1bd49ca103f3e55df3261c7cb2f45b71c
5
5
  SHA512:
6
- metadata.gz: 03be1679bf032a1f292b4490a41286eb02f3a56984cf8dc7281715db53f880dc3ded8feb445ae41a22d60c2a4c3a5e47f8b8fe1be5f4c8188d26e57d403b746e
7
- data.tar.gz: 0ffa4e0cc8c436d2ce7ac784c92465333d12ebaa67172f08bcfc55e59dd6f29472aa70211a3c2b766c234ef089b51d1c47a130cc6c0c8ab35e896f659b1ba43d
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 File.join(Rubee::APP_ROOT, Rubee::LIB, 'app/views', 'index.html')
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, attributes, controller_name, action_name, **options)
216
+ def initialize(model_name, model_attributes, controller_name, action_name, **options)
217
217
  @model_name = model_name&.downcase
218
- @attributes = attributes
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 #{@attributes.map { |hash| ":#{hash[:name]}" }.join(', ')}
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
- 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
- }
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
@@ -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** Supported out of the box as a rubee view
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
- **ruBee** is using **Sqlite** as a default database. However you can pick up any other database supported by sequel gem.
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
- ## Create API contract and generate files from the routes
71
- 1. Add the routes to the routes.rb
68
+ ## Run the tests
72
69
  ```bash
73
- Rubee::Router.draw do |router|
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
- 2. genrate the files
88
- ```bash
89
- rubee generate get /apples
90
- ```
91
- 3. This will generate the following files
92
- ```bash
93
- ./app/controllers/apples_controller.rb # Controller with respective action
94
- ./app/models/apple.rb # Model that acts as ORM
95
- ./app/views/apples_index.erb # ERB view that is rendered by the controller right away
96
- ./db/create_items.rb # Database migration file needed for creating repsective table
97
- ```
98
- 4. Fill those files with the logic you need and run the server again!
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
- # in memory example
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={<Home />} />
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
- You are more than welcome to contribute to ruBee! To do so, please follow these steps:
620
-
621
- 1. Fork the repository by clicking the "Fork" button on the GitHub page.
622
-
623
- 2. Clone your fork:
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
- Let's make it shine even brighter!
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.0
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