shaf 0.7.1 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff5e3dc188a76a89a8b4443f3996e61486a6836b91978b0fae3cd5adb9e88296
4
- data.tar.gz: bbc13631ee68eeef0b86edd050602b625f001d070a3f704d3915b20ce015149e
3
+ metadata.gz: d9eb918ad2c43059ac408c1bd9d85e41e3c3914510a22ed08628ffc9984f1777
4
+ data.tar.gz: b7f1593151ad34cac7e0edde0841cde9dc3494f72d1292835814870b733681f8
5
5
  SHA512:
6
- metadata.gz: 65f87a51936f02635793ecb730d211563950c3953cd08b967094d2586b2b1f8bf725e87b6f100b3a61c45c36070fd3a69f2e6b0916185f9c935ae333b10bd89f
7
- data.tar.gz: ad411b694fe94039f6577d7e934944054657572feeef49abc4557dec4b726a3e9cd71940ae66cfbe52c6de390cecedfa80d107207e1016d50e5dedda2c524297
6
+ metadata.gz: 6b76e3caf4a9e844b7c40e97e56ef37b332db9b3466efb585ad786dbbd7461f22b3b9088c758df2313eef3fcd2832ef880419f4b322ce63063861f4db8ed72fb
7
+ data.tar.gz: 6818d566651548ff3e8244e87fc98263b4ba52cffb728618a4c0c8822e20a9f043633ee9b4d6e1c8bbd443354f3de1c753f1ecc7255631cf5036c46560565d9e
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -4,14 +4,14 @@ module Shaf
4
4
  class App
5
5
  class << self
6
6
  def instance
7
- create_instance unless defined?(@instance)
8
- @instance
7
+ @instance ||= create_instance
9
8
  end
10
9
 
11
10
  def create_instance
12
- @instance = Sinatra.new
13
- @instance.set :port, Settings.port || 3000
14
- @instance.use Shaf::Middleware::RequestId
11
+ Sinatra.new.tap do |instance|
12
+ instance.set :port, Settings.port || 3000
13
+ instance.use Shaf::Middleware::RequestId
14
+ end
15
15
  end
16
16
 
17
17
  def use(middleware)
@@ -40,7 +40,7 @@ module Shaf
40
40
 
41
41
  def erb(content)
42
42
  return ERB.new(content, 0, '%-<>').result if RUBY_VERSION < "2.6.0"
43
- ERB.new(content, 0, trim_mode: '%-<>').result
43
+ ERB.new(content, trim_mode: '-<>').result
44
44
  end
45
45
 
46
46
  def copy_templates
@@ -11,8 +11,8 @@ module Shaf
11
11
  end
12
12
  end
13
13
 
14
- def resource_uris_for(*args)
15
- result = CreateUriMethods.new(*args).call
14
+ def resource_uris_for(name, **kwargs)
15
+ result = CreateUriMethods.new(name, **kwargs).call
16
16
  UriHelperMethods.add_path_helpers(self, result)
17
17
 
18
18
  include UriHelper unless self < UriHelper
@@ -94,36 +94,41 @@ module Shaf
94
94
  # edit_book_uri_template => /books/:id/edit
95
95
  #
96
96
  class CreateUriMethods
97
-
98
- def initialize(name, base: nil, plural_name: nil)
97
+ def initialize(name, base: nil, plural_name: nil, only: nil, except: nil)
99
98
  @name = name.to_s
100
99
  @base = base&.sub(%r(/\Z), '') || ''
101
100
  @plural_name = plural_name&.to_s || Utils::pluralize(name.to_s)
101
+ @only = only
102
+ @except = except
102
103
  @added_path_methods = []
103
104
  end
104
105
 
105
106
  def call
106
107
  if plural_name == name
107
- register_resource_uri_by_arg
108
+ register_resource_helper_by_arg
108
109
  else
