ez 0.6.0 → 0.6.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/README.md +10 -14
- data/lib/ez/domain_modeler.rb +26 -23
- data/lib/ez/schema_modifier.rb +110 -108
- data/lib/ez/version.rb +1 -1
- metadata +14 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 279ca85b40bfbf58aebba60d1a527a2da47f6daf
|
4
|
+
data.tar.gz: b2da5c258394b5642d32d9fcd8d4991f50bd23d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccd1d6ac56b6d1e76552a68ee8e49029f0a1357782a08b9163a3a3bd513329dc7bec366192c537e1047cca6991aac59055ffd42880c485429472424df6423c48
|
7
|
+
data.tar.gz: 695590626c05bdc3a55d4d8f7fab4017c434b4f8584309584332b64f9ea4179f6c15dba81f43348a8647584d5edf6553138f371c2fd70de01318ffa0b602efab
|
data/README.md
CHANGED
@@ -1,20 +1,16 @@
|
|
1
1
|
# EZ
|
2
2
|
|
3
|
-
For educational purposes only. Makes Rails a bit more beginner-friendly.
|
3
|
+
* For educational purposes only. Makes Rails a bit more beginner-friendly.
|
4
|
+
* Depends on Hirb ~> 0.7.1
|
5
|
+
* Patches the Rails dispatcher to avoid writing controllers for simple views by adding route support for `get "url" => "folder/file"`
|
6
|
+
* Enables instant modeling without migrations via `models.yml` and `rake ez:tables`
|
7
|
+
* Quick JSON API calls with `EZ.from_api(url)`, returns parsed Ruby hash (or array, etc.)
|
8
|
+
* Built-in `EZ.weather(location)` for classroom demo of API, to get quick hash and avoid JSON explanation. Relies on http://openweathermap.org
|
9
|
+
* Adds controller and view helpers `current_user`, `user_signed_in?`, `sign_in_as`, and `sign_out` to avoid cookies/session hash details
|
10
|
+
* Adds ActiveRecord::Base `read` method to provide symmetry with `create`, `update`, and `delete`
|
11
|
+
* Adds ActiveRecord::Base `sample` method to choose a random row
|
12
|
+
* Patches Hirb to allow table output for `ActiveRecord::Relation` lists (i.e. result of `.all`, `.where` or `.read(:col => value)` but normal output for single ActiveRecord objects, like the result of `.find_by(:id => id)` or `read(id)`
|
4
13
|
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'ez'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install ez
|
18
14
|
|
19
15
|
|
20
16
|
|
data/lib/ez/domain_modeler.rb
CHANGED
@@ -1,35 +1,38 @@
|
|
1
1
|
require_relative 'schema_modifier'
|
2
2
|
|
3
|
-
|
3
|
+
module EZ
|
4
|
+
class DomainModeler
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def initialize
|
7
|
+
load_model_specs
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def self.update_tables
|
11
|
+
self.new.update_tables
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def update_tables
|
15
|
+
SchemaModifier.migrate(@spec)
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
18
|
+
def load_model_specs
|
19
|
+
@spec = YAML.load_file('db/models.yml')
|
20
|
+
@spec ||= {}
|
21
|
+
|
22
|
+
@spec.each do |model, columns|
|
23
|
+
@spec[model] = []
|
24
|
+
columns.each do |column|
|
25
|
+
if column.is_a?(String) || column.is_a?(Symbol)
|
26
|
+
@spec[model] << { column.to_s => 'string' }
|
27
|
+
elsif column.is_a?(Hash) && column.keys.count == 1
|
28
|
+
@spec[model] << { column.keys.first.to_s => column.values.first.to_s }
|
29
|
+
else
|
30
|
+
raise "Bad syntax."
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
35
|
+
|
33
36
|
end
|
34
37
|
|
35
38
|
end
|
data/lib/ez/schema_modifier.rb
CHANGED
@@ -1,144 +1,146 @@
|
|
1
|
-
|
1
|
+
module EZ
|
2
|
+
class SchemaModifier
|
2
3
|
|
3
|
-
|
4
|
+
attr_reader :db, :spec
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def initialize(model_spec)
|
7
|
+
@spec = model_spec
|
8
|
+
connect_to_database
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def self.migrate(model_spec)
|
12
|
+
self.new(model_spec).migrate
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
def migrate
|
16
|
+
@changed = false
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
add_missing_schema
|
19
|
+
remove_dead_schema
|
20
|
+
update_schema_version
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
puts "Everything is up-to-date." unless @changed
|
23
|
+
end
|
23
24
|
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def tables
|
27
|
+
@tables ||= (db.tables - ['schema_migrations'])
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
def missing_model?(model_name)
|
31
|
+
missing_table?(model_name.tableize)
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def missing_table?(name)
|
35
|
+
tables.index(name).nil?
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
def add_missing_schema
|
39
|
+
@spec.each do |model_name, columns|
|
40
|
+
if missing_model?(model_name)
|
41
|
+
add_model(model_name, columns)
|
42
|
+
else
|
43
|
+
add_missing_columns(model_name, columns)
|
44
|
+
end
|
43
45
|
end
|
44
46
|
end
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
def display_change(message)
|
49
|
+
puts message
|
50
|
+
@changed = true
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
53
|
+
def add_missing_columns(model_name, columns)
|
54
|
+
table_name = model_name.tableize
|
55
|
+
columns.each do |column|
|
56
|
+
col_name = column.keys.first
|
57
|
+
col_type = column[col_name]
|
58
|
+
if db.column_exists?(table_name, col_name.to_sym)
|
59
|
+
unless db.column_exists?(table_name, col_name.to_sym, col_type.to_sym)
|
60
|
+
display_change "Changing column type for '#{col_name}' to #{col_type}"
|
61
|
+
db.change_column(table_name, col_name.to_sym, col_type.to_sym)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
display_change "Adding new column '#{col_name}' as #{col_type} for model #{model_name}"
|
65
|
+
db.add_column(table_name, col_name.to_sym, col_type.to_sym)
|
61
66
|
end
|
62
|
-
else
|
63
|
-
display_change "Adding new column '#{col_name}' as #{col_type} for model #{model_name}"
|
64
|
-
db.add_column(table_name, col_name.to_sym, col_type.to_sym)
|
65
67
|
end
|
66
68
|
end
|
67
|
-
end
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
def add_model(model_name, columns)
|
71
|
+
table_name = model_name.tableize
|
72
|
+
display_change "Defining model #{model_name}..."
|
73
|
+
ActiveRecord::Schema.define do
|
74
|
+
create_table table_name do |t|
|
75
|
+
columns.each do |column|
|
76
|
+
name = column.keys.first
|
77
|
+
col_type = column[name]
|
78
|
+
t.send(col_type, name)
|
79
|
+
end
|
80
|
+
# t.timestamps
|
78
81
|
end
|
79
|
-
# t.timestamps
|
80
82
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
filename = "app/models/#{model_name.underscore}.rb"
|
84
|
+
unless File.exists?(filename)
|
85
|
+
display_change "Creating new model file: #{filename}"
|
86
|
+
File.open(filename, "w") do |f|
|
87
|
+
f.puts "class #{model_name} < ActiveRecord::Base"
|
88
|
+
f.puts "end"
|
89
|
+
end
|
88
90
|
end
|
89
91
|
end
|
90
|
-
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
def remove_dead_schema
|
94
|
+
remove_dead_tables
|
95
|
+
remove_dead_columns
|
96
|
+
end
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
98
|
+
def remove_dead_columns
|
99
|
+
tables.each do |table_name|
|
100
|
+
model_name = table_name.classify.to_s
|
101
|
+
if @spec.has_key?(model_name)
|
102
|
+
columns = db.columns(table_name).map { |column| column.name.to_sym } - [:id, :created_at, :updated_at]
|
103
|
+
spec_columns = @spec[model_name].map do |column_entry|
|
104
|
+
column_entry.is_a?(Hash) ? column_entry.keys.first.to_sym : column_entry.to_sym
|
105
|
+
end
|
106
|
+
dead_columns = columns - spec_columns
|
107
|
+
if dead_columns.any?
|
108
|
+
display_change "Removing unused columns: #{dead_columns.to_sentence} for model #{model_name}"
|
109
|
+
db.remove_columns(table_name, *dead_columns)
|
110
|
+
end
|
109
111
|
end
|
110
112
|
end
|
111
113
|
end
|
112
|
-
end
|
113
114
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
def update_schema_version
|
116
|
+
@db.initialize_schema_migrations_table
|
117
|
+
@db.assume_migrated_upto_version(Time.now.strftime("%Y%m%d%H%M%S"))
|
118
|
+
end
|
118
119
|
|
119
|
-
|
120
|
-
|
121
|
-
|
120
|
+
def remove_dead_tables
|
121
|
+
tables_we_need = @spec.keys.map { |model| model.tableize }
|
122
|
+
dead_tables = tables - tables_we_need
|
122
123
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
124
|
+
dead_tables.each do |table_name|
|
125
|
+
model_name = table_name.classify
|
126
|
+
display_change "Dropping model #{model_name}"
|
127
|
+
db.drop_table(table_name)
|
128
|
+
display_change "Deleting file #{model_name.underscore}.rb"
|
129
|
+
File.unlink "app/models/#{model_name.underscore}.rb" rescue nil
|
130
|
+
end
|
129
131
|
end
|
130
|
-
end
|
131
132
|
|
132
|
-
|
133
|
-
|
134
|
-
|
133
|
+
def silence_migration_output
|
134
|
+
ActiveRecord::Migration.verbose = false
|
135
|
+
end
|
135
136
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
137
|
+
def connect_to_database
|
138
|
+
ActiveRecord::Base.establish_connection({
|
139
|
+
adapter: 'sqlite3',
|
140
|
+
database: "db/development.sqlite3",
|
141
|
+
})
|
142
|
+
@db = ActiveRecord::Base.connection
|
143
|
+
end
|
143
144
|
|
145
|
+
end
|
144
146
|
end
|
data/lib/ez/version.rb
CHANGED
metadata
CHANGED
@@ -1,61 +1,61 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ez
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Cohen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hirb
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.7.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.7.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '10.0'
|
48
|
-
- -
|
48
|
+
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: 10.0.0
|
51
51
|
type: :development
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
|
-
- - ~>
|
55
|
+
- - "~>"
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '10.0'
|
58
|
-
- -
|
58
|
+
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 10.0.0
|
61
61
|
description: Gem for easier Rails development.
|
@@ -65,7 +65,7 @@ executables: []
|
|
65
65
|
extensions: []
|
66
66
|
extra_rdoc_files: []
|
67
67
|
files:
|
68
|
-
- .gitignore
|
68
|
+
- ".gitignore"
|
69
69
|
- Gemfile
|
70
70
|
- LICENSE.txt
|
71
71
|
- README.md
|
@@ -122,17 +122,17 @@ require_paths:
|
|
122
122
|
- lib
|
123
123
|
required_ruby_version: !ruby/object:Gem::Requirement
|
124
124
|
requirements:
|
125
|
-
- -
|
125
|
+
- - ">="
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: '0'
|
128
128
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
129
|
requirements:
|
130
|
-
- -
|
130
|
+
- - ">="
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: '0'
|
133
133
|
requirements: []
|
134
134
|
rubyforge_project:
|
135
|
-
rubygems_version: 2.2.
|
135
|
+
rubygems_version: 2.2.2
|
136
136
|
signing_key:
|
137
137
|
specification_version: 4
|
138
138
|
summary: For educational purposes only.
|