dry_rails 0.5.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: 45e9f1560278be794de82bb4b02b2810eaa2cf0754216b90449179fab98da9f1
4
+ data.tar.gz: 112c9c2b20d87a231e76213e910c3510404466d22fe527a0727ded5c32b77b6f
5
+ SHA512:
6
+ metadata.gz: 1d3a39eb7221fd5de5a04fae053a346007d2b0e4024e875ee5eff291587f232bdc43da69abfdc847b3c49fdfecfa32ae8cce359dc7ec78534e29ec5e21600ef8
7
+ data.tar.gz: 0cc139ffa109deeea728d3fd03b6313eafe6b485690e9a4a5e2132f561ef9f03ccc21a8df9040d67c97782ac4fff56aa76c0026fa8f3a188ddc54b2deedc5816
@@ -0,0 +1,32 @@
1
+ = form_for form_arguments(@record), html: { class: 'form' } do |f|
2
+ %fieldset
3
+ - if lookup_context.exists?('form_fieldset_before',
4
+ %W[#{@resource.model_name.route_key}/dry], true)
5
+ = render "#{@resource.model_name.route_key}/dry/form_fieldset_before"
6
+
7
+ - @resource.each_form_fields do |attr, type|
8
+ %p.field
9
+ - case type
10
+ - when Class
11
+ = f.label attr
12
+ %br
13
+ = f.collection_select attr, type.send(:all), :id, :to_s
14
+ - when Symbol
15
+ - if type == :check_box
16
+ = f.send type, attr
17
+ = f.label attr
18
+ - else
19
+ = f.label attr
20
+ %br
21
+ - form_control = ['form_field_for',
22
+ @resource.model_name.singular_route_key,
23
+ attr].join(?_).to_sym
24
+ - if respond_to? form_control
25
+ = send form_control, f
26
+ - else
27
+ = f.send type, attr
28
+
29
+ - if @record.errors.any?
30
+ = render "form_errors", record: @record
31
+
32
+ %p= f.button
@@ -0,0 +1,5 @@
1
+ .form-errors
2
+ %ul.errors-list
3
+ - @record.errors.full_messages.each do |error|
4
+ %li.error
5
+ = error
@@ -0,0 +1,15 @@
1
+ %h1
2
+ Editing
3
+ = @resource.singular_name
4
+
5
+
6
+ = render 'form'
7
+
8
+ %ul.actions
9
+ - if @resource.relations?
10
+ - @resource.relations.each do |relation|
11
+ - relation = @record.send(relation)
12
+ %li= link_to relation.model_name.human.pluralize,
13
+ relation_path(@record, relation)
14
+ %li
15
+ = link_to 'Back', collection_path(@resource)
@@ -0,0 +1,62 @@
1
+ %h1
2
+ Listing
3
+ = @resource.plural_name
4
+
5
+
6
+ - if @collection.empty?
7
+ %p
8
+ No
9
+ = @resource.singular_name
10
+ found.
11
+
12
+ - else
13
+ %table.list
14
+ %thead
15
+ %tr
16
+ %th
17
+ = @resource.singular_name.capitalize
18
+ - @resource.attrs_read.each do |attr|
19
+ %th= attr.capitalize
20
+ - if @resource.edit? || @resource.destroy?
21
+ %th.list-actions
22
+ Actions
23
+
24
+ %tbody
25
+ - @collection.each do |record|
26
+ %tr
27
+ %td
28
+ - if @resource.show?
29
+ = link_to record, record_path(record)
30
+ - else
31
+ = link_to record, edit_path(record)
32
+ - @resource.attrs_read.each do |attr|
33
+ %td
34
+ - attr_content = ['read_attr_content',
35
+ @resource.model_name.singular_route_key,
36
+ attr].join(?_).to_sym
37
+ - if respond_to? attr_content
38
+ = send attr_content, record
39
+ - else
40
+ = record.send attr
41
+ - if @resource.edit? || @resource.destroy?
42
+ %td.list-actions
43
+ %ul.actions
44
+ - if @resource.edit?
45
+ %li= link_to 'Edit', edit_path(record)
46
+ - if @resource.destroy?
47
+ %li= link_to 'Destroy', record_path(record), method: :delete,
48
+ data: { confirm: t('confirmation',
49
+ default: 'Are you sure?') }
50
+ - if @resource.relations?
51
+ - @resource.relations.each do |relation|
52
+ - relation = record.send(relation)
53
+ %li= link_to relation.model_name.human.pluralize,
54
+ relation_path(record, relation)
55
+
56
+
57
+ %ul.actions
58
+ - if @resource.new?
59
+ %li
60
+ = link_to "New #{@resource.singular_name}", new_path(@resource)
61
+ - if lookup_context.exists?('index_actions_extra', %w[dry], true)
62
+ = render 'dry/index_actions_extra'
@@ -0,0 +1,10 @@
1
+ %h1
2
+ New
3
+ = @resource.singular_name
4
+
5
+
6
+ = render 'form'
7
+
8
+ %ul.actions
9
+ %li
10
+ = link_to 'Back', collection_path(@resource)
@@ -0,0 +1,134 @@
1
+ module Dry
2
+ module Controller
3
+ extend ActiveSupport::Concern
4
+ include RoutingHelpers
5
+
6
+ included do
7
+ class_attribute :_dry_scope, instance_accessor: false
8
+
9
+ class_attribute :_dry_attrs, instance_accessor: false
10
+ self._dry_attrs = { read: [], write: [], options: {} }
11
+
12
+ class_attribute :_dry_nested_relations, instance_accessor: false
13
+ self._dry_nested_relations = []
14
+
15
+ append_view_path TemplateResolver.new
16
+
17
+ helper RoutingHelpers
18
+
19
+ before_filter :set_resource
20
+ before_filter :set_collection, only: :index
21
+ before_filter :set_record, only: %i[show edit update destroy]
22
+ end
23
+
24
+ module ClassMethods
25
+ def dry_scope &block
26
+ self._dry_scope = block
27
+ end
28
+
29
+ def dry_attrs_read *attrs
30
+ self._dry_attrs[:read] = attrs
31
+ end
32
+
33
+ def dry_attrs_write *attrs
34
+ self._dry_attrs[:write] = attrs
35
+ end
36
+
37
+ def dry_attrs_options **options
38
+ self._dry_attrs[:options] = options
39
+ end
40
+
41
+ def dry_nest *relations
42
+ self._dry_nested_relations.push *relations
43
+ end
44
+ end
45
+
46
+ def index
47
+ end
48
+
49
+ def show
50
+ end
51
+
52
+ def new
53
+ @record = resource_scope.new
54
+ end
55
+
56
+ def edit
57
+ end
58
+
59
+ def create
60
+ @record = resource_scope.new record_params
61
+ if @record.save
62
+ redirect_to collection_path(@resource),
63
+ notice: "#{model_name.singular.capitalize} was successfully created."
64
+ else
65
+ render :new
66
+ end
67
+ end
68
+
69
+ def update
70
+ if @record.update record_params
71
+ redirect_to collection_path(@resource),
72
+ notice: "#{model_name.singular.capitalize} was successfully updated."
73
+ else
74
+ render :edit
75
+ end
76
+ end
77
+
78
+ def destroy
79
+ @record.destroy
80
+ redirect_to collection_path(@resource),
81
+ notice: "#{model_name.singular.capitalize} was successfully destroyed."
82
+ end
83
+
84
+ private
85
+
86
+ def resource
87
+ @resource ||= Resource.new(controller_name.classify.constantize,
88
+ attrs_read: self.class._dry_attrs[:read],
89
+ attrs_write: self.class._dry_attrs[:write],
90
+ attrs_options: self.class._dry_attrs[:options],
91
+ relations: self.class._dry_nested_relations,
92
+ routes: resource_routes
93
+ )
94
+ end
95
+
96
+ def resource_routes
97
+ ResourceRoutes.new(Rails.application.routes.routes, controller_path)
98
+ .routes
99
+ end
100
+
101
+ def resource_scope
102
+ if b = self.class._dry_scope
103
+ instance_exec &b
104
+ else
105
+ resource.model
106
+ end
107
+ end
108
+
109
+ def model_name
110
+ resource.model_name
111
+ end
112
+
113
+ def collection
114
+ resource_scope.order 'created_at ASC'
115
+ end
116
+
117
+ def set_resource
118
+ resource
119
+ end
120
+
121
+ def set_collection
122
+ @collection = collection
123
+ end
124
+
125
+ def set_record
126
+ @record = resource_scope.find params[:id]
127
+ end
128
+
129
+ def record_params
130
+ params.require(model_name.param_key.to_sym)
131
+ .permit *self.class._dry_attrs[:write]
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,100 @@
1
+ module Dry
2
+ class Resource
3
+ DEFAULT_OPTIONS = {
4
+ attrs_read: [],
5
+ attrs_write: [],
6
+ attrs_options: {},
7
+ relations: [],
8
+ routes: []
9
+ }
10
+
11
+ ATTR_TYPE_TO_FORM_FIELD = {
12
+ boolean: :check_box,
13
+ decimal: :number_field,
14
+ integer: :number_field,
15
+ string: :text_field,
16
+ text: :text_area
17
+ }
18
+
19
+ ATTR_RELATION_PATTERN = /_id\z/.freeze
20
+
21
+ extend Forwardable
22
+ def_delegators :@model, :model_name
23
+
24
+ attr_reader :model
25
+
26
+ def initialize model, options = {}
27
+ @model = model
28
+ @options = DEFAULT_OPTIONS.merge options
29
+ end
30
+
31
+ def singular_name
32
+ model_name.singular
33
+ end
34
+
35
+ def plural_name
36
+ model_name.plural
37
+ end
38
+
39
+ def relations?
40
+ @options[:relations].any?
41
+ end
42
+
43
+ def relations
44
+ @options[:relations]
45
+ end
46
+
47
+ def show?
48
+ has_route_for? :show
49
+ end
50
+
51
+ def new?
52
+ has_route_for? :new
53
+ end
54
+
55
+ def edit?
56
+ has_route_for? :edit
57
+ end
58
+
59
+ def destroy?
60
+ has_route_for? :destroy
61
+ end
62
+
63
+ def attrs_read
64
+ @options[:attrs_read]
65
+ end
66
+
67
+ def attrs_write
68
+ @options[:attrs_write]
69
+ end
70
+
71
+ def attrs_options
72
+ @options[:attrs_options]
73
+ end
74
+
75
+ def each_form_fields
76
+ attrs_write.each do |e|
77
+ if e =~ ATTR_RELATION_PATTERN
78
+ yield e,
79
+ @model.reflections[e.to_s.sub ATTR_RELATION_PATTERN, ''].klass
80
+ else
81
+ yield e, form_field_for(e)
82
+ end
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def has_route_for? action
89
+ @options[:routes].include? action
90
+ end
91
+
92
+ def form_field_for attr
93
+ if type = attrs_options[attr]
94
+ type
95
+ else
96
+ ATTR_TYPE_TO_FORM_FIELD[@model.column_types[attr.to_s].type]
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,20 @@
1
+ module Dry
2
+ class ResourceRoutes
3
+ def initialize routes, path
4
+ @routes = routes
5
+ @path = path
6
+ end
7
+
8
+ def routes
9
+ routes_for_path(@path).each_with_object([]) do |e, m|
10
+ m << e.defaults[:action].to_sym
11
+ end.uniq
12
+ end
13
+
14
+ private
15
+
16
+ def routes_for_path path
17
+ @routes.select { |e| e.defaults[:controller] == @path }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ module Dry
2
+ module RoutingHelpers
3
+ def collection_path resource
4
+ send "#{base_path resource, plural: true}_path"
5
+ end
6
+
7
+ def record_path record
8
+ send "#{base_path record.class}_path", *([@parent, record].compact)
9
+ end
10
+
11
+ def new_path resource
12
+ send "new_#{base_path resource}_path"
13
+ end
14
+
15
+ def edit_path record
16
+ send "edit_#{base_path record.class}_path", *([@parent, record].compact)
17
+ end
18
+
19
+ def relation_path record, relation
20
+ send "#{base_path record.class}_#{relation.model_name.route_key}_path",
21
+ record
22
+ end
23
+
24
+ def form_arguments record
25
+ [*current_namespace, @parent, record].compact
26
+ end
27
+
28
+ private
29
+
30
+ def current_namespace
31
+ (controller_path.split('/') - [controller_name]).map &:to_sym
32
+ end
33
+
34
+ def base_path klass, plural: false
35
+ path = [*current_namespace].flatten
36
+ path << parent_class.model_name.singular_route_key if parent?
37
+ path << klass.model_name.send(plural ? :route_key : :singular_route_key)
38
+ path * '_'
39
+ end
40
+
41
+ def parent?
42
+ !!@parent
43
+ end
44
+
45
+ def parent_class
46
+ @parent ? @parent.class : nil
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ require 'action_view/template/resolver.rb'
2
+
3
+ module Dry
4
+ class TemplateResolver < ::ActionView::FileSystemResolver
5
+ DRY_PATTERN = DEFAULT_PATTERN.sub /:prefix\//, ''
6
+
7
+ def initialize
8
+ super Dry.view_path, DRY_PATTERN
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Dry
2
+ VERSION = '0.5.0'.freeze
3
+ end
data/lib/dry.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'forwardable'
2
+
3
+ module Dry
4
+ class << self
5
+ def view_path
6
+ File.expand_path('../../app/views', __FILE__)
7
+ end
8
+
9
+ def lib_path
10
+ File.expand_path('..', __FILE__)
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dry_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Thibault Jouan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-03-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.5
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.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: haml
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: capybara
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
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: rspec-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sqlite3
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.3'
104
+ - - "<"
105
+ - !ruby/object:Gem::Version
106
+ version: '1.4'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: '1.3'
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '1.4'
117
+ description:
118
+ email: tj@a13.fr
119
+ executables: []
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - app/views/_form.haml
124
+ - app/views/_form_errors.haml
125
+ - app/views/edit.haml
126
+ - app/views/index.haml
127
+ - app/views/new.haml
128
+ - lib/dry.rb
129
+ - lib/dry/controller.rb
130
+ - lib/dry/resource.rb
131
+ - lib/dry/resource_routes.rb
132
+ - lib/dry/routing_helpers.rb
133
+ - lib/dry/template_resolver.rb
134
+ - lib/dry/version.rb
135
+ homepage:
136
+ licenses:
137
+ - BSD-3-Clause
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubygems_version: 3.0.3
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: Dry
158
+ test_files: []