109
- register_resources_uri
110
- register_resource_uri
110
+ register_collection_helper
111
+ register_resource_helper
111
112
  end
112
- register_new_resource_uri
113
- register_edit_resource_uri
113
+ register_new_resource_helper
114
+ register_edit_resource_helper
114
115
  @added_path_methods
115
116
  end
116
117
 
117
118
  private
118
119
 
119
- attr_reader :name, :base, :plural_name
120
+ attr_reader :name, :base, :plural_name, :only, :except
121
+
122
+ def register_collection_helper
123
+ return if skip? :collection
120
124
 
121
- def register_resources_uri
122
125
  template_uri = "#{base}/#{plural_name}".freeze
123
126
  register(plural_name, template_uri)
124
127
  end
125
128
 
126
- def register_resource_uri
129
+ def register_resource_helper
130
+ return if skip? :resource
131
+
127
132
  template_uri = "#{base}/#{plural_name}/:id".freeze
128
133
  register(name, template_uri)
129
134
  end
@@ -131,7 +136,10 @@ module Shaf
131
136
  # If a resource has the same singular and plural names, then this method
132
137
  # should be used. It will return the resource uri when a resource is given
133
138
  # as argument and the resources uri when no arguments are provided.
134
- def register_resource_uri_by_arg
139
+ def register_resource_helper_by_arg
140
+ return register_resource_helper if skip? :collection
141
+ return register_collection_helper if skip? :new
142
+
135
143
  resource_template_uri = "#{base}/#{plural_name}/:id"
136
144
  collection_template_uri = "#{base}/#{plural_name}"
137
145
 
@@ -139,12 +147,16 @@ module Shaf
139
147
  @added_path_methods << builder.call
140
148
  end
141
149
 
142
- def register_new_resource_uri
150
+ def register_new_resource_helper
151
+ return if skip? :new
152
+
143
153
  template_uri = "#{base}/#{name}/form".freeze
144
154
  register("new_#{name}", template_uri)
145
155
  end
146
156
 
147
- def register_edit_resource_uri
157
+ def register_edit_resource_helper
158
+ return if skip? :edit
159
+
148
160
  template_uri = "#{base}/#{plural_name}/:id/edit".freeze
149
161
  register("edit_#{name}", template_uri)
150
162
  end
@@ -153,6 +165,16 @@ module Shaf
153
165
  builder = MethodBuilder.new(name, template_uri)
154
166
  @added_path_methods << builder.call
155
167
  end
168
+
169
+ def skip? name
170
+ if only
171
+ !Array(only).include? name
172
+ elsif except
173
+ Array(except).include? name
174
+ else
175
+ false
176
+ end
177
+ end
156
178
  end
157
179
 
158
180
  class MethodBuilder
@@ -4,7 +4,7 @@ module Shaf
4
4
  module Formable
5
5
  class Builder
6
6
  InstanceAccessorType = Struct.new(:prefill?)
7
- DELEGATES = %i[title name action method type fields].freeze
7
+ DELEGATES = %i[title name action method type submit fields].freeze
8
8
 
9
9
  attr_reader :forms
10
10
 
@@ -42,7 +42,7 @@ module Shaf
42
42
 
43
43
  DELEGATES.each do |name|
44
44
  define_method(name) do |arg|
45
- form.send("#{name}=".to_sym, arg)
45
+ form.send(:"#{name}=", arg)
46
46
  end
47
47
  end
48
48
 
@@ -9,9 +9,10 @@ module Shaf
9
9
  class FormHasNoResourceError < Shaf::Error; end
10
10
 
11
11
  DEFAULT_TYPE = 'application/json'.freeze
12
+ DEFAULT_SUBMIT = 'save'.freeze
12
13
 
13
14
  attr_accessor :resource
14
- immutable_accessor :title, :name, :href, :type, :self_link
15
+ immutable_accessor :title, :name, :href, :type, :submit, :self_link
15
16
  immutable_reader :fields, :action
16
17
 
