yuba 0.0.1.pre → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 065c02ba0b6ba7a96764c3557e3f3abad4e2252d
4
- data.tar.gz: 13c440a52f8042fcd001d6d1305e233184c8aca2
3
+ metadata.gz: a0f50e10de1c64847c7dfb2087e0b8ca416ed1d5
4
+ data.tar.gz: f1d38de018095e4b0651a0c80c842cadb2070e20
5
5
  SHA512:
6
- metadata.gz: 107fbf7894edb031119725bd8f9844d78e52dbc3fc9f763cc0b60a244f50868b45949b2ffec47847e92a780598ee5af07e0a835adbcc15e339868ded43b275b8
7
- data.tar.gz: c9494157393285ba6b41d231ef56338411c890b96711010278053d6fdb00d71a6f4626ff1b564c1ba6bcecfebb3ea89c14e1f943dbdf83d12298ba5dddb33a10
6
+ metadata.gz: 4e2b3a1cb8b9f0ac254f67d504ddf99ffc47b02d322e7eded4a1475597eb8f6374c08c59e19ec39662dd2446c299973237ec8f46fa8cc6bd62e1d22bdfe57406
7
+ data.tar.gz: 8673f827dd5ecf5a140bfe8774b92de85bdf20bb9f2ff1feb894dc55f1fb8f7ffd01ea4105e9060d72f26b286650678d74da30739c9b6f36e118ce171b36c0fa
data/README.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Yuba
2
2
 
