yuba 0.0.1.pre → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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