mechanical 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3e83b7b9b4b6d26db4fe167d18290da402ca50c191170b27d23d5c4ae48e351d
4
+ data.tar.gz: f0b2bc0445a468092dc78bd5f7e18eb0018da1c6bbb0605cf692dcf34043c8a5
5
+ SHA512:
6
+ metadata.gz: b774147facef799a28e82e668dea5381f3eeeccc4851e4d5df200c12e13f8ec73f94671c3dfd01b5700a29594bcfea412f08538fb995b70d66b0d1220c20f140
7
+ data.tar.gz: 7ad53cb8c2d72f09fe21b18932f3465187a058ff56bb620522941b4a49738313221fa221f4471994e158d8aa78fc058afd5a11e431b9efe8f1d10ab54d972915
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2019 Igor Kasyanchuk
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # Mechanical
2
+
3
+ Simple gem which allows to store multiple models in a single table in DB (Postgres only). It's using STI and Postgres JSONB data type.
4
+
5
+ The whole schema is defined in one initializer file, and new attributes could be easily added just by adding new attribute in that file. So you don't need to create a migration.
6
+
7
+ ## Usage
8
+
9
+ - add in the Gemfile `gem "mechanical"`
10
+ - execute `bundle install`
11
+ - execute `rails g mechanical initializer`
12
+ - execute `rake db:migrate`
13
+ - edit `config/initializers/mechanical.rb` and define your schema
14
+ - start app `rails s`
15
+ - you can use models `Mechanical::Model::MODEL_NAME` in you app like a regular model.
16
+
17
+ You need to define attribute and it's type (it's importan to check this gem: https://github.com/madeintandem/jsonb_accessor).
18
+ In addition you can specify relations, validations, add instance or class methods. Behavior is the same as with AR model.
19
+
20
+ ```ruby
21
+
22
+ Mechanical.setup do |config|
23
+
24
+ model "Account" do
25
+ field :name, type: :string
26
+ field :balance, type: :integer
27
+
28
+ has_many :posts
29
+
30
+ validates :name, presence: true
31
+ validates :balance, numericality: true
32
+ end
33
+
34
+ model "Post" do
35
+ field :title, type: :string
36
+ field :description, type: :text
37
+ field :published_on, type: :date
38
+ field :account_id, type: :integer
39
+ field :active, type: :boolean, default: true
40
+
41
+ belongs_to :account, optional: true
42
+
43
+ has_one_attached :file
44
+
45
+ validates :title, presence: true
46
+
47
+ scope :active, -> { jsonb_where(:mechanical_data, active: true) }
48
+
49
+ after_create :say_hello
50
+
51
+ add_methods do
52
+ def self.total_posts
53
+ self.count
54
+ end
55
+
56
+ def title_uppercase
57
+ title&.upcase
58
+ end
59
+
60
+ def say_hello
61
+ puts "HELLO FROM initializer #{self}"
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ ```
68
+
69
+ After Installation you can do the following:
70
+
71
+ ```ruby
72
+ post = Mechanical::Model::Post.create(title: "Hello world", description: "this is description")
73
+ post.persisted? # true
74
+
75
+ post.title # "Hello world"
76
+ post.description # "this is description"
77
+
78
+ # for querying use: https://github.com/madeintandem/jsonb_accessor
79
+
80
+ Mechanical::Model::Post.create(title: "ABC", description: "this is description")
81
+ Mechanical::Model::Post.create(title: "TRE", description: "this is second description")
82
+ Mechanical::Model::Account.create(name: "XYZ", balance: 100)
83
+ Mechanical::Model::Account.create(name: "MTR", balance: 200)
84
+ Mechanical::Model::Post.jsonb_where(:mechanical_data, { title: 'ABC' }).count # 1
85
+ Mechanical::Model::Account.mechanical_data_where(balance: { greater_than_or_equal_to: 150 }).count # 1
86
+ Mechanical::Model::Account.mechanical_data_where(balance: 10..250).count # 2
87
+ ```
88
+
89
+ If you are building form and want to use this model you can do it same way as using regular model:
90
+
91
+ Example of very simple controller:
92
+
93
+ ```ruby
94
+ def index
95
+ @post = Mechanical::Model::Post.new
96
+ end
97
+
98
+ def submit_post
99
+ @post = Mechanical::Model::Post.new(params.require(:post).permit!)
100
+ @post.user = User.first
101
+ @post.save
102
+ if @post.save
103
+ redirect_to root_path
104
+ else
105
+ @posts = Mechanical::Model::Post.all
106
+ render :index
107
+ end
108
+ end
109
+ ```
110
+
111
+ View:
112
+
113
+ ```erb
114
+
115
+ <%= simple_form_for @post, url: submit_post_url, html: { novalidate: true } do |f| %>
116
+ <%= f.error_messages %>
117
+ <%= f.association :account %>
118
+ <%= f.input :title %>
119
+ <%= f.input :description %>
120
+ <%= f.input :published_on %>
121
+ <%= f.input :file %>
122
+ <%= f.input :active %>
123
+ <br/>
124
+ <%= f.submit %>
125
+ <% end %>
126
+
127
+ ```
128
+
129
+ As you can see it supports active storage.
130
+
131
+
132
+ ## Installation
133
+ Add this line to your application's Gemfile:
134
+
135
+ ```ruby
136
+ gem 'mechanical'
137
+ ```
138
+
139
+ And then execute:
140
+ ```bash
141
+ $ bundle
142
+ ```
143
+ ## Contributing
144
+
145
+ You are welcome to contribute.
146
+
147
+ ## License
148
+
149
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Mechanical'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/mechanical .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ module Mechanical
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Mechanical
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Mechanical
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Mechanical
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Mechanical
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Mechanical
2
+ class MechanicalStore < ApplicationRecord
3
+ end
4
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Mechanical</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "mechanical/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -0,0 +1,47 @@
1
+ if Object.const_defined?('Mechanical')
2
+
3
+ Mechanical.setup do |config|
4
+ # model "Account" do
5
+ # field :name, type: :string
6
+ # field :balance, type: :integer
7
+
8
+ # has_many :posts
9
+
10
+ # validates :name, presence: true
11
+ # validates :balance, numericality: true
12
+ # end
13
+
14
+ # model "Post" do
15
+ # field :title, type: :string
16
+ # field :description, type: :text
17
+ # field :published_on, type: :date
18
+ # field :account_id, type: :integer
19
+ # field :active, type: :boolean, default: true
20
+
21
+ # belongs_to :account, optional: true
22
+
23
+ # has_one_attached :file
24
+
25
+ # validates :title, presence: true
26
+
27
+ # scope :active, -> { jsonb_where(:mechanical_data, active: true) }
28
+
29
+ # after_create :say_hello
30
+
31
+ # add_methods do
32
+ # def self.total_posts
33
+ # self.count
34
+ # end
35
+
36
+ # def title_uppercase
37
+ # title&.upcase
38
+ # end
39
+
40
+ # def say_hello
41
+ # puts "HELLO FROM initializer #{self}"
42
+ # end
43
+ # end
44
+ # end
45
+ end
46
+
47
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Mechanical::Engine.routes.draw do
2
+ end
@@ -0,0 +1,17 @@
1
+ class CreateMechanicalMechanicalStores < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :mechanical_mechanical_stores do |t|
4
+ t.integer :mechanicalable_id
5
+ t.string :mechanicalable_type
6
+
7
+ t.integer :mechanical_user_id
8
+ t.string :mechanical_model_type
9
+ t.jsonb :mechanical_data, default: {}
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :mechanical_mechanical_stores, :mechanical_user_id
14
+ add_index :mechanical_mechanical_stores, :mechanical_model_type
15
+ add_index :mechanical_mechanical_stores, [:mechanicalable_id, :mechanicalable_type], name: :____mmidtype
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Generate configuration file.
3
+
4
+ Example:
5
+ rails generate mechanical initializer
6
+
7
+ This will create:
8
+ - config/mechanical.rb
9
+ - new mechanical migration
@@ -0,0 +1,7 @@
1
+ class MechanicalGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+ def copy_initializer
4
+ template 'mechanical.rb', 'config/initializers/mechanical.rb'
5
+ template '20190912181342_create_mechanical_mechanical_stores.rb', "db/migrate/#{Time.now.strftime('%Y%m%d%H%M%S')}_create_mechanical_mechanical_stores.rb"
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ class CreateMechanicalMechanicalStores < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :mechanical_mechanical_stores do |t|
4
+ t.integer :mechanicalable_id
5
+ t.string :mechanicalable_type
6
+
7
+ t.integer :mechanical_user_id
8
+ t.string :mechanical_model_type
9
+ t.jsonb :mechanical_data, default: {}
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :mechanical_mechanical_stores, :mechanical_user_id
14
+ add_index :mechanical_mechanical_stores, :mechanical_model_type
15
+ add_index :mechanical_mechanical_stores, [:mechanicalable_id, :mechanicalable_type], name: :____mmidtype
16
+ end
17
+ end
@@ -0,0 +1,47 @@
1
+ if Object.const_defined?('Mechanical')
2
+
3
+ Mechanical.setup do |config|
4
+ # model "Account" do
5
+ # field :name, type: :string
6
+ # field :balance, type: :integer
7
+
8
+ # has_many :posts
9
+
10
+ # validates :name, presence: true
11
+ # validates :balance, numericality: true
12
+ # end
13
+
14
+ # model "Post" do
15
+ # field :title, type: :string
16
+ # field :description, type: :text
17
+ # field :published_on, type: :date
18
+ # field :account_id, type: :integer
19
+ # field :active, type: :boolean, default: true
20
+
21
+ # belongs_to :account, optional: true
22
+
23
+ # has_one_attached :file
24
+
25
+ # validates :title, presence: true
26
+
27
+ # scope :active, -> { jsonb_where(:mechanical_data, active: true) }
28
+
29
+ # after_create :say_hello
30
+
31
+ # add_methods do
32
+ # def self.total_posts
33
+ # self.count
34
+ # end
35
+
36
+ # def title_uppercase
37
+ # title&.upcase
38
+ # end
39
+
40
+ # def say_hello
41
+ # puts "HELLO FROM initializer #{self}"
42
+ # end
43
+ # end
44
+ # end
45
+ end
46
+
47
+ end
data/lib/mechanical.rb ADDED
@@ -0,0 +1,95 @@
1
+ require "mechanical/engine"
2
+ require 'simple_form'
3
+ require 'ostruct'
4
+ require 'jsonb_accessor'
5
+
6
+ module Mechanical
7
+ class Schema
8
+ attr_reader :models
9
+
10
+ def initialize
11
+ @models = {}
12
+ end
13
+
14
+ def model(name, &block)
15
+ model = Model.new(name)
16
+ model.instance_eval(&block)
17
+ @models[name] = model
18
+ end
19
+
20
+ def [](name)
21
+ @models[name]
22
+ end
23
+ end
24
+
25
+ class Field
26
+ attr_reader :name, :options, :model
27
+
28
+ def initialize(model, name, options = {})
29
+ @model = model
30
+ @name = name
31
+ @options = options
32
+ model.model.jsonb_accessor :mechanical_data, name.to_sym => [options[:type].presence || String, default: options[:default]]
33
+ end
34
+
35
+ def validates(options = {})
36
+ model.model.send :validates, name.to_sym, options
37
+ end
38
+
39
+ end
40
+
41
+ class Model
42
+ attr_reader :fields, :name, :options, :model
43
+
44
+ delegate_missing_to :model
45
+
46
+ def initialize(name, options = {})
47
+ @name = name
48
+ @fields = {}
49
+ @options = options
50
+ @model = eval %{
51
+ class #{name} < ApplicationRecord
52
+ self.table_name = "mechanical_mechanical_stores"
53
+ def self.model_name; ActiveModel::Name.new(self, nil, "#{name.downcase}"); end
54
+
55
+ default_scope -> { where(mechanical_model_type: name) }
56
+
57
+ belongs_to :user, optional: true, foreign_key: :mechanical_user_id
58
+ belongs_to :mechanicalable, polymorphic: true, optional: true
59
+ end
60
+ #{name}
61
+ }
62
+
63
+ puts "Mechanical init model => #{@model}"
64
+ end
65
+
66
+ def field(name, options = {}, &block)
67
+ @fields[name] = Field.new(self, name, options)
68
+ end
69
+
70
+ def add_methods(&block)
71
+ @model.class_eval(&block)
72
+ end
73
+ end
74
+
75
+ mattr_accessor :schema
76
+ @@schema = Schema.new
77
+
78
+ def self.setup(&block)
79
+ setup_active_storage
80
+ schema.instance_eval(&block)
81
+ end
82
+
83
+ def self.[](name)
84
+ schema[name]
85
+ end
86
+
87
+ private
88
+
89
+ def self.setup_active_storage
90
+ ApplicationRecord.send :include, ActiveStorage::Reflection::ActiveRecordExtensions
91
+ ApplicationRecord.send :include, ActiveStorage::Attached::Model
92
+ ::ActiveRecord::Reflection.singleton_class.prepend(::ActiveStorage::Reflection::ReflectionExtension)
93
+ end
94
+
95
+ end
@@ -0,0 +1,5 @@
1
+ module Mechanical
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Mechanical
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Mechanical
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :mechanical do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mechanical
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Igor Kasyanchuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: simple_form
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jsonb_accessor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: image_processing
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mini_magick
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Dynamic forms, schema, everything stored in DB
112
+ email:
113
+ - igorkasyanchuk@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - MIT-LICENSE
119
+ - README.md
120
+ - Rakefile
121
+ - app/assets/config/mechanical_manifest.js
122
+ - app/assets/stylesheets/mechanical/application.css
123
+ - app/controllers/mechanical/application_controller.rb
124
+ - app/helpers/mechanical/application_helper.rb
125
+ - app/jobs/mechanical/application_job.rb
126
+ - app/mailers/mechanical/application_mailer.rb
127
+ - app/models/mechanical/application_record.rb
128
+ - app/models/mechanical/mechanical_store.rb
129
+ - app/views/layouts/mechanical/application.html.erb
130
+ - config/initializers/mechanical.rb
131
+ - config/routes.rb
132
+ - db/migrate/20190912181342_create_mechanical_mechanical_stores.rb
133
+ - lib/generators/USAGE
134
+ - lib/generators/mechanical_generator.rb
135
+ - lib/generators/templates/20190912181342_create_mechanical_mechanical_stores.rb
136
+ - lib/generators/templates/mechanical.rb
137
+ - lib/mechanical.rb
138
+ - lib/mechanical/engine.rb
139
+ - lib/mechanical/version.rb
140
+ - lib/tasks/mechanical_tasks.rake
141
+ homepage: https://github.com/igorkasyanchuk/mechanical
142
+ licenses:
143
+ - MIT
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.7.7
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: Forms / DB / Model
165
+ test_files: []