potter 0.1.0 → 0.1.1
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/.rubocop.yml +2 -0
- data/.ruby-version +1 -0
- data/README.md +39 -14
- data/Rakefile +7 -3
- data/db/migrate/20230109071230_create_requests.rb +48 -0
- data/lib/potter/application_record.rb +10 -0
- data/lib/potter/ast/binary.rb +35 -0
- data/lib/potter/ast/dsl.rb +9 -0
- data/lib/potter/ast/node.rb +37 -0
- data/lib/potter/ast/proxy.rb +14 -0
- data/lib/potter/ast/unary.rb +21 -0
- data/lib/potter/ast/value.rb +13 -0
- data/lib/potter/ast/variable.rb +11 -0
- data/lib/potter/ast.rb +25 -0
- data/lib/potter/caching.rb +33 -0
- data/lib/potter/collections.rb +29 -0
- data/lib/potter/core_ext/active_record.rb +17 -0
- data/lib/potter/core_ext.rb +7 -0
- data/lib/potter/csv.rb +17 -0
- data/lib/potter/endpoints.rb +8 -0
- data/lib/potter/engine.rb +15 -0
- data/lib/potter/enum.rb +12 -15
- data/lib/potter/field.rb +34 -0
- data/lib/potter/flag.rb +1 -3
- data/lib/potter/{endpoint.rb → index.rb} +1 -1
- data/lib/potter/information_schema/base.rb +11 -0
- data/lib/potter/information_schema/index.rb +9 -0
- data/lib/potter/information_schema/table.rb +7 -0
- data/lib/potter/migrations.rb +42 -0
- data/lib/potter/model.rb +16 -0
- data/lib/potter/option_helpers.rb +40 -0
- data/lib/potter/record.rb +46 -0
- data/lib/potter/request.rb +92 -0
- data/lib/potter/response.rb +21 -0
- data/lib/potter/schema.rb +58 -0
- data/lib/potter/transformer.rb +15 -0
- data/lib/potter/transformers.rb +28 -0
- data/lib/potter/type.rb +26 -0
- data/lib/potter/types.rb +66 -0
- data/lib/potter/version.rb +1 -1
- data/lib/potter.rb +26 -3
- metadata +123 -11
- data/.rspec +0 -3
- data/lib/potter/resource.rb +0 -15
- data/sig/potter.rbs +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a23406491aa285780e485ed61cfe1fb6853cd975d6319bf9b3d940fff9202a5d
|
|
4
|
+
data.tar.gz: 7d25cad13739d71f78f8faabdbd39cc0f95ec317830a623d4137b13fda108f26
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: deab47dc584ba58d04dd04423aac1ca28f841693faaa7fde01613080f0f360c560d59421fa4703775139aa5008451acb1a3b206783a01ace9870040cd710d73c
|
|
7
|
+
data.tar.gz: 57f40e4752edda31d00b4f3cdc79178d2519f75b61965fe65cce0b65d50359ae1a0347e8c969dcfd6067b0e560cbbe9036fe52c8aa8ed50de2d1f6ea8927036c
|
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.1
|
data/README.md
CHANGED
|
@@ -1,39 +1,64 @@
|
|
|
1
|
-
# Potter
|
|
1
|
+
# 🏺 Potter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A gem for modeling anything: databases, CSVs, REST APIs, file systems.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It's meant to be simple and compact.
|
|
6
6
|
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
7
|
+
## 💎 Installation
|
|
10
8
|
|
|
11
9
|
Install the gem and add to the application's Gemfile by executing:
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
|
-
bundle add
|
|
12
|
+
bundle add potter
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
If bundler is not being used to manage dependencies, install the gem by
|
|
15
|
+
If bundler is not being used to manage dependencies, install the gem by
|
|
16
|
+
executing:
|
|
18
17
|
|
|
19
18
|
```bash
|
|
20
|
-
gem install
|
|
19
|
+
gem install potter
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
## Usage
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
Start by declaring your models:
|
|
25
|
+
|
|
26
|
+
```rb
|
|
27
|
+
class Base
|
|
28
|
+
include Potter::API
|
|
29
|
+
root "https://"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Transaction < Base
|
|
33
|
+
date :date
|
|
34
|
+
belongs_to :merchant
|
|
35
|
+
string :category
|
|
36
|
+
string :account
|
|
37
|
+
string :original_statement
|
|
38
|
+
string :notes
|
|
39
|
+
float :amount, scale: 2, note: "positive numbers for income and negative numbers for expenses"
|
|
40
|
+
string :tags
|
|
41
|
+
end
|
|
42
|
+
```
|
|
26
43
|
|
|
27
44
|
## Development
|
|
28
45
|
|
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
46
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
47
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
|
48
|
+
prompt that will allow you to experiment.
|
|
30
49
|
|
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
50
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
51
|
+
release a new version, update the version number in `version.rb`, and then run
|
|
52
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
|
53
|
+
git commits and the created tag, and push the `.gem` file to
|
|
54
|
+
[rubygems.org](https://rubygems.org).
|
|
32
55
|
|
|
33
56
|
## Contributing
|
|
34
57
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at
|
|
58
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
59
|
+
https://github.com/craft-concept/potter.
|
|
36
60
|
|
|
37
61
|
## License
|
|
38
62
|
|
|
39
|
-
The gem is available as open source under the terms of the
|
|
63
|
+
The gem is available as open source under the terms of the
|
|
64
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bundler/gem_tasks"
|
|
4
|
-
require "
|
|
4
|
+
require "minitest/test_task"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Minitest::TestTask.create
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
require "rubocop/rake_task"
|
|
9
|
+
|
|
10
|
+
RuboCop::RakeTask.new
|
|
11
|
+
|
|
12
|
+
task default: %i[test rubocop]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class CreateRequests < ActiveRecord::Migration[8.0]
|
|
2
|
+
def adapter
|
|
3
|
+
@adapter ||= ActiveRecord::Base.connection.adapter_name.downcase.then { ActiveSupport::StringInquirer.new _1 }
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def change
|
|
7
|
+
methods = %w[get post put patch delete head options trace connect]
|
|
8
|
+
states = %w[received queued sending responded failed]
|
|
9
|
+
|
|
10
|
+
unless adapter.sqlite?
|
|
11
|
+
create_enum :http_method, methods
|
|
12
|
+
create_enum :request_state, states
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
create_table :responses do |t|
|
|
16
|
+
t.string :type, null: false
|
|
17
|
+
t.integer :status, null: false
|
|
18
|
+
|
|
19
|
+
t.jsonb :headers
|
|
20
|
+
t.text :body
|
|
21
|
+
|
|
22
|
+
t.timestamps
|
|
23
|
+
|
|
24
|
+
t.check_constraint %(status BETWEEN 0 AND 999), name: "valid_status"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
create_table :requests do |t|
|
|
28
|
+
t.string :type, null: false, index: true
|
|
29
|
+
t.string :state, null: false
|
|
30
|
+
t.string :http_method, null: false
|
|
31
|
+
t.string :root, null: false, index: true
|
|
32
|
+
t.string :path, null: false, index: true
|
|
33
|
+
|
|
34
|
+
t.jsonb :params
|
|
35
|
+
t.jsonb :headers
|
|
36
|
+
t.text :body
|
|
37
|
+
|
|
38
|
+
t.references :response, foreign_key: true
|
|
39
|
+
|
|
40
|
+
t.timestamps
|
|
41
|
+
|
|
42
|
+
t.check_constraint %{http_method in (#{methods.map { "'#{_1}'" }.join(?,)})}, name: "http_method_enum"
|
|
43
|
+
t.check_constraint %{state in (#{states.map { "'#{_1}'" }.join(?,)})}, name: "state_enum"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
add_index :requests, %i[type path params http_method]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module AST
|
|
3
|
+
class Binary < Node
|
|
4
|
+
def initialize(left, right)
|
|
5
|
+
super()
|
|
6
|
+
@left = left
|
|
7
|
+
@right = right
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def walk
|
|
11
|
+
yield @left
|
|
12
|
+
yield @right
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def eval = @left.eval.public_send(symbol, @right.eval)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.define_binary(const, symbol, name = const.underscore, &)
|
|
19
|
+
define_node(const, Binary, symbol:, name:, &)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
define_binary :EqualTo, :==, :eq
|
|
23
|
+
define_binary :GreaterThan, :>, :gt
|
|
24
|
+
define_binary :GreaterOrEqual, :>=, :gte
|
|
25
|
+
define_binary :LessThan, :<, :lt
|
|
26
|
+
define_binary :LessOrEqual, :<=, :lte
|
|
27
|
+
|
|
28
|
+
define_binary :And, :&
|
|
29
|
+
define_binary :Or, :|
|
|
30
|
+
define_binary :Plus, :+
|
|
31
|
+
define_binary :Minus, :-
|
|
32
|
+
define_binary :Times, :*
|
|
33
|
+
define_binary :Range, :".."
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module AST
|
|
3
|
+
class Node
|
|
4
|
+
def symbol = SYMBOL
|
|
5
|
+
def name = NAME
|
|
6
|
+
|
|
7
|
+
def visit(visitor)
|
|
8
|
+
visitor.try(name, self)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def hash = [self.class, *instance_variable_values].hash
|
|
12
|
+
|
|
13
|
+
def eql?(o)
|
|
14
|
+
hash == o.hash
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.define_node(const, parent = Node, symbol: nil, name: const.underscore, &)
|
|
19
|
+
define_class(const, parent) do
|
|
20
|
+
const_set(:SYMBOL, symbol) if symbol
|
|
21
|
+
const_set(:NAME, name) if name
|
|
22
|
+
class_exec(&) if block_given?
|
|
23
|
+
klass = self
|
|
24
|
+
|
|
25
|
+
if name
|
|
26
|
+
Node.define_method(name) {|*args| Proxy klass.new(self, *args.map { Node _1 }) }
|
|
27
|
+
DSL.define_singleton_method(name) {|*args| klass.new(*args.map { Node _1 }) }
|
|
28
|
+
Proxy.define_method(name) {|*args| Proxy klass.new(@node, *args.map { Node _1 }) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if symbol
|
|
32
|
+
Proxy.define_method(symbol) {|*args| Proxy klass.new(@node, *args.map { Node _1 }) }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module AST
|
|
3
|
+
class Unary < Node
|
|
4
|
+
attr_reader :child
|
|
5
|
+
|
|
6
|
+
def initialize(child)
|
|
7
|
+
super()
|
|
8
|
+
@child = child
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def eval = public_send(symbol)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.define_unary(const, symbol)
|
|
15
|
+
define_node(const, Unary, symbol:)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
define_unary :Not, :!@
|
|
19
|
+
define_unary :Negate, :-@
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/potter/ast.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module AST
|
|
3
|
+
module_function
|
|
4
|
+
|
|
5
|
+
def Proxy(o)
|
|
6
|
+
o.is_a?(Proxy) ? o : Proxy.new(Node o)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def Value(o)
|
|
10
|
+
o.is_a?(Value) ? o : Value.new(o)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def Node(o)
|
|
14
|
+
o.is_a?(Node) ? o : Value.new(o)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def Variable(o)
|
|
18
|
+
o.is_a?(Variable) ? o : Variable.new(o)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def proxy(o) = Proxy(o)
|
|
22
|
+
def value(o) = Value(o)
|
|
23
|
+
def var(o) = Variable(o)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
concern :Caching do
|
|
3
|
+
# def full = cache(:full) { first + last }
|
|
4
|
+
def cache(name, &)
|
|
5
|
+
name = "@#{name}"
|
|
6
|
+
@_cached ||= []
|
|
7
|
+
@_cached << name
|
|
8
|
+
instance_variable_defined?(name) ?
|
|
9
|
+
instance_variable_get(name) :
|
|
10
|
+
instance_variable_set(name, instance_exec(&))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def clear_cache!
|
|
14
|
+
@_cached.each { remove_instance_variable(_1) }.clear
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class_methods do
|
|
18
|
+
# derive :full, -> { first + last }
|
|
19
|
+
def derive(name, proc = nil, &block)
|
|
20
|
+
proc ||= block
|
|
21
|
+
define_method(name) { cache(name, &proc) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# cache! def full = first + last
|
|
25
|
+
def cache!(name)
|
|
26
|
+
prepend Module.new.tap { _1.module_eval <<~RUBY }
|
|
27
|
+
def #{name} = cache(:#{name}) { super }
|
|
28
|
+
RUBY
|
|
29
|
+
name
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
class Collection < Array
|
|
3
|
+
def self.filter(name, block)
|
|
4
|
+
define_method(name) do |*args|
|
|
5
|
+
filter { _1.instance_exec(*args, &block) }
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Collections
|
|
11
|
+
extend ActiveSupport::Concern
|
|
12
|
+
|
|
13
|
+
class_methods do
|
|
14
|
+
def inherited(child)
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
child.class_eval <<-RUBY
|
|
18
|
+
class Collection < Collection
|
|
19
|
+
end
|
|
20
|
+
RUBY
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def filter(...) = Collection.filter(...)
|
|
24
|
+
def all(arr) = Collection.new(arr)
|
|
25
|
+
def if(cond, ...) = cond ? instance_exec(cond, ...) : self
|
|
26
|
+
def to(...) = map { _1.to(...) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
if defined? ::ActiveRecord::ConnectionAdapters::SQLite3
|
|
2
|
+
class ::ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition
|
|
3
|
+
unless method_defined? :jsonb
|
|
4
|
+
def jsonb(name)
|
|
5
|
+
blob name
|
|
6
|
+
check_constraint %{json_valid(#{name}, 6)}, name: "#{name}_valid_json"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
unless method_defined? :json
|
|
11
|
+
def json(name)
|
|
12
|
+
text name
|
|
13
|
+
check_constraint %{json_valid(#{name}, 6)}, name: "#{name}_valid_json"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/potter/csv.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "csv"
|
|
2
|
+
|
|
3
|
+
module Potter
|
|
4
|
+
module CSV
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
class Table < ::CSV::Table
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Row < ::CSV::Row
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_csv
|
|
14
|
+
Row.new(attributes.keys, attributes.values.map(&:presence))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "rails"
|
|
2
|
+
|
|
3
|
+
module Potter
|
|
4
|
+
class Engine < ::Rails::Engine
|
|
5
|
+
# config.autoload_paths += paths["lib"].to_a
|
|
6
|
+
|
|
7
|
+
initializer "potter.inflections" do
|
|
8
|
+
ActiveSupport::Inflector.inflections do |i|
|
|
9
|
+
i.acronym "AST"
|
|
10
|
+
i.acronym "DSL"
|
|
11
|
+
i.acronym "CSV"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/potter/enum.rb
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
module Potter
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
base.extend ClassMethods
|
|
5
|
-
end
|
|
2
|
+
concern :Enum do
|
|
3
|
+
include Transformers
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
def next_id
|
|
5
|
+
class_methods do
|
|
6
|
+
def next_id = @prev_id ? @prev_id + 1 : 0
|
|
9
7
|
|
|
10
8
|
def const(name, id = next_id, description: nil)
|
|
11
|
-
@
|
|
9
|
+
@prev_id = id
|
|
12
10
|
const_set(name, id)
|
|
13
11
|
end
|
|
14
12
|
|
|
@@ -22,15 +20,14 @@ module Potter
|
|
|
22
20
|
end
|
|
23
21
|
end
|
|
24
22
|
|
|
25
|
-
def self.of(type)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const_set(type.name.gsub("::", ""), Class.new(type) do
|
|
23
|
+
def self.of(type, &)
|
|
24
|
+
const_cache(type) do
|
|
25
|
+
parent = self
|
|
26
|
+
Class.new(type) do
|
|
30
27
|
include parent
|
|
31
|
-
|
|
28
|
+
class_exec(&) if block_given?
|
|
29
|
+
end
|
|
30
|
+
end
|
|
32
31
|
end
|
|
33
32
|
end
|
|
34
|
-
|
|
35
|
-
def self.Enum(type) = Enum.of(type)
|
|
36
33
|
end
|
data/lib/potter/field.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
class Field
|
|
3
|
+
include OptionHelpers
|
|
4
|
+
|
|
5
|
+
option :name, &:to_sym
|
|
6
|
+
option :type, -> { _1.is_a?(Class) ? _1.new : _1 }
|
|
7
|
+
option :default
|
|
8
|
+
|
|
9
|
+
option :enum
|
|
10
|
+
option :validates
|
|
11
|
+
option :normalizes
|
|
12
|
+
|
|
13
|
+
option :persist?, default: true
|
|
14
|
+
option :required?, default: -> { default.nil? }
|
|
15
|
+
option :declared?
|
|
16
|
+
option :description
|
|
17
|
+
|
|
18
|
+
def initialize(**)
|
|
19
|
+
assign_options!(**)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def optional? = !required?
|
|
23
|
+
|
|
24
|
+
def string? = type.type == :string
|
|
25
|
+
|
|
26
|
+
def record!(klass)
|
|
27
|
+
klass.attribute(name, type, default:)
|
|
28
|
+
klass.normalizes(name, **normalizes) if normalizes?
|
|
29
|
+
klass.validates(name, **validates) if validates?
|
|
30
|
+
klass.enum(name, enum) if enum?
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/potter/flag.rb
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module InformationSchema
|
|
3
|
+
class Base < ActiveRecord::Base
|
|
4
|
+
# include Potter::Record
|
|
5
|
+
self.abstract_class = true
|
|
6
|
+
self.table_name_prefix = "information_schema."
|
|
7
|
+
self.param_delimiter = "-"
|
|
8
|
+
self.inheritance_column = nil
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module Migrations
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
class Migration < ActiveRecord::Migration[8.0]
|
|
6
|
+
def initialize(model)
|
|
7
|
+
@model = model
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def column_names
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def create_or_change_table(name, **, &)
|
|
14
|
+
return create_table(name, **, &) unless table_exists?(name)
|
|
15
|
+
|
|
16
|
+
change_table(name, **) do |t|
|
|
17
|
+
t.remove_columns(*(t.columns.map(&:name) - %w[id]))
|
|
18
|
+
yield t
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def change
|
|
23
|
+
create_or_change_table(model.table_name) do |t|
|
|
24
|
+
model.fields.each do |f|
|
|
25
|
+
t.column f.name, f.type.to_sym, null: f.optional?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
included do
|
|
32
|
+
unless defined?(table_name)
|
|
33
|
+
def self.table_name = name.tableize
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class_methods do
|
|
38
|
+
def migrate! = migration.migrate(:up)
|
|
39
|
+
def migration = Migration.new(self)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
data/lib/potter/model.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Potter
|
|
2
|
+
module Model
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
include Schema
|
|
6
|
+
include Collections
|
|
7
|
+
include Transformers
|
|
8
|
+
include CSV
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
from Array do |values|
|
|
12
|
+
assign values.zip(fields.keys).to_h(&:reverse)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|