17
18
  def initialize(params = {})
@@ -20,6 +21,7 @@ module Shaf
20
21
  @name = params[:name]&.to_sym || name_from(@action)
21
22
  @method = params[:method] ||= http_method_from(@action)
22
23
  @type = params[:type] || DEFAULT_TYPE
24
+ @submit = params[:submit] || DEFAULT_SUBMIT
23
25
  @fields = (params[:fields] || {}).map do |name, args|
24
26
  Field.new(name, args)
25
27
  end
@@ -47,7 +47,7 @@ module Shaf
47
47
  b = OpenStruct.new(locals).instance_eval { binding }
48
48
 
49
49
  return ERB.new(str, 0, '%-<>').result(b) if RUBY_VERSION < "2.6.0"
50
- ERB.new(str, 0, trim_mode: '%-<>').result(b)
50
+ ERB.new(str,trim_mode: '-<>').result(b)
51
51
  rescue SystemCallError => e
52
52
  puts "Failed to render template #{template}: #{e.message}"
53
53
  raise
@@ -1,37 +1,10 @@
1
1
  require 'date'
2
+ require 'shaf/generator/migration/types'
2
3
 
3
4
  module Shaf
4
5
  module Generator
5
6
  module Migration
6
7
  class Base
7
- DB_COL_FORMAT_STRINGS = {
8
- integer: ['Integer :%s', 'add_column :%s, Integer'],
9
- varchar: ['String %s', 'add_column :%s, String'],
10
- string: ['String :%s', 'add_column :%s, String'],
11
- text: ['String :%s, text: true', 'add_column :%s, String, text: true'],
12
- blob: ['File :%s', 'add_column :%s, File'],
13
- bigint: ['Bignum :%s', 'add_column :%s, Bignum'],
14
- double: ['Float :%s', 'add_column :%s, Float'],
15
- numeric: ['BigDecimal :%s', 'add_column :%s, BigDecimal'],
16
- date: ['Date :%s', 'add_column :%s, Date'],
17
- timestamp: ['DateTime :%s', 'add_column :%s, DateTime'],
18
- time: ['Time :%s', 'add_column :%s, Time'],
19
- bool: ['TrueClass :%s', 'add_column :%s, TrueClass'],
20
- boolean: ['TrueClass :%s', 'add_column :%s, TrueClass'],
21
- index: ['index :%s, unique: true', 'add_index :%s'],
22
- }
23
-
24
- COMPLEX_DB_TYPES = [
25
- {
26
- pattern: /\Aforeign_key\((\w+)\)/,
27
- strings: ['foreign_key :%s, :\1', 'add_foreign_key :%s, :\1'],
28
- validator: ->(type, match) {
29
- break if ::DB.table_exists?(match[1])
30
- ["Foreign key table '#{match[1]}' does not exist!"]
31
- }
32
- }
33
- ]
34
-
35
8
  attr_reader :args, :options
36
9
 
37
10
  class << self
@@ -68,9 +41,10 @@ module Shaf
68
41
  end
69
42
 
70
43
  def column_def(str, create: true)
71
- name, type = str.split(':')
72
- format_string = db_format_string(type, create ? 0 : 1)
73
- format format_string, name.downcase
44
+ _, col_type = str.split(':')
45
+ type = Type.find(col_type)
46
+ raise "No supported DB column types for: #{col_type}" unless type
47
+ type.build(str, create: create, alter: !create)
74
48
  end
75
49
 
76
50
  def target(name)
@@ -91,32 +65,6 @@ module Shaf
91
65
  end
92
66
  end
93
67
 
