encore 0.0.2 → 0.0.3
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 +4 -4
- data/.travis.yml +11 -0
- data/README.md +178 -27
- data/encore.gemspec +3 -3
- data/gemfiles/Gemfile.activerecord-3.2.x +5 -0
- data/gemfiles/Gemfile.activerecord-4.0 +5 -0
- data/lib/encore/association/has_many_association.rb +12 -0
- data/lib/encore/association/has_one_association.rb +12 -0
- data/lib/encore/association.rb +39 -0
- data/lib/encore/attribute.rb +10 -7
- data/lib/encore/entity/input/associations.rb +27 -0
- data/lib/encore/entity/input/errors.rb +1 -1
- data/lib/encore/entity/input/exposed_attributes.rb +7 -7
- data/lib/encore/entity/input.rb +30 -11
- data/lib/encore/entity/output/json.rb +14 -0
- data/lib/encore/entity/output.rb +6 -0
- data/lib/encore/entity.rb +10 -1
- data/lib/encore/helpers/controller_helper.rb +37 -0
- data/lib/encore/helpers.rb +1 -0
- data/lib/encore/railtie.rb +11 -0
- data/lib/encore/version.rb +1 -1
- data/lib/encore.rb +5 -3
- data/spec/encore/entity/input/associations_spec.rb +48 -0
- data/spec/encore/entity/input/exposed_attributes_spec.rb +46 -0
- data/spec/{poutine/entity_spec.rb → encore/entity/input_spec.rb} +31 -31
- data/spec/encore/entity/output/json_spec.rb +76 -0
- data/spec/encore/entity/output_spec.rb +5 -0
- data/spec/encore/entity_spec.rb +31 -0
- data/spec/encore/helpers/controller_helper_spec.rb +59 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/macros/model_macros.rb +14 -0
- metadata +32 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c05497c6b6640c47a20eafba79c3eb344cc523a6
|
4
|
+
data.tar.gz: 1e727f1662fdf0927f940e0a4d46fa5054073d88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b0c3d9175e9665cb709d725cf48873f2c16a4b9fb4100af1dafc07f087a9a9a075fbb8492822624a186386f4b5a0e7f25c560fdfd3b02dee4efd43e89820157
|
7
|
+
data.tar.gz: 46d9c310cdaed3ea98051dea98f3a463137468f512abadfd62019553e74dd4c35e0c88d9531f14d47c289b358b516d82ed2e208b6f1059ba87fb3d1a5796c7f2
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
<p align="center">
|
2
|
+
<a href="https://github.com/mirego/encore">
|
3
|
+
<img src="http://i.imgur.com/erXBozp.png" alt="Encore" />
|
4
|
+
</a>
|
5
|
+
<br />
|
6
|
+
Encore is a Ruby framework to help dealing with entities.
|
7
|
+
<br /><br />
|
8
|
+
<a href="https://rubygems.org/gems/encore"><img src="https://badge.fury.io/rb/encore.png" /></a>
|
9
|
+
<a href="https://codeclimate.com/github/mirego/encore"><img src="https://codeclimate.com/github/mirego/encore.png" /></a>
|
10
|
+
<a href="https://travis-ci.org/mirego/encore"><img src="https://travis-ci.org/mirego/encore.png?branch=master" /></a>
|
11
|
+
</p>
|
12
|
+
|
13
|
+
---
|
4
14
|
|
5
15
|
## Installation
|
6
16
|
|
@@ -24,6 +34,109 @@ $ gem install encore
|
|
24
34
|
|
25
35
|
## Usage
|
26
36
|
|
37
|
+
Let’s say we have the `UserEntity` entity class bound to the `User` model:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
class User < ActiveRecord::Base
|
41
|
+
end
|
42
|
+
|
43
|
+
class UserEntity
|
44
|
+
include Encore::Entity
|
45
|
+
|
46
|
+
expose :name
|
47
|
+
expose :email
|
48
|
+
expose :created_at, readonly: true
|
49
|
+
expose :updated_at, readonly: true
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
We can create a new `User` resource with attributes:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
@entity = UserEntity.new
|
57
|
+
@entity.assign_attributes email: 'remi@example.com', name: 'Rémi Prévost'
|
58
|
+
@entity.save
|
59
|
+
```
|
60
|
+
|
61
|
+
When assigning attributes to an entity, we can pass either an `:update` or a `:partial_update` context.
|
62
|
+
|
63
|
+
With the (default) `:partial_update` context, Encore will assign new attributes and ignore the other exposed attributes. This makes sense in a `PATCH` HTTP request context.
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
new_attributes = { email: 'remi+new@example.com' }
|
67
|
+
@entity.assign_attributes new_attributes
|
68
|
+
@entity.object.email # => "remi+new@example.com"
|
69
|
+
@entity.object.name # => "Rémi Prévost"
|
70
|
+
```
|
71
|
+
|
72
|
+
However, with the `:update` context, Encore will assign new attributes and set all non-provided exposed attributes to `nil`. This
|
73
|
+
makes sense in a `PUT` HTTP request context.
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
new_attributes = { email: 'remi+new-again@example.com' }
|
77
|
+
@entity.assign_attributes new_attributes, context: :update
|
78
|
+
@entity.object.email # => "remi+new-again@example.com"
|
79
|
+
@entity.object.name # => nil
|
80
|
+
```
|
81
|
+
|
82
|
+
If we try to assign a value to a non-exposed or readonly attribute, Encore will raise an error.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
@entity.assign_attributes email: 'remi+new@example.com', created_at: Time.now
|
86
|
+
# => raises #<Encore::Entity::Input::InvalidAttributeError: The #<Encore::Attribute UserEntity@created_at> attribute is not exposed.>
|
87
|
+
```
|
88
|
+
|
89
|
+
### Associations
|
90
|
+
|
91
|
+
You can also expose associations.
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
class User < ActiveRecord::Base
|
95
|
+
belongs_to :organization
|
96
|
+
end
|
97
|
+
|
98
|
+
class Organization < ActiveRecord::Base
|
99
|
+
has_many :users
|
100
|
+
end
|
101
|
+
|
102
|
+
class UserEntity
|
103
|
+
include Encore::Entity
|
104
|
+
|
105
|
+
expose :name
|
106
|
+
expose_one :organization
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
Assigning new value for associations doesn’t save them right away.
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
@user = User.first # => #<User id=1 organization_id=1>
|
114
|
+
@entity = UserEntity.new(@user)
|
115
|
+
@entity.assign_attributes organization: 2
|
116
|
+
@entity.object.organization_id # => 1
|
117
|
+
```
|
118
|
+
|
119
|
+
Calling `save` on the entity saves them.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
@entity.save
|
123
|
+
@entity.object.organization_id # => 2
|
124
|
+
```
|
125
|
+
|
126
|
+
## Typical setup with Ruby on Rails
|
127
|
+
|
128
|
+
_This is work-in-progress. There’s still missing stuff._
|
129
|
+
|
130
|
+
### Model
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
# app/models/user.rb
|
134
|
+
class User < ActiveRecord::Base
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
### Entity
|
139
|
+
|
27
140
|
```ruby
|
28
141
|
# app/entities/user_entity.rb
|
29
142
|
class UserEntity
|
@@ -34,43 +147,81 @@ class UserEntity
|
|
34
147
|
expose :created_at, readonly: true
|
35
148
|
expose :updated_at, readonly: true
|
36
149
|
end
|
150
|
+
```
|
151
|
+
|
152
|
+
### Routes
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
# config/routes.rb
|
156
|
+
Rails::Application.routes.draw do
|
157
|
+
resources :users do
|
158
|
+
# This makes Rails route PUT and PATCH requests to two separate actions
|
159
|
+
patch on: :member, action: :partial_update
|
160
|
+
end
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
### Controller
|
37
165
|
|
166
|
+
```ruby
|
38
167
|
# app/controllers/users_controller.rb
|
39
168
|
class UsersController < ApplicationController
|
169
|
+
before_action :fetch_user, only: [:update, :partial_update]
|
170
|
+
|
40
171
|
# POST /users
|
41
172
|
def create
|
42
|
-
@
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
173
|
+
@entity = UserEntity.new
|
174
|
+
@entity.assign_attributes(params[:user], context: :create)
|
175
|
+
|
176
|
+
process! @entity
|
177
|
+
|
178
|
+
# Here, `process!` is a shortcut for:
|
179
|
+
#
|
180
|
+
# if @entity.save
|
181
|
+
# render json: @entity, status: 201
|
182
|
+
# else
|
183
|
+
# render json: { errors: @entity.errors }, status: 422
|
184
|
+
# end
|
50
185
|
end
|
51
186
|
|
52
187
|
# PUT /users/:id
|
53
188
|
def update
|
54
|
-
@
|
55
|
-
@
|
56
|
-
|
57
|
-
|
58
|
-
render json: @user
|
59
|
-
else
|
60
|
-
render json: { errors: @user.errors }, status: 422
|
61
|
-
end
|
189
|
+
@entity = UserEntity.new(@user)
|
190
|
+
@entity.assign_attributes(params[:user], context: :update)
|
191
|
+
|
192
|
+
process! @entity
|
62
193
|
end
|
63
194
|
|
64
195
|
# PATCH /users/:id
|
65
196
|
def partial_update
|
66
|
-
@
|
67
|
-
@
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
197
|
+
@entity = UserEntity.new(@user)
|
198
|
+
@entity.assign_attributes(params[:user], context: :partial_update)
|
199
|
+
|
200
|
+
process! @entity
|
201
|
+
end
|
202
|
+
|
203
|
+
protected
|
204
|
+
|
205
|
+
def fetch_user
|
206
|
+
@user = User.find(params[:id])
|
74
207
|
end
|
75
208
|
end
|
76
209
|
```
|
210
|
+
|
211
|
+
## Todo
|
212
|
+
|
213
|
+
Please keep in mind that this gem is far from finished and totally not ready to use in production.
|
214
|
+
This is something we’ve been wanting to build for a long time and now we’re finally taking the time
|
215
|
+
do it right.
|
216
|
+
|
217
|
+
## License
|
218
|
+
|
219
|
+
`Encore` is © 2013 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/encore/blob/master/LICENSE.md) file.
|
220
|
+
|
221
|
+
The nut logo is based on [this lovely icon](http://thenounproject.com/noun/hazelnuts/#icon-No3618) by [Alessandro Suraci](http://thenounproject.com/alessandro.suraci/), from The Noun Project. Used under a [Creative Commons BY 3.0](http://creativecommons.org/licenses/by/3.0/) license.
|
222
|
+
|
223
|
+
## About Mirego
|
224
|
+
|
225
|
+
Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun. We proudly build mobile applications for [iPhone](http://mirego.com/en/iphone-app-development/ "iPhone application development"), [iPad](http://mirego.com/en/ipad-app-development/ "iPad application development"), [Android](http://mirego.com/en/android-app-development/ "Android application development"), [Blackberry](http://mirego.com/en/blackberry-app-development/ "Blackberry application development"), [Windows Phone](http://mirego.com/en/windows-phone-app-development/ "Windows Phone application development") and [Windows 8](http://mirego.com/en/windows-8-app-development/ "Windows 8 application development") in beautiful Quebec City.
|
226
|
+
|
227
|
+
We also love [open-source software](http://open.mirego.com/) and we try to extract as much code as possible from our projects to give back to the community.
|
data/encore.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Encore::VERSION
|
9
9
|
spec.authors = ['Rémi Prévost']
|
10
10
|
spec.email = ['rprevost@mirego.com']
|
11
|
-
spec.description = 'Encore is a framework
|
11
|
+
spec.description = 'Encore is a Ruby framework to help dealing with entities.'
|
12
12
|
spec.summary = spec.description
|
13
|
-
spec.homepage = 'https://github.com/
|
13
|
+
spec.homepage = 'https://github.com/mirego/encore'
|
14
14
|
spec.license = "BSD 3-Clause"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency 'rake'
|
23
23
|
spec.add_development_dependency 'rspec'
|
24
24
|
spec.add_development_dependency 'sqlite3'
|
25
|
+
spec.add_development_dependency 'rails', '>= 3.0.0'
|
25
26
|
|
26
|
-
spec.add_dependency 'activerecord', '>= 3.0.0'
|
27
27
|
spec.add_dependency 'activesupport', '>= 3.0.0'
|
28
28
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Encore
|
2
|
+
class Association < Attribute
|
3
|
+
def initialize(*args)
|
4
|
+
super
|
5
|
+
|
6
|
+
# Create a temporary accessor to store new values
|
7
|
+
@klass.send :attr_accessor, self.tmp_column_accessor
|
8
|
+
|
9
|
+
# Add callback on `before_save` to apply new values
|
10
|
+
association = self
|
11
|
+
@klass.before_save lambda { association.apply(self) }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Store the value in a temporary accessor used by the `before_save` callback
|
15
|
+
def assign(object, value)
|
16
|
+
object.send :"#{tmp_column_accessor}=", value
|
17
|
+
end
|
18
|
+
|
19
|
+
# Apply the new value to the column and reset the temporary accessor
|
20
|
+
def apply(object)
|
21
|
+
object.send :"#{column_accessor}=", object.send(tmp_column_accessor)
|
22
|
+
object.send :"#{tmp_column_accessor}=", nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return the value of the association
|
26
|
+
def fetch(object)
|
27
|
+
object.send :"#{column_accessor}"
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def tmp_column_accessor
|
33
|
+
:"encore_tmp_#{column_accessor}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'encore/association/has_one_association'
|
39
|
+
require 'encore/association/has_many_association'
|
data/lib/encore/attribute.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
module Encore
|
2
2
|
class Attribute
|
3
|
-
attr_reader :attribute, :klass
|
3
|
+
attr_reader :attribute, :klass, :column, :opts
|
4
4
|
|
5
|
-
def initialize(klass,
|
5
|
+
def initialize(klass, column, opts = {})
|
6
6
|
@klass = klass
|
7
|
-
@
|
7
|
+
@column = column
|
8
|
+
@attribute = opts[:as].try(:to_sym) || @column
|
8
9
|
@opts = opts
|
9
10
|
end
|
10
11
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def assign(object, value)
|
13
|
+
object.send :"#{self.column}=", value
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetch(object)
|
17
|
+
object.send :"#{self.column}"
|
15
18
|
end
|
16
19
|
|
17
20
|
def ==(other_attribute)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Encore
|
2
|
+
module Entity
|
3
|
+
module Input
|
4
|
+
module Associations
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def expose_one(column, opts = {})
|
9
|
+
expose_association(:one, column, opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
def expose_many(column, opts = {})
|
13
|
+
expose_association(:many, column, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def expose_association(type, column, opts)
|
19
|
+
@exposed_attributes ||= []
|
20
|
+
association_class = Encore::Association.const_get("Has#{type.to_s.capitalize}Association")
|
21
|
+
@exposed_attributes << association_class.new(self, column.to_sym, opts)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -6,14 +6,9 @@ module Encore
|
|
6
6
|
|
7
7
|
module ClassMethods
|
8
8
|
# Declare a new exposed attribute
|
9
|
-
def expose(
|
9
|
+
def expose(column, opts = {})
|
10
10
|
@exposed_attributes ||= []
|
11
|
-
@exposed_attributes << Encore::Attribute.new(self,
|
12
|
-
end
|
13
|
-
|
14
|
-
# Return only the attribute keys for each exposed attribute
|
15
|
-
def exposed_attributes_list
|
16
|
-
@exposed_attributes.map(&:attribute)
|
11
|
+
@exposed_attributes << Encore::Attribute.new(self, column.to_sym, opts)
|
17
12
|
end
|
18
13
|
|
19
14
|
# Return whether an attribute is exposed by the entity
|
@@ -26,6 +21,11 @@ module Encore
|
|
26
21
|
modifiable_attributes.include?(attribute)
|
27
22
|
end
|
28
23
|
|
24
|
+
# Return a list of all exposed attributes
|
25
|
+
def exposed_attributes
|
26
|
+
@exposed_attributes
|
27
|
+
end
|
28
|
+
|
29
29
|
# Return a list of all attributes that can be modified
|
30
30
|
def modifiable_attributes
|
31
31
|
@exposed_attributes.reject(&:readonly?)
|
data/lib/encore/entity/input.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'encore/entity/input/errors'
|
2
2
|
require 'encore/entity/input/exposed_attributes'
|
3
|
+
require 'encore/entity/input/associations'
|
3
4
|
|
4
5
|
module Encore
|
5
6
|
module Entity
|
@@ -7,48 +8,66 @@ module Encore
|
|
7
8
|
extend ActiveSupport::Concern
|
8
9
|
|
9
10
|
included do
|
11
|
+
extend ActiveModel::Callbacks
|
10
12
|
include Encore::Entity::Input::ExposedAttributes
|
13
|
+
include Encore::Entity::Input::Associations
|
14
|
+
define_model_callbacks :save
|
11
15
|
|
12
16
|
# Expose ID as a readonly attribute
|
13
17
|
expose :id, readonly: true
|
18
|
+
|
19
|
+
# Make the context accessible
|
20
|
+
attr_reader :context
|
14
21
|
end
|
15
22
|
|
16
23
|
# Assign specific attribute to the object
|
17
24
|
def assign_attributes(attributes = {}, opts = nil)
|
18
25
|
# Find the right context
|
19
|
-
unless context = opts.try(:delete, :context)
|
20
|
-
context = @object.persisted? ? :
|
26
|
+
unless @context = opts.try(:delete, :context)
|
27
|
+
@context = @object.persisted? ? :partial_update : :create
|
21
28
|
end
|
22
29
|
|
23
30
|
# Convert attribute keys to Attribute objects
|
24
|
-
attributes =
|
31
|
+
attributes = self.class.map_attributes(self.class, attributes)
|
25
32
|
|
26
33
|
# Loop through every passed attribute and set it
|
27
|
-
assign_provided_attributes(attributes
|
34
|
+
assign_provided_attributes(attributes)
|
28
35
|
|
29
36
|
# If we're doing an update, for any exposed attribute that wasn't passed, set it to nil
|
30
|
-
reset_forgotten_attributes(attributes
|
37
|
+
reset_forgotten_attributes(attributes)
|
31
38
|
end
|
32
39
|
|
33
40
|
protected
|
34
41
|
|
35
|
-
def assign_provided_attributes(attributes
|
42
|
+
def assign_provided_attributes(attributes)
|
36
43
|
attributes.each_pair do |attribute, value|
|
37
44
|
if self.class.modifiable_attribute?(attribute)
|
38
|
-
|
45
|
+
attribute.assign(self, value)
|
39
46
|
else
|
40
|
-
raise Encore::Entity::Input::
|
47
|
+
raise Encore::Entity::Input::InvalidAttributeError.new("The #{attribute} attribute is not exposed.")
|
41
48
|
end
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
45
|
-
def reset_forgotten_attributes(attributes
|
46
|
-
if context == :update
|
52
|
+
def reset_forgotten_attributes(attributes)
|
53
|
+
if @context == :update
|
47
54
|
(self.class.modifiable_attributes - attributes.keys).each do |attribute|
|
48
|
-
|
55
|
+
attribute.assign(self, nil)
|
49
56
|
end
|
50
57
|
end
|
51
58
|
end
|
59
|
+
|
60
|
+
module ClassMethods
|
61
|
+
def map_attributes(klass, params)
|
62
|
+
params.inject({}) do |memo, (attribute, value)|
|
63
|
+
exposed_attribute = klass.exposed_attributes.detect { |a| a.attribute == attribute }
|
64
|
+
key = exposed_attribute || Attribute.new(klass, attribute.to_sym)
|
65
|
+
|
66
|
+
memo.merge key => value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
52
71
|
end
|
53
72
|
end
|
54
73
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Encore
|
2
|
+
module Entity
|
3
|
+
module Output
|
4
|
+
module JSON
|
5
|
+
# Return each exposed attribute as a JSON value
|
6
|
+
def as_json(args = {})
|
7
|
+
self.class.exposed_attributes.inject({}) do |memo, item|
|
8
|
+
memo.merge item.attribute => item.fetch(self)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/encore/entity/output.rb
CHANGED
data/lib/encore/entity.rb
CHANGED
@@ -19,9 +19,18 @@ module Encore
|
|
19
19
|
@object = object || self.class.linked_class.new
|
20
20
|
end
|
21
21
|
|
22
|
+
# Save the object
|
23
|
+
def save
|
24
|
+
run_callbacks(:save) { @object.save }
|
25
|
+
end
|
26
|
+
|
22
27
|
# Delegate everything to the object
|
23
28
|
def method_missing(method, *args, &blk)
|
24
|
-
@object.
|
29
|
+
if @object.respond_to?(method)
|
30
|
+
@object.send(method, *args, &blk)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
36
|
module ClassMethods
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Encore
|
2
|
+
module Helpers
|
3
|
+
module ControllerHelper
|
4
|
+
HTTP_ERROR_STATUS_CODE = 422
|
5
|
+
HTTP_SUCCESS_CODE = 200
|
6
|
+
HTTP_SUCCESS_CREATED_CODE = 201
|
7
|
+
|
8
|
+
# Inject itself into the ActionController::Base class
|
9
|
+
def self.inject_into_action_controller
|
10
|
+
::ActionController::Base.send :include, self
|
11
|
+
end
|
12
|
+
|
13
|
+
# Save the entity and return a JSON response
|
14
|
+
def process!(entity)
|
15
|
+
error_status = HTTP_ERROR_STATUS_CODE
|
16
|
+
success_status = success_status_code_from_entity(entity)
|
17
|
+
|
18
|
+
if entity.save
|
19
|
+
render json: entity, status: success_status
|
20
|
+
else
|
21
|
+
render json: { errors: entity.errors }, status: error_status
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
# Return the status code to send after a successful processing
|
28
|
+
# of an entity, depending on its context
|
29
|
+
def success_status_code_from_entity(entity)
|
30
|
+
case entity.context
|
31
|
+
when :create then HTTP_SUCCESS_CREATED_CODE
|
32
|
+
else HTTP_SUCCESS_CODE
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'encore/helpers/controller_helper'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'encore'
|
2
|
+
require 'rails'
|
3
|
+
require 'action_controller'
|
4
|
+
|
5
|
+
module Encore
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer 'encore.action_controller' do |app|
|
8
|
+
ActiveSupport.on_load :action_controller, {}, &Encore::Helpers::ControllerHelper.inject_into_action_controller
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/encore/version.rb
CHANGED
data/lib/encore.rb
CHANGED
@@ -3,9 +3,11 @@ require 'encore/version'
|
|
3
3
|
# ActiveSupport
|
4
4
|
require 'active_support'
|
5
5
|
|
6
|
-
# ActiveRecord
|
7
|
-
require 'active_record'
|
8
|
-
|
9
6
|
# Encore
|
10
7
|
require 'encore/entity'
|
11
8
|
require 'encore/attribute'
|
9
|
+
require 'encore/association'
|
10
|
+
require 'encore/helpers'
|
11
|
+
|
12
|
+
# Railtie
|
13
|
+
require 'encore/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Encore::Entity::Input::Associations do
|
4
|
+
describe :ClassMethods do
|
5
|
+
describe :has_one do
|
6
|
+
before do
|
7
|
+
spawn_model(:User) { belongs_to :organization }
|
8
|
+
spawn_model(:Organization) { has_many :users }
|
9
|
+
|
10
|
+
spawn_entity :UserEntity do
|
11
|
+
expose :name
|
12
|
+
expose_one :organization
|
13
|
+
end
|
14
|
+
|
15
|
+
run_migration do
|
16
|
+
create_table(:users, force: true) do |t|
|
17
|
+
t.string :name
|
18
|
+
t.integer :organization_id
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table(:organizations, force: true)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:organization) { Organization.create }
|
27
|
+
let(:other_organization) { Organization.create }
|
28
|
+
let(:user) { organization.users.create(name: 'Art Vandelay') }
|
29
|
+
let(:entity) { UserEntity.new(user) }
|
30
|
+
|
31
|
+
context 'when assigning attributes' do
|
32
|
+
before { entity.assign_attributes organization: other_organization.id }
|
33
|
+
it { expect(entity.object.organization_id).to eql organization.id }
|
34
|
+
it { expect(entity.encore_tmp_organization_id).to eql other_organization.id }
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when saving the entity' do
|
38
|
+
before do
|
39
|
+
entity.assign_attributes organization: other_organization.id
|
40
|
+
entity.save
|
41
|
+
end
|
42
|
+
|
43
|
+
it { expect(entity.object.organization_id).to eql other_organization.id }
|
44
|
+
it { expect(entity.encore_tmp_organization_id).to be_nil }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Encore::Entity::Input::ExposedAttributes do
|
4
|
+
shared_examples 'exposability' do
|
5
|
+
before do
|
6
|
+
spawn_object_class!
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'with attribute name' do
|
10
|
+
it { expect{ entity.assign_attributes(name: 'Art Vandelay') }.to raise_error(Encore::Entity::Input::InvalidAttributeError) }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'with column name' do
|
14
|
+
before { entity.assign_attributes fullname: 'Art Vandelay' }
|
15
|
+
it { expect(entity.object.name).to eql 'Art Vandelay' }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:entity) { UserEntity.new }
|
20
|
+
|
21
|
+
before do
|
22
|
+
spawn_entity :UserEntity do
|
23
|
+
expose :name, as: :fullname
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with ActiveRecord model' do
|
28
|
+
let(:spawn_object_class!) do
|
29
|
+
spawn_model :User
|
30
|
+
|
31
|
+
run_migration do
|
32
|
+
create_table(:users, force: true) do |t|
|
33
|
+
t.string :name
|
34
|
+
t.timestamps
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it_has_behavior 'exposability'
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with OpenStruct structure' do
|
43
|
+
let(:spawn_object_class!) { spawn_struct :User }
|
44
|
+
it_has_behavior 'exposability'
|
45
|
+
end
|
46
|
+
end
|
@@ -1,79 +1,79 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Encore::Entity do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
describe Encore::Entity::Input do
|
4
|
+
describe :InstanceMethods do
|
5
|
+
describe :assign_attributes do
|
6
|
+
before do
|
7
|
+
spawn_model :User
|
8
|
+
|
9
|
+
spawn_entity :UserEntity do
|
10
|
+
expose :name
|
11
|
+
expose :email
|
12
|
+
expose :created_at, readonly: true
|
13
|
+
expose :updated_at, readonly: true
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
run_migration do
|
17
|
+
create_table(:users, force: true) do |t|
|
18
|
+
t.string :email
|
19
|
+
t.string :name
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
end
|
19
23
|
end
|
20
|
-
end
|
21
|
-
end
|
22
24
|
|
23
|
-
describe :InstanceMethods do
|
24
|
-
describe :assign_attributes do
|
25
25
|
let(:assign_attributes!) { entity.assign_attributes attributes, context: context }
|
26
26
|
|
27
27
|
context 'with :create context' do
|
28
28
|
let(:entity) { UserEntity.new }
|
29
|
-
let(:attributes) { { email: '
|
29
|
+
let(:attributes) { { email: 'art@vandelay.com' } }
|
30
30
|
let(:context) { :create }
|
31
31
|
|
32
32
|
before { assign_attributes! }
|
33
33
|
|
34
|
-
it { expect(entity.object.email).to eql '
|
34
|
+
it { expect(entity.object.email).to eql 'art@vandelay.com' }
|
35
35
|
it { expect(entity.object.name).to be_blank }
|
36
36
|
it { expect(entity.object.created_at).to be_blank }
|
37
37
|
it { expect(entity.object.updated_at).to be_blank }
|
38
38
|
end
|
39
39
|
|
40
|
-
context 'with :update context'
|
40
|
+
context 'with :update context' do
|
41
41
|
let(:entity) { UserEntity.new(User.first) }
|
42
42
|
let(:context) { :update }
|
43
|
-
let(:create_user!) { User.create(email: '
|
43
|
+
let(:create_user!) { User.create(email: 'art@vandelay.com', name: 'Art Vandelay') }
|
44
44
|
|
45
45
|
before { create_user! }
|
46
46
|
|
47
47
|
context 'when updating valid attributes' do
|
48
|
-
let(:attributes) { { email: '
|
48
|
+
let(:attributes) { { email: 'art+test@vandelay.com' } }
|
49
49
|
before { assign_attributes! }
|
50
50
|
|
51
|
-
it { expect(entity.object.email).to eql '
|
51
|
+
it { expect(entity.object.email).to eql 'art+test@vandelay.com' }
|
52
52
|
it { expect(entity.object.name).to be_blank }
|
53
53
|
it { expect(entity.object.created_at).to_not be_blank }
|
54
54
|
it { expect(entity.object.updated_at).to_not be_blank }
|
55
55
|
end
|
56
56
|
|
57
57
|
context 'when updating a protected attribute' do
|
58
|
-
let(:attributes) { { email: '
|
58
|
+
let(:attributes) { { email: 'art+test@vandelay.com', created_at: '2013-08-29 21:22:44' } }
|
59
59
|
|
60
|
-
it { expect { assign_attributes! }.to raise_error(Encore::Entity::Input::
|
60
|
+
it { expect { assign_attributes! }.to raise_error(Encore::Entity::Input::InvalidAttributeError) }
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
context 'with :partial_update context' do
|
65
65
|
let(:entity) { UserEntity.new(User.first) }
|
66
|
-
let(:attributes) { { email: '
|
66
|
+
let(:attributes) { { email: 'art+test@vandelay.com' } }
|
67
67
|
let(:context) { :partial_update }
|
68
|
-
let(:create_user!) { User.create(email: '
|
68
|
+
let(:create_user!) { User.create(email: 'art@vandelay.com', name: 'Art Vandelay') }
|
69
69
|
|
70
70
|
before do
|
71
71
|
create_user!
|
72
72
|
assign_attributes!
|
73
73
|
end
|
74
74
|
|
75
|
-
it { expect(entity.object.email).to eql '
|
76
|
-
it { expect(entity.object.name).to eql '
|
75
|
+
it { expect(entity.object.email).to eql 'art+test@vandelay.com' }
|
76
|
+
it { expect(entity.object.name).to eql 'Art Vandelay' }
|
77
77
|
it { expect(entity.object.created_at).to_not be_blank }
|
78
78
|
it { expect(entity.object.updated_at).to_not be_blank }
|
79
79
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Encore::Entity::Output::JSON do
|
4
|
+
describe :InstanceMethods do
|
5
|
+
describe :as_json do
|
6
|
+
context 'for simple entity' do
|
7
|
+
before do
|
8
|
+
# Create a model
|
9
|
+
spawn_model :User
|
10
|
+
|
11
|
+
# Create an entity
|
12
|
+
spawn_entity :UserEntity do
|
13
|
+
expose :name
|
14
|
+
end
|
15
|
+
|
16
|
+
run_migration do
|
17
|
+
create_table(:users, force: true) do |t|
|
18
|
+
t.string :name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:user) { User.create(name: 'Art Vandelay') }
|
24
|
+
let(:entity) { UserEntity.new(user) }
|
25
|
+
let(:json) { entity.as_json }
|
26
|
+
|
27
|
+
it { expect(json.keys).to include :id, :name }
|
28
|
+
it { expect(json[:id]).to eql user.id }
|
29
|
+
it { expect(json[:name]).to eql 'Art Vandelay' }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'for entity with associations' do
|
33
|
+
before do
|
34
|
+
# Create a model
|
35
|
+
spawn_model :User do
|
36
|
+
has_many :comments
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create a model
|
40
|
+
spawn_model :Comment
|
41
|
+
|
42
|
+
# Create an entity
|
43
|
+
spawn_entity :UserEntity do
|
44
|
+
expose :name
|
45
|
+
expose_many :comments
|
46
|
+
end
|
47
|
+
|
48
|
+
run_migration do
|
49
|
+
create_table(:users, force: true) do |t|
|
50
|
+
t.string :name
|
51
|
+
end
|
52
|
+
|
53
|
+
create_table(:comments, force: true) do |t|
|
54
|
+
t.text :body
|
55
|
+
t.integer :user_id
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
let(:user) do
|
61
|
+
User.create(name: 'Art Vandelay').tap do |user|
|
62
|
+
user.comments << Comment.create(body: 'Test 1')
|
63
|
+
user.comments << Comment.create(body: 'Test 2')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
let(:entity) { UserEntity.new(user) }
|
68
|
+
let(:json) { entity.as_json }
|
69
|
+
|
70
|
+
it { expect(json.keys).to include :id, :name, :comments }
|
71
|
+
it { expect(json[:comments]).to be_instance_of Array }
|
72
|
+
it { expect(json[:comments]).to include *Comment.pluck(:id) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Encore::Entity do
|
4
|
+
describe :InstanceMethods do
|
5
|
+
describe :method_missing do
|
6
|
+
before do
|
7
|
+
spawn_model :User
|
8
|
+
spawn_entity(:UserEntity) { expose :name }
|
9
|
+
|
10
|
+
run_migration do
|
11
|
+
create_table(:users, force: true) do |t|
|
12
|
+
t.string :name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:user) { User.create }
|
18
|
+
let(:entity) { UserEntity.new(user) }
|
19
|
+
|
20
|
+
context 'for delegated method' do
|
21
|
+
before { expect(user).to receive(:save) }
|
22
|
+
specify { entity.save }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'for setter method' do
|
26
|
+
before { expect(user).to receive(:name=).with('Art Vandelay') }
|
27
|
+
specify { entity.name = "Art Vandelay" }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Encore::Helpers::ControllerHelper do
|
4
|
+
describe :process! do
|
5
|
+
before do
|
6
|
+
# Create a model
|
7
|
+
spawn_model :User
|
8
|
+
|
9
|
+
# Create a controller
|
10
|
+
spawn_controller :UsersController do
|
11
|
+
before_filter :fetch_user, only: [:update]
|
12
|
+
|
13
|
+
define_method :create do
|
14
|
+
@entity = UserEntity.new
|
15
|
+
@entity.assign_attributes(params[:user], context: :create)
|
16
|
+
process! @entity
|
17
|
+
end
|
18
|
+
|
19
|
+
define_method :update do
|
20
|
+
@entity = UserEntity.new(@user)
|
21
|
+
@entity.assign_attributes(params[:user], context: :update0)
|
22
|
+
process! @entity
|
23
|
+
end
|
24
|
+
|
25
|
+
define_method :fetch_user do
|
26
|
+
@user = User.find(params[:id])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Create an entity
|
31
|
+
spawn_entity :UserEntity do
|
32
|
+
expose :name
|
33
|
+
end
|
34
|
+
|
35
|
+
run_migration do
|
36
|
+
create_table(:users, force: true) do |t|
|
37
|
+
t.string :name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:request) { ActionDispatch::TestRequest.new }
|
43
|
+
let(:env) { request.env.tap { |e| e['action_dispatch.request.parameters'] = params } }
|
44
|
+
|
45
|
+
context 'for create context' do
|
46
|
+
let(:params) { { user: { name: 'H.E. Pennypacker' } } }
|
47
|
+
let(:response) { UsersController.action(:create).call(env) }
|
48
|
+
it { expect(response.first).to eql 201 }
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'for update context' do
|
52
|
+
before { User.create(name: 'Art Vandelay') }
|
53
|
+
|
54
|
+
let(:params) { { id: 1, user: { name: 'H.E. Pennypacker' } } }
|
55
|
+
let(:response) { UsersController.action(:update).call(env) }
|
56
|
+
it { expect(response.first).to eql 200 }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,18 +1,31 @@
|
|
1
1
|
$:.unshift File.expand_path('../lib', __FILE__)
|
2
2
|
|
3
|
+
# Test dependencies
|
3
4
|
require 'rspec'
|
4
5
|
require 'sqlite3'
|
5
6
|
|
7
|
+
# Data structure
|
8
|
+
require 'active_record'
|
9
|
+
require 'ostruct'
|
10
|
+
|
11
|
+
# Encore
|
6
12
|
require 'encore'
|
7
13
|
|
8
14
|
# Require our macros and extensions
|
9
15
|
Dir[File.expand_path('../../spec/support/macros/*.rb', __FILE__)].map(&method(:require))
|
10
16
|
|
17
|
+
# Emulate our railtie's behavior
|
18
|
+
require 'encore/railtie'
|
19
|
+
Encore::Helpers::ControllerHelper.inject_into_action_controller
|
20
|
+
|
11
21
|
RSpec.configure do |config|
|
12
22
|
# Include our macros
|
13
23
|
config.include DatabaseMacros
|
14
24
|
config.include ModelMacros
|
15
25
|
|
26
|
+
# Shared examples aliases
|
27
|
+
config.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:'
|
28
|
+
|
16
29
|
config.before(:each) do
|
17
30
|
# Create the SQLite database
|
18
31
|
setup_database
|
@@ -14,6 +14,20 @@ module ModelMacros
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
# Create a new OpenStruct struct
|
18
|
+
def spawn_struct(klass_name, &block)
|
19
|
+
spawn_klass klass_name, OpenStruct do
|
20
|
+
instance_exec(&block) if block
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create a new ActionPack controller
|
25
|
+
def spawn_controller(klass_name, &block)
|
26
|
+
spawn_klass klass_name, ActionController::Base do
|
27
|
+
instance_exec(&block) if block
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
17
31
|
protected
|
18
32
|
|
19
33
|
# Create a new class
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: encore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rémi Prévost
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,13 +67,13 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rails
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 3.0.0
|
76
|
-
type: :
|
76
|
+
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 3.0.0
|
97
|
-
description: Encore is a framework
|
97
|
+
description: Encore is a Ruby framework to help dealing with entities.
|
98
98
|
email:
|
99
99
|
- rprevost@mirego.com
|
100
100
|
executables: []
|
@@ -103,24 +103,41 @@ extra_rdoc_files: []
|
|
103
103
|
files:
|
104
104
|
- .gitignore
|
105
105
|
- .rspec
|
106
|
+
- .travis.yml
|
106
107
|
- Gemfile
|
107
108
|
- LICENSE.md
|
108
109
|
- README.md
|
109
110
|
- Rakefile
|
110
111
|
- encore.gemspec
|
112
|
+
- gemfiles/Gemfile.activerecord-3.2.x
|
113
|
+
- gemfiles/Gemfile.activerecord-4.0
|
111
114
|
- lib/encore.rb
|
115
|
+
- lib/encore/association.rb
|
116
|
+
- lib/encore/association/has_many_association.rb
|
117
|
+
- lib/encore/association/has_one_association.rb
|
112
118
|
- lib/encore/attribute.rb
|
113
119
|
- lib/encore/entity.rb
|
114
120
|
- lib/encore/entity/input.rb
|
121
|
+
- lib/encore/entity/input/associations.rb
|
115
122
|
- lib/encore/entity/input/errors.rb
|
116
123
|
- lib/encore/entity/input/exposed_attributes.rb
|
117
124
|
- lib/encore/entity/output.rb
|
125
|
+
- lib/encore/entity/output/json.rb
|
126
|
+
- lib/encore/helpers.rb
|
127
|
+
- lib/encore/helpers/controller_helper.rb
|
128
|
+
- lib/encore/railtie.rb
|
118
129
|
- lib/encore/version.rb
|
119
|
-
- spec/
|
130
|
+
- spec/encore/entity/input/associations_spec.rb
|
131
|
+
- spec/encore/entity/input/exposed_attributes_spec.rb
|
132
|
+
- spec/encore/entity/input_spec.rb
|
133
|
+
- spec/encore/entity/output/json_spec.rb
|
134
|
+
- spec/encore/entity/output_spec.rb
|
135
|
+
- spec/encore/entity_spec.rb
|
136
|
+
- spec/encore/helpers/controller_helper_spec.rb
|
120
137
|
- spec/spec_helper.rb
|
121
138
|
- spec/support/macros/database_macros.rb
|
122
139
|
- spec/support/macros/model_macros.rb
|
123
|
-
homepage: https://github.com/
|
140
|
+
homepage: https://github.com/mirego/encore
|
124
141
|
licenses:
|
125
142
|
- BSD 3-Clause
|
126
143
|
metadata: {}
|
@@ -143,9 +160,15 @@ rubyforge_project:
|
|
143
160
|
rubygems_version: 2.0.2
|
144
161
|
signing_key:
|
145
162
|
specification_version: 4
|
146
|
-
summary: Encore is a framework
|
163
|
+
summary: Encore is a Ruby framework to help dealing with entities.
|
147
164
|
test_files:
|
148
|
-
- spec/
|
165
|
+
- spec/encore/entity/input/associations_spec.rb
|
166
|
+
- spec/encore/entity/input/exposed_attributes_spec.rb
|
167
|
+
- spec/encore/entity/input_spec.rb
|
168
|
+
- spec/encore/entity/output/json_spec.rb
|
169
|
+
- spec/encore/entity/output_spec.rb
|
170
|
+
- spec/encore/entity_spec.rb
|
171
|
+
- spec/encore/helpers/controller_helper_spec.rb
|
149
172
|
- spec/spec_helper.rb
|
150
173
|
- spec/support/macros/database_macros.rb
|
151
174
|
- spec/support/macros/model_macros.rb
|