clean_model 0.0.5 → 0.0.6

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.
data/.gitignore CHANGED
@@ -1,5 +1,5 @@
1
- *.gem
2
- .bundle
3
- Gemfile.lock
4
- pkg/*
5
- .idea
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in clean_model.gemspec
4
- gemspec
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in clean_model.gemspec
4
+ gemspec
data/README.md CHANGED
@@ -1,211 +1,211 @@
1
- # CleanModel
2
-
3
- Extensions for ActiveModel to implement multiple types of models
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'clean_model'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install clean_model
18
-
19
- ## Basic models
20
-
21
- ### Class definitions
22
-
23
- class Person
24
- include CleanModel::Base
25
-
26
- attribute :first_name
27
- attribute :last_name
28
- end
29
-
30
- ### Usage
31
-
32
- person = Person.new first_name: 'John', last_name: 'Doe'
33
-
34
- person.first_name -> 'John'
35
- person.last_name -> 'Doe'
36
-
37
- person.attributes -> {first_name: 'John', last_name: 'Doe'}
38
-
39
- person.assign_attributes first_name: 'Jorge'
40
-
41
- person.attributes -> {first_name: 'Jorge', last_name: 'Doe'}
42
-
43
- ### Defaults
44
-
45
- class Person
46
- include CleanModel::Base
47
-
48
- attribute :first_name, default: 'John'
49
- attribute :last_name
50
- end
51
-
52
- person = Person.new
53
- person.first_name -> 'John'
54
- person.last_name -> nil
55
-
56
- ### Active Model validations
57
-
58
- class Person
59
- include CleanModel::Base
60
-
61
- attribute :first_name
62
- attribute :last_name
63
-
64
- validates_presence_of :first_name, :last_name
65
- end
66
-
67
- person = Person.new
68
- person.valid? -> false
69
-
70
- ### Strong typing
71
-
72
- class Engine
73
- include CleanModel::Base
74
-
75
- attribute :power, class_name: :numeric
76
- attribute :cylinders, class_name: :integer
77
- attribute :valves, class_name: 'Integer'
78
- end
79
-
80
- engine = Engine.new
81
- engine.power = 130
82
- engine.cylinders = 6.1 -> Raise error CleanModel::InvalidTypeAssignment
83
-
84
- ### Transformations
85
-
86
- class Car
87
- include CleanModel::Base
88
-
89
- attribute :brand
90
- attribute :model
91
- attribute :engine, class_name: 'Engine'
92
- attribute :comfort, transformation: lambda { |v| v.is_a?(String) ? v.split(',').map(&:strip) : v }
93
- end
94
-
95
- car = Car.new do |c|
96
- c.engine = {power: 110, cylinders: 16, valves: 6}
97
- end
98
- car.engine -> <Engine @power=110, @cylinders=16, @valves=6>
99
-
100
- car = Car.new do |c|
101
- c.comfort = 'bluetooth, gps, electric pack'
102
- end
103
- car.comfort -> ['bluetooth', 'gps', 'electric pack']
104
-
105
- ### Collections
106
-
107
- class Factory
108
- include CleanModel::Base
109
-
110
- attribute :cars, collection: 'Car'
111
- end
112
-
113
- factory = Factory.new do |f|
114
- f.cars = [
115
- {brand: 'Honda', model: 'Civic'},
116
- {brand: 'Toyota', model: 'Corolla'},
117
- ]
118
- end
119
-
120
- factory.cars -> [<Car @brand=Honda, @model=Civic>, <Car @brand=Toyota, @model=Corolla>]
121
-
122
- ## Models with custom persistence
123
-
124
- ### Definition
125
-
126
- class Post
127
- include CleanModel::Persistent
128
-
129
- attribute :subject
130
- attribute :content
131
-
132
- private
133
-
134
- def create
135
- ...
136
- end
137
-
138
- def update
139
- ...
140
- end
141
-
142
- def delete
143
- ...
144
- end
145
- end
146
-
147
- ### Usage
148
-
149
- Post.create(subject: 'Title', content: 'Some text')
150
- or
151
- post = Post.new subject: 'Title', content: 'Some text'
152
- post.save
153
-
154
- post.content = 'Another text'
155
- post.save
156
-
157
- post.update_attributes(title: 'Another title')
158
-
159
- post.destroy
160
-
161
- ## Remote models (for REST APIs)
162
-
163
- ### Definition
164
-
165
- class User
166
- include CleanModel::Remote
167
-
168
- connection host: 'localhost', port: 9999
169
-
170
- attribute :first_name
171
- attribute :last_name
172
- attribute :email
173
-
174
- def self.find(id)
175
- http_get "/users/#{id}.json" do |response|
176
- new JSON.parse(response.body)
177
- end
178
- end
179
-
180
- private
181
-
182
- def create
183
- http.post '/users/create.json', wrapped_attributes
184
- end
185
-
186
- def update
187
- http.put "/users/#{id}.json", wrapped_attributes(except: :id)
188
- end
189
-
190
- def delete
191
- http.delete("/users/#{id}.json")
192
- end
193
- end
194
-
195
- ### Usage
196
-
197
- User.create first_name: 'John', last_name: 'Doe'
198
-
199
- user = User.find(1)
200
-
201
- user.update_attributes(first_name: 'Jorge')
202
-
203
- user.destroy
204
-
205
- ## Contributing
206
-
207
- 1. Fork it
208
- 2. Create your feature branch (`git checkout -b my-new-feature`)
209
- 3. Commit your changes (`git commit -am 'Added some feature'`)
210
- 4. Push to the branch (`git push origin my-new-feature`)
211
- 5. Create new Pull Request
1
+ # CleanModel
2
+
3
+ Extensions for ActiveModel to implement multiple types of models
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'clean_model'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install clean_model
18
+
19
+ ## Basic models
20
+
21
+ ### Class definitions
22
+
23
+ class Person
24
+ include CleanModel::Base
25
+
26
+ attribute :first_name
27
+ attribute :last_name
28
+ end
29
+
30
+ ### Usage
31
+
32
+ person = Person.new first_name: 'John', last_name: 'Doe'
33
+
34
+ person.first_name -> 'John'
35
+ person.last_name -> 'Doe'
36
+
37
+ person.attributes -> {first_name: 'John', last_name: 'Doe'}
38
+
39
+ person.assign_attributes first_name: 'Jorge'
40
+
41
+ person.attributes -> {first_name: 'Jorge', last_name: 'Doe'}
42
+
43
+ ### Defaults
44
+
45
+ class Person
46
+ include CleanModel::Base
47
+
48
+ attribute :first_name, default: 'John'
49
+ attribute :last_name
50
+ end
51
+
52
+ person = Person.new
53
+ person.first_name -> 'John'
54
+ person.last_name -> nil
55
+
56
+ ### Active Model validations
57
+
58
+ class Person
59
+ include CleanModel::Base
60
+
61
+ attribute :first_name
62
+ attribute :last_name
63
+
64
+ validates_presence_of :first_name, :last_name
65
+ end
66
+
67
+ person = Person.new
68
+ person.valid? -> false
69
+
70
+ ### Strong typing
71
+
72
+ class Engine
73
+ include CleanModel::Base
74
+
75
+ attribute :power, class_name: :numeric
76
+ attribute :cylinders, class_name: :integer
77
+ attribute :valves, class_name: 'Integer'
78
+ end
79
+
80
+ engine = Engine.new
81
+ engine.power = 130
82
+ engine.cylinders = 6.1 -> Raise error CleanModel::InvalidTypeAssignment
83
+
84
+ ### Transformations
85
+
86
+ class Car
87
+ include CleanModel::Base
88
+
89
+ attribute :brand
90
+ attribute :model
91
+ attribute :engine, class_name: 'Engine'
92
+ attribute :comfort, transformation: lambda { |v| v.is_a?(String) ? v.split(',').map(&:strip) : v }
93
+ end
94
+
95
+ car = Car.new do |c|
96
+ c.engine = {power: 110, cylinders: 16, valves: 6}
97
+ end
98
+ car.engine -> <Engine @power=110, @cylinders=16, @valves=6>
99
+
100
+ car = Car.new do |c|
101
+ c.comfort = 'bluetooth, gps, electric pack'
102
+ end
103
+ car.comfort -> ['bluetooth', 'gps', 'electric pack']
104
+
105
+ ### Collections
106
+
107
+ class Factory
108
+ include CleanModel::Base
109
+
110
+ attribute :cars, collection: 'Car'
111
+ end
112
+
113
+ factory = Factory.new do |f|
114
+ f.cars = [
115
+ {brand: 'Honda', model: 'Civic'},
116
+ {brand: 'Toyota', model: 'Corolla'},
117
+ ]
118
+ end
119
+
120
+ factory.cars -> [<Car @brand=Honda, @model=Civic>, <Car @brand=Toyota, @model=Corolla>]
121
+
122
+ ## Models with custom persistence
123
+
124
+ ### Definition
125
+
126
+ class Post
127
+ include CleanModel::Persistent
128
+
129
+ attribute :subject
130
+ attribute :content
131
+
132
+ private
133
+
134
+ def create
135
+ ...
136
+ end
137
+
138
+ def update
139
+ ...
140
+ end
141
+
142
+ def delete
143
+ ...
144
+ end
145
+ end
146
+
147
+ ### Usage
148
+
149
+ Post.create(subject: 'Title', content: 'Some text')
150
+ or
151
+ post = Post.new subject: 'Title', content: 'Some text'
152
+ post.save
153
+
154
+ post.content = 'Another text'
155
+ post.save
156
+
157
+ post.update_attributes(title: 'Another title')
158
+
159
+ post.destroy
160
+
161
+ ## Remote models (for REST APIs)
162
+
163
+ ### Definition
164
+
165
+ class User
166
+ include CleanModel::Remote
167
+
168
+ connection host: 'localhost', port: 9999
169
+
170
+ attribute :first_name
171
+ attribute :last_name
172
+ attribute :email
173
+
174
+ def self.find(id)
175
+ connection.get "/users/#{id}.json" do |response|
176
+ new JSON.parse(response.body)
177
+ end
178
+ end
179
+
180
+ private
181
+
182
+ def create
183
+ connection.post! '/users/create.json', wrapped_attributes
184
+ end
185
+
186
+ def update
187
+ connection.put! "/users/#{id}.json", wrapped_attributes(except: :id)
188
+ end
189
+
190
+ def delete
191
+ connection.delete!("/users/#{id}.json")
192
+ end
193
+ end
194
+
195
+ ### Usage
196
+
197
+ User.create first_name: 'John', last_name: 'Doe'
198
+
199
+ user = User.find(1)
200
+
201
+ user.update_attributes(first_name: 'Jorge')
202
+
203
+ user.destroy
204
+
205
+ ## Contributing
206
+
207
+ 1. Fork it
208
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
209
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
210
+ 4. Push to the branch (`git push origin my-new-feature`)
211
+ 5. Create new Pull Request
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require "bundler/gem_tasks"
1
+ require "bundler/gem_tasks"
data/clean_model.gemspec CHANGED
@@ -1,25 +1,24 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require 'clean_model/version'
4
-
5
- Gem::Specification.new do |s|
6
- s.name = 'clean_model'
7
- s.version = CleanModel::VERSION
8
- s.authors = ['Gabriel Naiman']
9
- s.email = ['gabynaiman@gmail.com']
10
- s.homepage = 'https://github.com/gabynaiman/clean_model'
11
- s.summary = 'Extensions for ActiveModel to implement multiple types of models'
12
- s.description = 'Extensions for ActiveModel to implement multiple types of models'
13
-
14
- s.files = `git ls-files`.split("\n")
15
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
- s.require_paths = ["lib"]
18
-
19
- s.add_dependency 'activesupport', '>= 3.0.0'
20
- s.add_dependency 'activemodel', '>= 3.0.0'
21
- s.add_dependency 'web_client', '0.0.3'
22
-
23
- s.add_development_dependency 'rspec'
24
- s.add_development_dependency 'webmock'
25
- end
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'clean_model/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'clean_model'
7
+ s.version = CleanModel::VERSION
8
+ s.authors = ['Gabriel Naiman']
9
+ s.email = ['gabynaiman@gmail.com']
10
+ s.homepage = 'https://github.com/gabynaiman/clean_model'
11
+ s.summary = 'Extensions for ActiveModel to implement multiple types of models'
12
+ s.description = 'Extensions for ActiveModel to implement multiple types of models'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'activemodel', '>= 3.0.0'
20
+ s.add_dependency 'web_client', '0.0.4'
21
+
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'webmock'
24
+ end
@@ -1,56 +1,56 @@
1
- module CleanModel
2
- class Attribute
3
- attr_reader :name, :options
4
-
5
- def initialize(name, options={})
6
- @name = symbolize(name)
7
- @options = options
8
- end
9
-
10
- def validate!(value)
11
- raise InvalidTypeAssignment.new(name, value) unless value.is_a? klass
12
- end
13
-
14
- def transform(value)
15
- if @options[:transformation]
16
- @options[:transformation].call(value)
17
- elsif value.is_a?(Hash) && klass.new.respond_to?(:assign_attributes)
18
- obj = klass.new
19
- obj.assign_attributes value
20
- obj
21
- elsif value.is_a?(Array) && collection_class.instance_methods.include?(:assign_attributes)
22
- value.map do |v|
23
- if v.is_a? collection_class
24
- v
25
- else
26
- obj = collection_class.new
27
- obj.assign_attributes v
28
- obj
29
- end
30
- end
31
- else
32
- value
33
- end
34
- end
35
-
36
- def assign_default(model)
37
- default_value = @options[:default].is_a?(Proc) ? @options[:default].call : @options[:default]
38
- model.send("#{@name}=", default_value) if default_value && model.respond_to?("#{@name}=")
39
- end
40
-
41
- private
42
-
43
- def klass
44
- @options[:class_name].to_s.classify.constantize
45
- end
46
-
47
- def collection_class
48
- @options[:collection].to_s.classify.constantize
49
- end
50
-
51
- def symbolize(text)
52
- text.is_a?(String) ? text.to_s.underscore.parameterize('_').to_sym : text
53
- end
54
-
55
- end
1
+ module CleanModel
2
+ class Attribute
3
+ attr_reader :name, :options
4
+
5
+ def initialize(name, options={})
6
+ @name = symbolize(name)
7
+ @options = options
8
+ end
9
+
10
+ def validate!(value)
11
+ raise InvalidTypeAssignment.new(name, value) unless value.is_a? klass
12
+ end
13
+
14
+ def transform(value)
15
+ if @options[:transformation]
16
+ @options[:transformation].call(value)
17
+ elsif value.is_a?(Hash) && klass.new.respond_to?(:assign_attributes)
18
+ obj = klass.new
19
+ obj.assign_attributes value
20
+ obj
21
+ elsif value.is_a?(Array) && collection_class.instance_methods.include?(:assign_attributes)
22
+ value.map do |v|
23
+ if v.is_a? collection_class
24
+ v
25
+ else
26
+ obj = collection_class.new
27
+ obj.assign_attributes v
28
+ obj
29
+ end
30
+ end
31
+ else
32
+ value
33
+ end
34
+ end
35
+
36
+ def assign_default(model)
37
+ default_value = @options[:default].is_a?(Proc) ? @options[:default].call : @options[:default]
38
+ model.send("#{@name}=", default_value) if default_value && model.respond_to?("#{@name}=")
39
+ end
40
+
41
+ private
42
+
43
+ def klass
44
+ @options[:class_name].to_s.classify.constantize
45
+ end
46
+
47
+ def collection_class
48
+ @options[:collection].to_s.classify.constantize
49
+ end
50
+
51
+ def symbolize(text)
52
+ text.is_a?(String) ? text.to_s.underscore.parameterize('_').to_sym : text
53
+ end
54
+
55
+ end
56
56
  end