clean_model 0.0.5 → 0.0.6

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