3
- This gem is now under construction. It doesn't work now.
3
+ [![Build Status](https://travis-ci.org/willnet/yuba.svg?branch=master)](https://travis-ci.org/willnet/yuba)
4
+ [![Gem Version](https://badge.fury.io/rb/yuba.svg)](https://badge.fury.io/rb/yuba)
5
+
6
+ ## warning
7
+
8
+ Version of this gem is now 0.0.x. It works but there must be occasional breaking changes to the API.
9
+
10
+ ## Summary
4
11
 
5
12
  Yuba add new layers to rails.
6
13
 
@@ -8,11 +15,12 @@ Yuba add new layers to rails.
8
15
  - Form
9
16
  - ViewModel
10
17
 
11
- ## Usage
18
+ It is convenient to use them in combination, but you can use them even by themselves.
12
19
 
13
- How to use my plugin.
20
+ If you have difficulties with large rails application, Yuba help you.
14
21
 
15
22
  ## Installation
23
+
16
24
  Add this line to your application's Gemfile:
17
25
 
18
26
  ```ruby
@@ -20,17 +28,216 @@ gem 'yuba'
20
28
  ```
21
29
 
22
30
  And then execute:
31
+
23
32
  ```bash
24
- $ bundle
33
+ $ bundle install
25
34
  ```
26
35
 
27
- Or install it yourself as:
28
- ```bash
29
- $ gem install yuba
36
+ ## Support
37
+
38
+ - Rails 4.2+
39
+ - Ruby 2.2+
40
+
41
+ ## ViewModel
42
+
43
+ ViewModel is useful when there are many instance variables in controller.
44
+
45
+ ```ruby
46
+ class PostViewModel < Yuba::ViewModel
47
+ property :post
48
+ property :author, public: true
49
+ property :other, optional: true
50
+
51
+ def title
52
+ post.title
53
+ end
54
+
55
+ def body
56
+ post.body
57
+ end
58
+ end
59
+
60
+ Post = Struct.new(:title, :body)
61
+ post = Post.new('hello', 'world')
62
+
63
+ view_model = PostViewModel.new(post: post, author: 'willnet')
64
+ view.title #=> 'hello'
65
+ view.body #=> 'world'
66
+ view.author #=> 'willnet'
67
+ view.post #=> NoMethodError
68
+ ```
69
+
70
+ ### property
71
+
72
+ `.property` method register property to the class.
73
+
74
+ Those registered by property need to be passed as arguments to the `initialize` except when `optional: true` is attached. You get ArgumentError if you don't pass `property` to `initialize`.
75
+
76
+ Property is default to private. This means you can use it in internal the instance. If you want to use it as public, use `public: true` option.
77
+
78
+ ### Auto Assign
79
+
80
+ You can use ViewModel in a controller like following
81
+
82
+ ```ruby
83
+ class PostsController
84
+ def show
85
+ @view_model = PostViewModel.new(post: post, author: 'willnet')
86
+ end
87
+ end
88
+ ```
89
+
90
+ In view template, if you want to access post and author, you have to use `@view_model` instance variable like `@view_model.post.title`. if it feels troublesome, you can write like following
91
+
92
+ ```ruby
93
+ class PostsController
94
+ def show
95
+ view_model = PostViewModel.new(post: post, author: 'willnet')
96
+ render view_model: view_model
97
+ end
98
+ end
99
+ ```
100
+
101
+ view_model option of render takes ViewModel, which get it's public methods (include public property) and assign them to instance variables in view template. So you can write `<%= @post.title %>` instead of `<%= @view_model.post.title %>`
102
+
103
+ ## Service
104
+
105
+ Service is useful when controller has many application logic.
106
+
107
+ ```ruby
108
+ class PostController < ApplicationController
109
+ def new
110
+ @post = CreatePostService.call(user: current_user).post
111
+ end
112
+
113
+ def create
114
+ service = CreatePostService.call(user: current_user, params: params)
115
+
116
+ if service.success?
117
+ redirect_to root_path
118
+ else
119
+ @post = service.post
120
+ render :new
121
+ end
122
+ end
123
+ end
124
+
125
+ class CreatePostService < Yuba::Service
126
+ property :user, public: true
127
+ property :params, optional: true
128
+
129
+ def call
130
+ if post.save
131
+ notify_to_admin
132
+ else
133
+ fail!
134
+ end
135
+ end
136
+
137
+ def post
138
+ user.posts.build(post_params)
139
+ end
140
+
141
+ private
142
+
143
+ def notify_to_admin
144
+ AdminMailer.notify_create_post(post).deliver_later
145
+ end
146
+
147
+ def post_params
148
+ params.require(:post).permit(:title, :body)
149
+ end
150
+ end
151
+ ```
152
+
153
+ - `.property` method register property to the class like ViewModel.
154
+ - `.call` invokes `#call` after assigning arguments as properties.
155
+ - `#success?` returns `true` if you don't invoke `#fail!`
156
+
157
+ ## Form
158
+
159
+ Form is just wrapper of [reform-rails](https://github.com/trailblazer/reform-rails) for now.
160
+
161
+ You can see documentation [here](http://trailblazer.to/gems/reform/rails.html).
162
+
163
+ ## Combination Sample
164
+
165
+ ```ruby
166
+ class ArtistsController < ApplicationController
167
+ def new
168
+ @view_model = Artist::CreateService.new(params: params).view_model
169
+ end
170
+
171
+ def create
172
+ service = Artist::CreateService.call(params: params)
173
+
174
+ if service.success?
175
+ redirect_to artists_path
176
+ else
177
+ @view_model = service.view_model
178
+ render :new
179
+ end
180
+ end
181
+ ```
182
+
183
+ ```ruby
184
+ class Artist::CreateService < Yuba::Service
185
+ property :params
186
+
187
+ def call
188
+ if form.validate(params)
189
+ form.save
190
+ else
191
+ fail!
192
+ end
193
+ end
194
+
195
+ def view_model
196
+ Artist::CreateViewModel.new(form: form)
197
+ end
198
+
199
+ private
200
+
201
+ def form
202
+ @form ||= ArtistForm.new(Artist.new)
203
+ end
204
+ end
205
+ ```
206
+
207
+ ```ruby
208
+ class ArtistForm < Yuba::Form
209
+ property :name
210
+
211
+ validates :name, presence: true, length: { maximum: 100 }
212
+ end
213
+ ```
214
+
215
+ ```ruby
216
+ class Artist::CreateViewModel < Yuba::ViewModel
217
+ property :form, public: true
218
+ end
219
+ ```
220
+
221
+ ## generators
222
+
223
+ You can use generators.
224
+
225
+ ```
226
+ rails generate yuba:service create_artist
227
+ rails generate yuba:form artist
228
+ rails generate yuba:view_model artist_index
30
229
  ```
31
230
 
32
231
  ## Contributing
33
- Contribution directions go here.
232
+
233
+ You can try to test by doing as following
234
+
235
+ ```
236
+ git clone https://github.com/willnet/yuba.git
237
+ cd yuba
238
+ bundle
239
+ bundle exec rake
240
+ ```
34
241
 
35
242
  ## License
36
243
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,9 @@
1
+ module Yuba
2
+ class FormGenerator < ::Rails::Generators::NamedBase
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def generate_form
6
+ template 'form.tt', File.join('app/forms', class_path, "#{file_name}_form.rb")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Form < Yuba::Form
3
+ end
4
+ <% end -%>
@@ -0,0 +1,9 @@
1
+ module Yuba
2
+ class ServiceGenerator < ::Rails::Generators::NamedBase
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def generate_service
6
+ template 'service.tt', File.join('app/services', class_path, "#{file_name}_service.rb")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Service < Yuba::Service
3
+ def call
4
+ end
5
+ end
6
+ <% end -%>
@@ -0,0 +1,4 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>ViewModel < Yuba::ViewModel
3
+ end
4
+ <% end -%>
@@ -0,0 +1,9 @@
1
+ module Yuba
2
+ class ViewModelGenerator < ::Rails::Generators::NamedBase
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def generate_view_model
6
+ template 'view_model.tt', File.join('app/view_models', class_path, "#{file_name}_view_model.rb")
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,13 @@
1
+ require 'reform/rails'
2
+ require 'dry/types'
3
+
1
4
  module Yuba
2
5
  autoload :Form, 'yuba/form'
3
6
  autoload :Service, 'yuba/service'
4
7
  autoload :ViewModel, 'yuba/view_model'
8
+ autoload :Rendering, 'yuba/rendering'
9
+ end
10
+
11
+ ActiveSupport.on_load(:action_controller) do
12
+ ActionController::Base.include(Yuba::Rendering)
5
13
  end
@@ -1,60 +1,15 @@
1
- module Yuba
2
- class Form
3
- autoload :Attribute, 'yuba/form/attribute'
4
- autoload :Attributes, 'yuba/form/attributes'
5
- autoload :Collection, 'yuba/form/collection'
6
-
7
- include ActiveModel::Model
8
- class_attribute :_model_attribute
9
- class_attribute :attributes
1
+ require 'yuba/form/coercion'
2
+ require 'yuba/form/multi_parameter_attributes'
10
3
 
4
+ module Yuba
5
+ class Form < ::Reform::Form
11
6
  class << self
12
- # TODO: reformのようにネストできるようにしたい
13
- def attribute(name, type: 'string', &block)
14
- mod = Module.new do
15
- define_method(name) do
16
- attributes[name.to_s]
17
- end
18
- define_method("#{name}=") do |value|
19
- write_attribute(name.to_s, value, block)
20
- end
21
- end
22
- include mod
23
- end
24
-
25
- def collection(name)
7
+ def inherited(subclass)
8
+ subclass.feature Coercion
9
+ subclass.feature MultiParameterAttributes
10
+ subclass.include Reform::Form::ActiveRecord
11
+ subclass.include Reform::Form::ActiveModel::ModelReflections
26
12
  end
27
-
28
- def model(name)
29
- self._model_attribute = name
30
- end
31
-
32
- def build(**args)
33
- new(**args)
34
- end
35
- end
36
-
37
- def save
38
- valid? && persist
39
- end
40
-
41
- def persist
42
- end
43
-
44
- def model
45
- send(_model_attribute)
46
- end
47
-
48
- def model_name
49
- model&.model_name
50
- end
51
-
52
- private
53
-
54
- def write_attribute(name, value, block)
55
- # TODO: convert value by type of attribute
56
- value = Attributes.new(value, &block) if block
57
- attributes[name] = value
58
13
  end
59
14
  end
60
15
  end
@@ -0,0 +1,36 @@
1
+ require 'dry-types'
2
+
3
+ module Yuba
4
+ class Form < ::Reform::Form
5
+ module Coercion
6
+ module Types
7
+ include Dry::Types.module
8
+ end
9
+
10
+ module ClassMethods
11
+ def property(name, options={}, &block)
12
+ super(name, options, &block).tap do
13
+ break unless options[:type]
14
+ coercing_setter!(name, options[:type])
15
+ end
16
+ end
17
+
18
+ def coercing_setter!(name, type)
19
+ class_name = type.to_s.classify
20
+ type_class = "Yuba::Form::Coercion::Types::Form::#{class_name}".constantize
21
+
22
+ mod = Module.new do
23
+ define_method("#{name}=") do |value|
24
+ super type_class.(value)
25
+ end
26
+ end
27
+ include mod
28
+ end
29
+ end
30
+
31
+ def self.included(includer)
32
+ includer.extend ClassMethods
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,52 @@
1
+ module Yuba::Form::MultiParameterAttributes
2
+ # TODO: implement this with parse_filter, so we don't have to manually walk through the hash, etc.
3
+ class DateTimeParamsFilter
4
+ def call(params)
5
+ params = params.dup # DISCUSS: not sure if that slows down form processing?
6
+ date_attributes = {}
7
+
8
+ params.each do |attribute, value|
9
+ if value.is_a?(Hash)
10
+ params[attribute] = call(value) # TODO: #validate should only handle local form params.
11
+ elsif matches = attribute.match(/^(\w+)\(.i\)$/)
12
+ date_attribute = matches[1]
13
+ date_attributes[date_attribute] = params_to_date(
14
+ params.delete("#{date_attribute}(1i)"),
15
+ params.delete("#{date_attribute}(2i)"),
16
+ params.delete("#{date_attribute}(3i)"),
17
+ params.delete("#{date_attribute}(4i)"),
18
+ params.delete("#{date_attribute}(5i)")
19
+ )
20
+ end
21
+ end
22
+
23
+ date_attributes.each do |attribute, date|
24
+ params[attribute] = date
25
+ end
26
+ params
27
+ end
28
+
29
+ private
30
+ def params_to_date(year, month, day, hour, minute)
31
+ date_fields = [year, month, day].map!(&:to_i)
32
+ time_fields = [hour, minute].map!(&:to_i)
33
+
34
+ if date_fields.any?(&:zero?) || !Date.valid_date?(*date_fields)
35
+ return nil
36
+ end
37
+
38
+ if hour.blank? && minute.blank?
39
+ Date.new(*date_fields)
40
+ else
41
+ args = date_fields + time_fields
42
+ Time.zone ? Time.zone.local(*args) :
43
+ Time.new(*args)
44
+ end
45
+ end
46
+ end
47
+
48
+ # this hooks into the format-specific #deserialize! method.
49
+ def deserialize!(params)
50
+ super DateTimeParamsFilter.new.call(params) # if params.is_a?(Hash) # this currently works for hash, only.
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ module Yuba
2
+ module Rendering
3
+ def render(*args)
4
+ view_model_hash = args.find { |arg| arg.is_a?(Hash) && arg[:view_model] }
5
+ @_view_model = view_model_hash[:view_model] if view_model_hash[:view_model]
6
+ super
7
+ end
8
+
9
+ def view_assigns
10
+ super.merge(view_model_assigns)
11
+ end
12
+
13
+ private
14
+
15
+ def _protected_ivars
16
+ super.merge(:@_view_model)
17
+ end
18
+
19
+ def view_model_assigns
20
+ return {} unless @_view_model
21
+ # TODO: get all public methods between self and Yuba::ViewModel
22
+ # now get only in self
23
+ methods = @_view_model.public_methods(false)
24
+ methods.reject! do |method_name|
25
+ %i[call initialize].include?(method_name)
26
+ end
27
+ methods.inject({}) do |hash, method_name|
28
+ hash[method_name] = @_view_model.public_send(method_name)
29
+ hash
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,37 +1,60 @@
1
1
  module Yuba
2
2
  class Service
3
+ class_attribute :_properties
4
+ self._properties = {}
5
+
3
6
  class << self
4
7
  def call(**args)
5
- service = new
6
- return_value = args.present? ? service.call(**args) : service.call
7
- if return_value.respond_to?(:success?)
8
- return_value
9
- else
10
- result.success(form: service.form)
11
- end
8
+ service = args.empty? ? new : new(**args)
9
+ service.call
10
+ service
11
+ end
12
+
13
+ def property(name, options = {})
14
+ _properties[name.to_sym] = options
12
15
  end
13
16
  end
14
17
 
15
- def build_form(**args)
16
- form_class.build(**args)
18
+ def initialize(**args)
19
+ validate_arguments(args)
20
+ define_accessors(args)
21
+ success
22
+ end
23
+
24
+ def success
25
+ @_success = true
17
26
  end
18
27
 
19
- def form_class
20
- Object.const_get(form_class_name)
28
+ def fail!
29
+ @_success = false
21
30
  end
22
31
 
23
- def view_model_class
24
- Object.const_get(form_class_name)
32
+ def success?
33
+ @_success
34
+ end
35
+
36
+ def failure?
37
+ !@_success
25
38
  end
26
39
 
27
40
  private
28
41
 
29
- def form_class_name
30
- self.class.name.sub(/::.+Service/, 'Form')
42
+ def validate_arguments(args)
43
+ args.each_key do |key|
44
+ if !_properties.has_key?(key.to_sym) && !_properties.dig(key.to_sym, :optional)
45
+ raise ArgumentError, "missing 'property :#{key}' in #{self.class.name} class"
46
+ end
47
+ end
31
48
  end
32
49
 
33
- def view_model_class_name
34
- self.class.name.sub(/Service\z/, 'ViewModel')
50
+ def define_accessors(args)
51
+ args.each do |key, value|
52
+ public_method = _properties[key.to_sym][:public]
53
+ define_singleton_method key do
54
+ value
55
+ end
56
+ self.singleton_class.class_eval { private key.to_sym } unless public_method
57
+ end
35
58
  end
36
59
  end
37
60
  end
@@ -1,3 +1,3 @@
1
1
  module Yuba
2
- VERSION = '0.0.1.pre'
2
+ VERSION = '0.0.1'
3
3
  end
@@ -1,26 +1,45 @@
1
1
  module Yuba
2
2
  class ViewModel
3
+ class_attribute :_properties
4
+ self._properties = {}
5
+
3
6
  class << self
4
- def success(**args)
5
- new(args.merge(success: true))
7
+ # You can register property to the class.
8
+ # Those registered by property need to be passed as arguments to the `initialize` except when `optional: true`
9
+ # is attached. You get `ArgumentError` if you don't pass `property` to `initialize`.
10
+ # Property is default to private. This means you can use it in internal the instance.
11
+ # If you it as public, use `public: true` option.
12
+ #
13
+ # property :name, public: true
14
+ # property :email, optional: true
15
+ def property(name, options = {})
16
+ _properties[name.to_sym] = options
6
17
  end
7
18
  end
8
19
 
9
- def initialize(success: true, **args)
10
- @success = success
11
- args.each { |k,v| self.class.send(:define_method, k) { v } }
20
+ def initialize(**args)
21
+ validate_arguments(args)
22
+ define_accessors(args)
12
23
  end
13
24
 
14
- def success?
15
- @success
16
- end
25
+ private
17
26
 
18
- def failure?
19
- !@success
27
+ def validate_arguments(args)
28
+ args.each_key do |key|
29
+ if !_properties.has_key?(key.to_sym) && !_properties.dig(key.to_sym, :optional)
30
+ raise ArgumentError, "missing 'property :#{key}' in #{self.class.name} class"
31
+ end
32
+ end
20
33
  end
21
34
 
22
- def to_model
23
- form
35
+ def define_accessors(args)
36
+ args.each do |key, value|
37
+ public_method = _properties[key.to_sym][:public]
38
+ define_singleton_method key do
39
+ value
40
+ end
41
+ self.singleton_class.class_eval { private key.to_sym } unless public_method
42
+ end
24
43
  end
25
44
  end
26
45
  end
metadata CHANGED
@@ -1,29 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yuba
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - willnet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-12 00:00:00.000000000 Z
11
+ date: 2017-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
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.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: reform-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dry-types
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
18
46
  - !ruby/object:Gem::Version
19
- version: 5.1.0
47
+ version: '0'
20
48
  type: :runtime
21
49
  prerelease: false
22
50
  version_requirements: !ruby/object:Gem::Requirement
23
51
  requirements:
24
- - - "~>"
52
+ - - ">="
25
53
  - !ruby/object:Gem::Version
26
- version: 5.1.0
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: sqlite3
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +66,76 @@ dependencies:
38
66
  - - ">="
39
67
  - !ruby/object:Gem::Version
40
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-rails
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: capybara
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: puma
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: selenium-webdriver
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: chromedriver-helper
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
41
139
  description: Add New Layers to Rails. Form, Service, ViewModel.
42
140
  email:
43
141
  - netwillnet@gmail.com
@@ -48,11 +146,18 @@ files:
48
146
  - MIT-LICENSE
49
147
  - README.md
50
148
  - Rakefile
149
+ - lib/generators/yuba/form/form_generator.rb
150
+ - lib/generators/yuba/form/templates/form.tt
151
+ - lib/generators/yuba/service/service_generator.rb
152
+ - lib/generators/yuba/service/templates/service.tt
153
+ - lib/generators/yuba/view_model/templates/view_model.tt
154
+ - lib/generators/yuba/view_model/view_model_generator.rb
51
155
  - lib/tasks/crepe_tasks.rake
52
156
  - lib/yuba.rb
53
157
  - lib/yuba/form.rb
54
- - lib/yuba/form/attribute.rb
55
- - lib/yuba/form/attributes.rb
158
+ - lib/yuba/form/coercion.rb
159
+ - lib/yuba/form/multi_parameter_attributes.rb
160
+ - lib/yuba/rendering.rb
56
161
  - lib/yuba/service.rb
57
162
  - lib/yuba/version.rb
58
163
  - lib/yuba/view_model.rb
@@ -71,12 +176,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
176
  version: '0'
72
177
  required_rubygems_version: !ruby/object:Gem::Requirement
73
178
  requirements:
74
- - - ">"
179
+ - - ">="
75
180
  - !ruby/object:Gem::Version
76
- version: 1.3.1
181
+ version: '0'
77
182
  requirements: []
78
183
  rubyforge_project:
79
- rubygems_version: 2.6.11
184
+ rubygems_version: 2.6.13
80
185
  signing_key:
81
186
  specification_version: 4
82
187
  summary: Add New Layers to Rails
@@ -1,9 +0,0 @@
1
- module Yuba
2
- class Form
3
- class Attribute
4
- def initialize(name)
5
- @name = name
6
- end
7
- end
8
- end
9
- end
@@ -1,44 +0,0 @@
1
- module Yuba
2
- module Form
3
- class Attributes
4
- class_attribute :attributes
5
- self.attributes = {}
6
-
7
- def initialize(value)
8
- yield if block_given?
9
- deep_assign(value)
10
- end
11
-
12
- def attribute(name, type: string, &block)
13
- mod = Module.new do
14
- define_method(name) do
15
- attributes[name.to_s]
16
- end
17
- define_method("#{name}=") do |value|
18
- write_attribute(name.to_s, value, block)
19
- end
20
- end
21
- include mod
22
- end
23
-
24
- private
25
-
26
- def write_attribute(name, value, block)
27
- # TODO: convert value by type of attribute
28
- value = Attributes.new(value, &block) if block
29
- attributes[name] = value
30
- end
31
-
32
- def deep_assign(value)
33
- raise ArgumentError unless value.is_a? Hash
34
- value.each do |k,v|
35
- if v.is_a? Hash
36
- deep_assign(v)
37
- else
38
- attributes[name.to_s] = v
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end