spectifly-sequel 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +55 -0
- data/README.md +99 -0
- data/Rakefile +13 -0
- data/lib/spectifly/sequel/builder.rb +30 -0
- data/lib/spectifly/sequel/config.rb +53 -0
- data/lib/spectifly/sequel/erb/create_association_tables.erb +4 -0
- data/lib/spectifly/sequel/erb/create_table.erb +9 -0
- data/lib/spectifly/sequel/erb/field/many_to_many_association.erb +9 -0
- data/lib/spectifly/sequel/erb/field/multiple_value_simple_type_field.erb +8 -0
- data/lib/spectifly/sequel/erb/field/single_value_simple_type_field.erb +1 -0
- data/lib/spectifly/sequel/erb/new_migration.erb +6 -0
- data/lib/spectifly/sequel/field.rb +22 -0
- data/lib/spectifly/sequel/field_for_migration.rb +45 -0
- data/lib/spectifly/sequel/migration_generator.rb +39 -0
- data/lib/spectifly/sequel/model.rb +47 -0
- data/lib/spectifly/sequel/relationship/base.rb +14 -0
- data/lib/spectifly/sequel/relationship/belongs_to.rb +17 -0
- data/lib/spectifly/sequel/relationship/belongs_to_many.rb +8 -0
- data/lib/spectifly/sequel/relationship/has_a.rb +8 -0
- data/lib/spectifly/sequel/relationship/has_and_belongs_to_many.rb +21 -0
- data/lib/spectifly/sequel/relationship/has_many.rb +12 -0
- data/lib/spectifly/sequel/relationship/has_one.rb +8 -0
- data/lib/spectifly/sequel/relationship/one_to_one.rb +17 -0
- data/lib/spectifly/sequel/tasks.rb +2 -0
- data/lib/spectifly/sequel/types.rb +22 -0
- data/lib/spectifly/sequel/version.rb +5 -0
- data/lib/spectifly/sequel.rb +24 -0
- data/lib/tasks/spectifly-sequel.rake +12 -0
- data/spec/expectations/animal_multiple_value_string_field.migration +8 -0
- data/spec/expectations/cow.migration +19 -0
- data/spec/expectations/group.migration +10 -0
- data/spec/expectations/individual.migration +21 -0
- data/spec/fixtures/config_file.yml +7 -0
- data/spec/fixtures/cow.entity +34 -0
- data/spec/fixtures/group.entity +17 -0
- data/spec/fixtures/individual.entity +37 -0
- data/spec/fixtures/invalid_config_file.yml +2 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/spectifly/sequel/builder_spec.rb +27 -0
- data/spec/spectifly/sequel/config_spec.rb +60 -0
- data/spec/spectifly/sequel/field_spec.rb +61 -0
- data/spec/spectifly/sequel/migration_generator_spec.rb +45 -0
- data/spec/spectifly/sequel/model_spec.rb +17 -0
- data/spec/spectifly/sequel/types_spec.rb +10 -0
- data/spec/tmp/migrations/README +2 -0
- data/spectifly-sequel.gemspec +30 -0
- metadata +253 -0
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p392
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
spectifly-sequel (0.0.1)
|
5
|
+
activesupport
|
6
|
+
sequel
|
7
|
+
spectifly
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (3.2.12)
|
13
|
+
i18n (~> 0.6)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
builder (3.2.0)
|
16
|
+
columnize (0.3.6)
|
17
|
+
debugger (1.5.0)
|
18
|
+
columnize (>= 0.3.1)
|
19
|
+
debugger-linecache (~> 1.2.0)
|
20
|
+
debugger-ruby_core_source (~> 1.2.0)
|
21
|
+
debugger-linecache (1.2.0)
|
22
|
+
debugger-ruby_core_source (1.2.0)
|
23
|
+
diff-lcs (1.2.4)
|
24
|
+
i18n (0.6.4)
|
25
|
+
json (1.8.0)
|
26
|
+
multi_json (1.7.2)
|
27
|
+
rake (10.0.4)
|
28
|
+
rspec (2.13.0)
|
29
|
+
rspec-core (~> 2.13.0)
|
30
|
+
rspec-expectations (~> 2.13.0)
|
31
|
+
rspec-mocks (~> 2.13.0)
|
32
|
+
rspec-core (2.13.1)
|
33
|
+
rspec-expectations (2.13.0)
|
34
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
35
|
+
rspec-mocks (2.13.1)
|
36
|
+
sequel (3.47.0)
|
37
|
+
simplecov (0.7.1)
|
38
|
+
multi_json (~> 1.0)
|
39
|
+
simplecov-html (~> 0.7.1)
|
40
|
+
simplecov-html (0.7.1)
|
41
|
+
spectifly (0.0.1)
|
42
|
+
builder
|
43
|
+
json
|
44
|
+
rake
|
45
|
+
|
46
|
+
PLATFORMS
|
47
|
+
ruby
|
48
|
+
|
49
|
+
DEPENDENCIES
|
50
|
+
bundler (~> 1.3)
|
51
|
+
debugger
|
52
|
+
rake
|
53
|
+
rspec
|
54
|
+
simplecov
|
55
|
+
spectifly-sequel!
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Spectifly Sequel Add-on
|
2
|
+
|
3
|
+
An add-on to Spectifly, which uses entity definitions based on YAML, to
|
4
|
+
create Sequel migrations and model files
|
5
|
+
|
6
|
+
## Caveat
|
7
|
+
|
8
|
+
This is very much a work in progress and any migrations generated from
|
9
|
+
the gem should be carefully scrutinized for correctness prior to
|
10
|
+
applying them to your database. Right now, the gem's output is only
|
11
|
+
tested with Postgres and only creates new tables but does not update
|
12
|
+
schema that already exists (though ideally, that would be a future
|
13
|
+
feature).
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'spectifly-sequel'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Once on rubygems, you'll also be able to install it yourself as:
|
26
|
+
|
27
|
+
$ gem install spectifly-sequel
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
The Spectifly markup language is a subset of YAML. Only one root node is allowed
|
32
|
+
per file (since a single `.entity` file represents a single business entity),
|
33
|
+
and there are other restrictions, as well as additional features, which we'll
|
34
|
+
discuss here.
|
35
|
+
|
36
|
+
Given a Spectifly entity defintion `lib/entities/widget.entity`:
|
37
|
+
|
38
|
+
```YAML
|
39
|
+
Widget:
|
40
|
+
Description: A widget produced by WidgetCo
|
41
|
+
Fields:
|
42
|
+
Name*:
|
43
|
+
Description: Display name of widget
|
44
|
+
|
45
|
+
Created At:
|
46
|
+
Description: When the widget was built
|
47
|
+
Type: DateTime
|
48
|
+
|
49
|
+
Awesome?:
|
50
|
+
Description: Whether or not the widget is awesome
|
51
|
+
```
|
52
|
+
When `rake spectifly:sequel:generate['widget']` is run, the following
|
53
|
+
migration `db/migrate/001_create_widgets.rb` will be created.
|
54
|
+
```ruby
|
55
|
+
Sequel.migration do
|
56
|
+
change do
|
57
|
+
create_table(:widgets) do
|
58
|
+
primary_key :id
|
59
|
+
String :name, :null => false
|
60
|
+
DateTime :created_at
|
61
|
+
Boolean :awesome
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
## Configuration
|
68
|
+
|
69
|
+
Spectifly Sequel does not make any assumptions about where you put your
|
70
|
+
entity definitions or migrations. In order for the gem to run
|
71
|
+
correctly, you'll need to specifly the path to a YAML file or set the
|
72
|
+
config directly via a hash.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
# to set via YAML file
|
76
|
+
Spectifly::Sequel.configure_with PATH_TO_CONFIG_YAML
|
77
|
+
|
78
|
+
# to set via hash
|
79
|
+
Spectifly::Sequel.configure {
|
80
|
+
'migration_path' => PATH_TO_MIGRATION_DIRECTORY
|
81
|
+
'entity_definition_path' => PATH_TO_ENTITY_DEFINITION_DIRECTORY
|
82
|
+
}
|
83
|
+
```
|
84
|
+
|
85
|
+
The YAML configuration file should look something like this:
|
86
|
+
```yaml
|
87
|
+
Sequel:
|
88
|
+
Spectifly:
|
89
|
+
migration_path: PATH_TO_MIGRATION_DIRECTORY
|
90
|
+
entity_definition_path: PATH_TO_ENTITY_DEFINITION_DIRECTORY
|
91
|
+
```
|
92
|
+
|
93
|
+
## Contributing
|
94
|
+
|
95
|
+
1. Fork it
|
96
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
97
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
98
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
99
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
Bundler::GemHelper.install_tasks
|
4
|
+
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
task :default => [:spec]
|
8
|
+
|
9
|
+
require 'sequel'
|
10
|
+
require 'spectifly'
|
11
|
+
require 'spectifly/base'
|
12
|
+
require 'spectifly/sequel'
|
13
|
+
require 'spectifly/sequel/tasks'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'erb'
|
2
|
+
module Spectifly
|
3
|
+
module Sequel
|
4
|
+
class Builder < Spectifly::Base::Builder
|
5
|
+
attr_accessor :entities, :model
|
6
|
+
def initialize(entity, options = {})
|
7
|
+
super(entity, options)
|
8
|
+
@entities = Spectifly::Entity.from_directory(File.dirname(entity.path))
|
9
|
+
@model = Spectifly::Sequel::Model.new(entity, fields)
|
10
|
+
end
|
11
|
+
|
12
|
+
def field_class
|
13
|
+
Spectifly::Sequel::Field
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
template_path = File.join(*File.dirname(__FILE__), 'erb', 'new_migration.erb')
|
18
|
+
render template_path
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def render path
|
23
|
+
content = File.read(File.expand_path(path))
|
24
|
+
t = ERB.new(content, nil, '-') # third param lets us use trim
|
25
|
+
t.filename = File.expand_path(path)
|
26
|
+
t.result(binding)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
@valid_config_keys = [:migration_path, :entity_definition_path, :migration_version_type]
|
4
|
+
@config = {}
|
5
|
+
|
6
|
+
def self.configure_with(path_to_config_file)
|
7
|
+
begin
|
8
|
+
config = YAML.load_file(path_to_config_file)['Spectifly']['Sequel']
|
9
|
+
rescue NoMethodError
|
10
|
+
raise config_instructions
|
11
|
+
end
|
12
|
+
configure(config)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configure(opts)
|
16
|
+
opts.each {|k,v| @config[k.to_sym] = v if @valid_config_keys.include? k.to_sym}
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.migration_path
|
20
|
+
@config[:migration_path] or raise missing_configuration('migration_path')
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.entity_definition_path
|
24
|
+
@config[:entity_definition_path] or raise missing_configuration('entity_definition_path')
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.migration_version_type
|
28
|
+
type = @config[:migration_version_type].to_s
|
29
|
+
if %w(Timestamp Integer).include? type
|
30
|
+
type
|
31
|
+
else
|
32
|
+
'Timestamp'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def self.config_instructions
|
38
|
+
<<-INSTRUCTIONS
|
39
|
+
Please format config files in the following manner:
|
40
|
+
``- begin YAML
|
41
|
+
Sequel:
|
42
|
+
Spectifly:
|
43
|
+
migration_path: PATH_TO_MIGRATION_DIRECTORY
|
44
|
+
entity_definition_path: PATH_TO_ENTITY_DEFINITION_DIRECTORY
|
45
|
+
``- end YAML
|
46
|
+
INSTRUCTIONS
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.missing_configuration(config_param)
|
50
|
+
"Spectify::Sequel is not configured properly. \"#{config_param}\" must be set via YAML or a hash."
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
create_table(:<%= @model.table_name %>) do
|
2
|
+
primary_key :id
|
3
|
+
<% @model.single_value_fields.each do |field| -%>
|
4
|
+
<%= field.for_new_migration(@model, @entities) %>
|
5
|
+
<% end -%>
|
6
|
+
<% @model.foreign_keys.each do |key| -%>
|
7
|
+
foreign_key :<%= key.field_name %>, :<%= key.table_name %><%= ", :unique => true" if key.unique -%><%= ", :null => false" if key.required %>
|
8
|
+
<% end -%>
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% @model.has_and_belong_to_many.each do |relationship| -%>
|
2
|
+
|
3
|
+
create_table(:<%= relationship.many_to_many_table_name %>) do
|
4
|
+
foreign_key :<%= @model.name_as_foreign_key %>, :<%= @model.table_name %>, :null => false
|
5
|
+
foreign_key :<%= relationship.field_name %>, :<%= relationship.table_name %>, :null => false
|
6
|
+
end
|
7
|
+
|
8
|
+
add_index [:<%=@model.name_as_foreign_key -%>, :<%= relationship.field_name -%>], :<%= relationship.many_to_many_table_name -%>, :unique => true
|
9
|
+
<% end -%>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
|
2
|
+
create_table(:<%= @model.table_name %>_<%= @field.name %>) do
|
3
|
+
primary_key :id
|
4
|
+
foreign_key :<%= @model.name_as_foreign_key %>, :<%= @model.table_name %>, :null => false
|
5
|
+
<%= @field.type %> :name, :null => false
|
6
|
+
end
|
7
|
+
|
8
|
+
add_index [:<%=@model.name_as_foreign_key %>, :name], :<%= @model.table_name %>_<%= @field.name %>, :unique => true
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @field_type %> :<%= @field_name %><%= ", #{@options.join(', ')}" if !@options.empty? -%>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
class Field < Spectifly::Base::Field
|
4
|
+
def type
|
5
|
+
field_type = super
|
6
|
+
if base_type = Spectifly::Sequel::Types::Extended[field_type]
|
7
|
+
field_type = base_type['Type']
|
8
|
+
end
|
9
|
+
|
10
|
+
Spectifly::Support.camelize(field_type)
|
11
|
+
end
|
12
|
+
|
13
|
+
# The entity_references param is the list of entity namesthat the caller
|
14
|
+
# knows about. This lets us figure out whether the field should actually
|
15
|
+
# be the id of the entity/model being referenced by the field type.
|
16
|
+
def for_new_migration(model, entity_references = [])
|
17
|
+
@field_for_migration = Spectifly::Sequel::FieldForMigration.new(self, model, entity_references)
|
18
|
+
@field_for_migration.render
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
class FieldForMigration
|
4
|
+
attr_accessor :field_name, :field_type, :options, :model
|
5
|
+
|
6
|
+
def initialize(field, model, entity_references)
|
7
|
+
@field = field
|
8
|
+
@field_name = field.name
|
9
|
+
@field_type = field.type
|
10
|
+
@model = model
|
11
|
+
@options = retrieve_options(field)
|
12
|
+
end
|
13
|
+
|
14
|
+
def retrieve_options(field)
|
15
|
+
options = []
|
16
|
+
options << ':null => false' if field.required?
|
17
|
+
options << ':unique => true' if field.unique?
|
18
|
+
options
|
19
|
+
end
|
20
|
+
|
21
|
+
def render
|
22
|
+
template = if single_value_simple_type?
|
23
|
+
'single_value_simple_type_field'
|
24
|
+
elsif multiple_value_simple_type?
|
25
|
+
'multiple_value_simple_type_field'
|
26
|
+
end
|
27
|
+
return if template.nil?
|
28
|
+
|
29
|
+
path = File.expand_path(File.join(*File.dirname(__FILE__), 'erb', 'field', "#{template}.erb"))
|
30
|
+
content = File.read(path)
|
31
|
+
t = ERB.new(content, nil, '-')
|
32
|
+
t.filename = path
|
33
|
+
t.result(binding)
|
34
|
+
end
|
35
|
+
|
36
|
+
def single_value_simple_type?
|
37
|
+
@model_for_field.nil? && !@field.multiple?
|
38
|
+
end
|
39
|
+
|
40
|
+
def multiple_value_simple_type?
|
41
|
+
@model_for_field.nil? && @field.multiple?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
class MigrationGenerator
|
4
|
+
def initialize(entity, migration_path=nil, entity_path=nil, migration_version_type=nil)
|
5
|
+
@migration_path = File.expand_path(migration_path || Spectifly::Sequel.migration_path)
|
6
|
+
@entity_definition_path = File.expand_path(entity_path || Spectifly::Sequel.entity_definition_path)
|
7
|
+
@migration_version_type = migration_version_type || Spectifly::Sequel.migration_version_type
|
8
|
+
@builder = Spectifly::Sequel::Builder.from_path(File.join(@entity_definition_path, entity + '.entity'))
|
9
|
+
end
|
10
|
+
|
11
|
+
def run!
|
12
|
+
migration_output = @builder.build
|
13
|
+
File.open(File.join(@migration_path, migration_name), 'w') { |f| f.write(migration_output) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def migration_name
|
17
|
+
'%s_create_%s.rb' % [next_migration_version, @builder.model.table_name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def next_migration_version
|
21
|
+
if @migration_version_type == 'Timestamp'
|
22
|
+
DateTime.now.strftime('%Y%m%d%H%M%S')
|
23
|
+
else
|
24
|
+
last_migration = 0
|
25
|
+
length = 3
|
26
|
+
Dir.glob("#{@migration_path}/*.rb") do |rb_file|
|
27
|
+
migration = File.basename(rb_file).split('_').first
|
28
|
+
if migration.to_i > last_migration
|
29
|
+
last_migration = migration.to_i
|
30
|
+
length = migration.length
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
(last_migration + 1).to_s.rjust(length, "0")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
class Model
|
4
|
+
attr_accessor :table_name, :display_name, :model_name,
|
5
|
+
:single_value_fields, :multiple_value_fields,
|
6
|
+
:has_and_belong_to_many, :name_as_foreign_key,
|
7
|
+
:foreign_keys
|
8
|
+
|
9
|
+
def initialize(entity, fields)
|
10
|
+
@display_name = entity.root
|
11
|
+
@model_name = Spectifly::Support.camelize(display_name)
|
12
|
+
@table_name = Spectifly::Support.tokenize(ActiveSupport::Inflector.pluralize(display_name))
|
13
|
+
|
14
|
+
@single_value_fields = fields.select { |f| !f.multiple? }
|
15
|
+
@multiple_value_fields = fields.select { |f| f.multiple? }
|
16
|
+
|
17
|
+
@name_as_foreign_key = Spectifly::Support.tokenize(display_name) + '_id'
|
18
|
+
get_relationships(entity)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_relationships(entity)
|
22
|
+
@foreign_keys = []
|
23
|
+
@has_and_belong_to_many = []
|
24
|
+
entity.relationships.each do |relationship_type, rels|
|
25
|
+
camelized_type = Spectifly::Support.camelize(relationship_type)
|
26
|
+
rels.each do |name, attributes|
|
27
|
+
if %w(BelongsTo HasOne HasA).include? camelized_type
|
28
|
+
relation = create_relation(camelized_type, name, attributes, entity)
|
29
|
+
@foreign_keys << relation
|
30
|
+
elsif %(BelongsToMany HasAndBelongsToMany HasMany).include?(camelized_type)
|
31
|
+
relation = create_relation(camelized_type, name, attributes, entity)
|
32
|
+
# as long as the has_many has a coinciding belongs_to_many and the association table makes sense...
|
33
|
+
if relation.multiple_related_entity? && !(@name_as_foreign_key == relation.field_name && @table_name == relation.table_name)
|
34
|
+
@has_and_belong_to_many << relation
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_relation(type, name, attributes, entity)
|
42
|
+
relationship_class = ActiveSupport::Inflector.constantize('Spectifly::Sequel::Relationship::%s' % type)
|
43
|
+
relation = relationship_class.new(name, attributes, entity)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
module Relationship
|
4
|
+
class Base
|
5
|
+
attr_accessor :entity, :related_entity
|
6
|
+
|
7
|
+
def initialize(name, attributes, related_entity)
|
8
|
+
@entity = Spectifly::Base::EntityNode.new(name, attributes)
|
9
|
+
@related_entity = related_entity
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
module Relationship
|
4
|
+
class BelongsTo < Base
|
5
|
+
attr_accessor :field_name, :table_name, :required, :unique
|
6
|
+
|
7
|
+
def initialize(name, attributes, related_entity)
|
8
|
+
super
|
9
|
+
@table_name = Spectifly::Support.tokenize(ActiveSupport::Inflector.pluralize(@entity.type))
|
10
|
+
@field_name = Spectifly::Support.tokenize(@entity.name) + '_id'
|
11
|
+
@required = @entity.required?
|
12
|
+
@unique = @entity.unique?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
module Relationship
|
4
|
+
class HasAndBelongsToMany < Base
|
5
|
+
attr_accessor :field_name, :table_name, :many_to_many_table_name
|
6
|
+
|
7
|
+
def initialize(name, attributes, related_entity)
|
8
|
+
super
|
9
|
+
related_table_name = Spectifly::Support.tokenize(ActiveSupport::Inflector.pluralize(related_entity.root))
|
10
|
+
@field_name = Spectifly::Support.tokenize(ActiveSupport::Inflector.singularize(@entity.name)) + '_id'
|
11
|
+
@table_name = Spectifly::Support.tokenize(ActiveSupport::Inflector.pluralize(@entity.type))
|
12
|
+
@many_to_many_table_name = [related_table_name, Spectifly::Support.tokenize(@entity.name)].sort.join('_')
|
13
|
+
end
|
14
|
+
|
15
|
+
def multiple_related_entity?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
module Relationship
|
4
|
+
class HasMany < HasAndBelongsToMany
|
5
|
+
def multiple_related_entity?
|
6
|
+
related_entity = Spectifly::Entity.from_directory(File.dirname(@related_entity.path))[@entity.type]
|
7
|
+
(related_entity.relationships['Belongs To Many'] || {}).any? { |rel_name, attrs| attrs['Type'] == @related_entity.root }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Spectifly
|
2
|
+
module Sequel
|
3
|
+
module Relationship
|
4
|
+
class OneToOne < Base
|
5
|
+
attr_accessor :field_name, :table_name, :required, :unique
|
6
|
+
|
7
|
+
def initialize(name, attributes, related_entity)
|
8
|
+
super
|
9
|
+
@table_name = Spectifly::Support.tokenize(ActiveSupport::Inflector.pluralize(@entity.type))
|
10
|
+
@field_name = Spectifly::Support.tokenize(@entity.name) + '_id'
|
11
|
+
@required = @entity.required?
|
12
|
+
@unique = @entity.unique?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
module Spectifly
|
3
|
+
module Sequel
|
4
|
+
class Types
|
5
|
+
Native = ::Sequel::Schema::CreateTableGenerator::GENERIC_TYPES.map { |type| type.to_s }
|
6
|
+
|
7
|
+
Extended = {
|
8
|
+
'percent' => {
|
9
|
+
'Type' => 'Numeric',
|
10
|
+
},
|
11
|
+
'currency' => {
|
12
|
+
'Type' => 'Numeric',
|
13
|
+
},
|
14
|
+
'year' => {
|
15
|
+
'Type' => 'Integer'
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
All = Native + Extended.map { |k, v| v['Type'] }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support/inflector/methods'
|
2
|
+
require 'spectifly'
|
3
|
+
require_relative 'sequel/config'
|
4
|
+
require_relative 'sequel/types'
|
5
|
+
require_relative 'sequel/model'
|
6
|
+
require_relative 'sequel/tasks'
|
7
|
+
require_relative 'sequel/relationship/base'
|
8
|
+
require_relative 'sequel/relationship/one_to_one'
|
9
|
+
require_relative 'sequel/relationship/belongs_to'
|
10
|
+
require_relative 'sequel/relationship/has_and_belongs_to_many'
|
11
|
+
require_relative 'sequel/relationship/belongs_to_many'
|
12
|
+
require_relative 'sequel/relationship/has_a'
|
13
|
+
require_relative 'sequel/relationship/has_one'
|
14
|
+
require_relative 'sequel/relationship/has_many'
|
15
|
+
require_relative 'sequel/field'
|
16
|
+
require_relative 'sequel/field_for_migration'
|
17
|
+
require_relative 'sequel/builder'
|
18
|
+
require_relative 'sequel/migration_generator'
|
19
|
+
require_relative 'sequel/version'
|
20
|
+
|
21
|
+
module Spectifly
|
22
|
+
module Sequel
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spectifly/sequel'
|
3
|
+
|
4
|
+
namespace 'spectifly' do
|
5
|
+
namespace 'sequel' do
|
6
|
+
desc 'Generate migration from entity definition file'
|
7
|
+
task :generate, [:entity_type] do |t, args|
|
8
|
+
Spectifly::Sequel.configure_with File.join(Dir.pwd, 'config', 'spectifly.yml')
|
9
|
+
Spectifly::Sequel::MigrationGenerator.new(args[:entity_type]).run!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|