94
- def db_format_string(type, range = 0..1)
95
- type ||= :string
96
- result = DB_COL_FORMAT_STRINGS[type.to_sym]
97
- result ||= regexp_db_format_string(type)
98
- raise "Column type '#{type}' not supported" unless result
99
- result[range]
100
- end
101
-
102
- def regexp_db_format_string(type)
103
- COMPLEX_DB_TYPES.find do |complex_type|
104
- match = complex_type[:pattern].match(type) or next
105
- validator = complex_type[:validator]
106
- errors = validator&.call(type, match)
107
- raise "Failed to process '#{type}': #{errors&.join(', ')}" unless Array(errors).empty?
108
-
109
- break complex_type[:strings].map { |s| replace_backreferences(match, s) }
110
- end
111
- end
112
-
113
- def replace_backreferences(match, str)
114
- groups = match.size
115
- (1...groups).inject(str) do |s, i|
116
- s.gsub("\\#{i}", match[i])
117
- end
118
- end
119
-
120
68
  def render
121
69
  <<~RUBY
122
70
  Sequel.migration do
@@ -0,0 +1,88 @@
1
+ module Shaf
2
+ module Generator
3
+ module Migration
4
+ class Type
5
+ attr_reader :name, :create_template, :alter_template, :validator
6
+
7
+ class << self
8
+ def add(name, **kwargs)
9
+ new(name, **kwargs).tap do |type|
10
+ types[type.name] = type
11
+ end
12
+ end
13
+
14
+ def find(str)
15
+ name, _ = str.to_s.split(',', 2)
16
+ types[name.to_sym]
17
+ end
18
+
19
+ private
20
+
21
+ def types
22
+ @types ||= {}
23
+ end
24
+
25
+ def clear
26
+ @types.clear if defined? @types
27
+ end
28
+ end
29
+
30
+ def initialize(str, create_template:, alter_template:, validator: nil)
31
+ @name = str.downcase.to_sym
32
+ @create_template = create_template
33
+ @alter_template = alter_template
34
+ @validator = validator
35
+ end
36
+
37
+ def build(str, create: false, alter: false)
38
+ args = parse_args(str)
39
+ validate!(*args)
40
+
41
+ if create && !alter
42
+ build_create_string(*args)
43
+ elsif alter && !create
44
+ build_alter_string(*args)
45
+ else
46
+ [
47
+ build_create_string(*args),
48
+ build_alter_string(*args)
49
+ ]
50
+ end
51
+ end
52
+
53
+ def parse_args(str)
54
+ name, col_type = str.to_s.downcase.split(':')
55
+ _, *args = col_type&.split(',')
56
+ args.unshift name
57
+ end
58
+
59
+ def build_create_string(*args)
60
+ format create_template, *args
61
+ rescue ArgumentError
62
+ raise Command::ArgumentError,
63
+ "Wrong number of arguments for type #{name} with string " \
64
+ "template '#{create_template}. Given: #{args}"
65
+ end
66
+
67
+ def build_alter_string(*args)
68
+ format alter_template, *args
69
+ rescue ArgumentError
70
+ raise Command::ArgumentError,
71
+ "Wrong number of arguments for type #{name} with string " \
72
+ "template '#{alter_template}. Given: #{args}"
73
+ end
74
+
75
+ def validate!(*args)
76
+ errors = Array(validator&.call(name, *args))
77
+ return if errors.empty?
78
+
79
+ raise "Failed to process '#{name}': #{errors&.join(', ')}"
80
+ end
81
+
82
+ def ==(other)
83
+ name == other.name
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,31 @@
1
+ require 'shaf/generator/migration/type'
2
+
3
+ module Shaf
4
+ module Generator
5
+ module Migration
6
+ Type.add :integer, create_template: 'Integer :%s', alter_template: 'add_column :%s, Integer'
7
+ Type.add :varchar, create_template: 'String %s', alter_template: 'add_column :%s, String'
8
+ Type.add :string, create_template: 'String :%s', alter_template: 'add_column :%s, String'
9
+ Type.add :text, create_template: 'String :%s, text: true', alter_template: 'add_column :%s, String, text: true'
10
+ Type.add :blob, create_template: 'File :%s', alter_template: 'add_column :%s, File'
11
+ Type.add :bigint, create_template: 'Bignum :%s', alter_template: 'add_column :%s, Bignum'
12
+ Type.add :double, create_template: 'Float :%s', alter_template: 'add_column :%s, Float'
13
+ Type.add :numeric, create_template: 'BigDecimal :%s', alter_template: 'add_column :%s, BigDecimal'
14
+ Type.add :date, create_template: 'Date :%s', alter_template: 'add_column :%s, Date'
15
+ Type.add :timestamp, create_template: 'DateTime :%s', alter_template: 'add_column :%s, DateTime'
16
+ Type.add :time, create_template: 'Time :%s', alter_template: 'add_column :%s, Time'
17
+ Type.add :bool, create_template: 'TrueClass :%s', alter_template: 'add_column :%s, TrueClass'
18
+ Type.add :boolean, create_template: 'TrueClass :%s', alter_template: 'add_column :%s, TrueClass'
19
+ Type.add :index, create_template: 'index :%s, unique: true', alter_template: 'add_index :%s'
20
+
21
+ Type.add :foreign_key,
22
+ create_template: 'foreign_key :%s, :%s',
23
+ alter_template: 'add_foreign_key :%s, :%s',
24
+ validator: ->(type, *args) {
25
+ table = args[1]
26
+ break if ::DB.table_exists?(table)
27
+ ["Foreign key table '#{table}' does not exist!"]
28
+ }
29
+ end
30
+ end
31
+ end
@@ -86,9 +86,9 @@ module Shaf
86
86
  status(status)
