mechanical 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []