spectifly-sequel 0.0.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.
- 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
|