87
87
 
88
88
  preferred_response = preferred_response_type(resource)
89
- serialized = serialize(resource, serializer, collection)
89
+ http_cache = kwargs.delete(:http_cache) { Settings.http_cache }
90
90
 
91
- http_cache = kwargs.fetch(:http_cache, Settings.http_cache)
91
+ serialized = serialize(resource, serializer, collection, **kwargs)
92
92
  add_cache_headers(serialized) if http_cache
93
93
 
94
94
  log.info "#{request.request_method} #{request.path_info} => #{status}"
@@ -100,12 +100,12 @@ module Shaf
100
100
  end
101
101
  end
102
102
 
103
- def serialize(resource, serializer, collection)
103
+ def serialize(resource, serializer, collection, **options)
104
104
  serializer ||= HALPresenter
105
105
  if collection
106
- serializer.to_collection(resource, current_user: current_user)
106
+ serializer.to_collection(resource, current_user: current_user, **options)
107
107
  else
108
- serializer.to_hal(resource, current_user: current_user)
108
+ serializer.to_hal(resource, current_user: current_user, **options)
109
109
  end
110
110
  end
111
111
 
@@ -34,18 +34,8 @@ module Shaf
34
34
  end
35
35
 
36
36
  def immutable_accessor(*methods)
37
- methods.each do |method|
38
- define_method(method) do
39
- value = instance_variable_get(:"@#{method}")
40
- ImmutableAttr.dup(value)
41
- end
42
- define_method(:"#{method}=") do |value|
43
- instance_variable_set(
44
- :"@#{method}",
45
- ImmutableAttr.dup(value)
46
- )
47
- end
48
- end
37
+ immutable_reader(*methods)
38
+ immutable_writer(*methods)
49
39
  end
50
40
  end
51
41
  end
@@ -12,7 +12,8 @@ module Shaf
12
12
  extend Shaf::Utils
13
13
  bootstrap
14
14
 
15
- UriHelperMethods.path_helpers_for.each do |controller, methods|
15
+ helpers = UriHelperMethods.path_helpers_for.sort { |a, b| a[0].to_s <=> b[0].to_s }
16
+ helpers.each do |controller, methods|
16
17
  puts "\n#{controller}:"
17
18
  methods.each do |method|
18
19
  template_method = "#{method}_template".to_sym
@@ -1,3 +1,3 @@
1
1
  module Shaf
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -7,6 +7,5 @@ require 'shaf/settings'
7
7
  require 'config/constants'
8
8
  require 'config/database'
9
9
  require 'config/initializers'
10
- require 'api/controllers/base_controller'
11
10
  require 'config/directories'
12
11
  require 'config/helpers'
@@ -1,6 +1,7 @@
1
1
  APP_ROOT = File.expand_path('../', __dir__)
2
2
  APP_DIR = File.expand_path('api', APP_ROOT)
3
3
  SRC_DIR = File.expand_path('src', APP_ROOT)
4
+ LIB_DIR = File.expand_path('lib', APP_ROOT)
4
5
  VIEWS_DIR = File.join(APP_ROOT, Shaf::Settings.views_folder)
5
6
  ASSETS_DIR = File.join(APP_ROOT, Shaf::Settings.public_folder)
6
7
  AUTH_TOKEN_HEADER = 'HTTP_X_AUTH_TOKEN'
@@ -1,7 +1,5 @@
1
1
  require 'config/constants'
2
2
 
3
- $:.unshift APP_DIR
4
-
5
3
  def sort_files(files)
6
4
  files.sort_by do |file|
7
5
  directory_priority(file) + file_priority(file)
@@ -27,7 +25,6 @@ def directory_priority(file)
27
25
  end
28
26
  end
29
27
 
30
-
31
28
  def file_priority(file)
32
29
  case File.basename(file)
33
30
  when /\Abase[\._]/
@@ -46,15 +43,11 @@ def require_ruby_files
46
43
  end
47
44
  end
48
45
 
49
- if Dir.exist? SRC_DIR
50
- $:.unshift SRC_DIR
46
+ [LIB_DIR, SRC_DIR, APP_DIR].each do |dir|
47
+ next unless Dir.exist? dir
48
+ $LOAD_PATH.unshift dir
51
49
 
52
- Dir.chdir(SRC_DIR) do
50
+ Dir.chdir(dir) do
53
51
  require_ruby_files
54
52
  end
55
53
  end
56
-
57
- Dir.chdir(APP_DIR) do
58
- require_ruby_files
59
- end
60
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -30,7 +30,7 @@ cert_chain:
30
30
  ZMhjYR7sRczGJx+GxGU2EaR0bjRsPVlC4ywtFxoOfRG3WaJcpWGEoAoMJX6Z0bRv
31
31
  M40=
32
32
  -----END CERTIFICATE-----
33
- date: 2019-01-05 00:00:00.000000000 Z
33
+ date: 2019-02-09 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rake
@@ -152,6 +152,8 @@ files:
152
152
  - lib/shaf/generator/migration/drop_column.rb
153
153
  - lib/shaf/generator/migration/empty.rb
154
154
  - lib/shaf/generator/migration/rename_column.rb
155
+ - lib/shaf/generator/migration/type.rb
156
+ - lib/shaf/generator/migration/types.rb
155
157
  - lib/shaf/generator/model.rb
156
158
  - lib/shaf/generator/policy.rb
157
159
  - lib/shaf/generator/scaffold.rb
metadata.gz.sig CHANGED
@@ -1,2 +1 @@
1
- f��8��^D�-X�@�t�w��vfe&���x�x�x����̆��UR��©�dv\�j2q��0A � ƻy*5�:��dC42�ʏfJ{��Ѡ����ɘo�Fo����YF123�ɦ��pZ�SĐ�XX����PԏZ�ӝ��Ƿ��p���5�W�lK�T�9
2
- �GF�b�~�G���?�w�|�B]���%=�_�^�F��(��4�g��RO�z ��SC�W�A���6��;��sᒶR��ӊ
1
+ ��_��1��YY=n�ʯ�\g{|��zb5���)��؉_]�%Y<?��oЁi��B�پ����Co"}I n ���"�����}<���kJ���ݒ��yyr'۝2y��2���