make_resourceful 1.0.2 → 2.0.0.pre.beta

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
- ---
2
- SHA512:
3
- metadata.gz: 22ca8d52e43ead8ff5f40ee8af5d392304d190f6b7313cb33d3c0989930d53c86a09e2aac77c7f83c3ee003e104ea4f8d113b6da09574504514711303547d1e8
4
- data.tar.gz: 163467a219b321a68f72d136fd13da5b4a8d629f1c2d797ffbc1a4dab47acaf6cb9c6fad7031b0ecba0ee8474b8438bfeb669c097ea543d08210a3d9a8bda36c
5
- SHA1:
6
- metadata.gz: a3487669f91061847b76c0e65acbd661632a0e73
7
- data.tar.gz: b07115117516e9000e70fecf46a54f2f964995e9
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b4d2696450977a5370e0ad8e968c56fd633b7276e7e7963505b7d7d22a47006c
4
+ data.tar.gz: 79a14f2c03df4ec188a88d0f50e10228f085bf2c2cb525133ffbbfdb17035923
5
+ SHA512:
6
+ metadata.gz: a33582780d8b43b953b8bd0e2980549cee1d7c275083758aec2c6809776fa80b2890ad791fad0f27781300f0511efb046dd30a32377c93dc44e3eed4e56d6028
7
+ data.tar.gz: 053cfc6b27dcd4bfef4b98132eb39b338e153b72be3cb77f4bf970fd527f1b4a15e1e89aed30862f3fd1efcc62a5f38be3b56a9440826a28fb8210aa6bcb1288
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rake'
2
- require 'rake/rdoctask'
3
- require 'spec/rake/spectask'
2
+ require 'rdoc/task'
3
+ require 'rspec/core/rake_task'
4
4
 
5
5
  desc 'Default: run specs.'
6
6
  task :default => :spec
@@ -8,13 +8,13 @@ task :default => :spec
8
8
  spec_files = Rake::FileList["spec/**/*_spec.rb"]
9
9
 
10
10
  desc "Run specs"
11
- Spec::Rake::SpecTask.new do |t|
12
- t.spec_files = spec_files
13
- t.spec_opts = ["-c"]
11
+ RSpec::Core::RakeTask.new(:spec) do |t|
12
+ t.pattern = "spec/**/*_spec.rb"
13
+ t.rspec_opts = ["-c"]
14
14
  end
15
15
 
16
16
  desc "Generate code coverage"
17
- Spec::Rake::SpecTask.new(:coverage) do |t|
17
+ RSpec::Core::RakeTask.new(:coverage) do |t|
18
18
  t.spec_files = spec_files
19
19
  t.rcov = true
20
20
  t.rcov_opts = ['--exclude', 'spec,/var/lib/gems']
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 2.0.0-beta
@@ -30,6 +30,7 @@ module Resourceful
30
30
  @shallow_parent = nil
31
31
  @custom_member_actions = []
32
32
  @custom_collection_actions = []
33
+ @permitted_params = []
33
34
  end
34
35
 
35
36
  # This method is only meant to be called internally.
@@ -41,7 +42,7 @@ module Resourceful
41
42
  apply_publish
42
43
 
43
44
  kontroller = @controller
44
-
45
+
45
46
  Resourceful::ACTIONS.each do |action_named|
46
47
  # See if this is a method listed by #actions
47
48
  unless @ok_actions.include? action_named
@@ -51,28 +52,31 @@ module Resourceful
51
52
  end
52
53
  end
53
54
 
54
- kontroller.hidden_actions.reject! &@ok_actions.method(:include?)
55
+ if kontroller.respond_to?(:hidden_actions)
56
+ kontroller.hidden_actions.reject! &@ok_actions.method(:include?)
57
+ end
55
58
  kontroller.send :include, @action_module
56
-
59
+
57
60
  merged_callbacks = kontroller.resourceful_callbacks.merge @callbacks
58
61
  merged_responses = kontroller.resourceful_responses.merge @responses
59
-
62
+
63
+ kontroller.permitted_params = @permitted_params
60
64
  kontroller.resourceful_callbacks = merged_callbacks
61
65
  kontroller.resourceful_responses = merged_responses
62
66
  kontroller.made_resourceful = true
63
67
 
64
- kontroller.parents = @parents
68
+ kontroller.parent_controllers = @parents
65
69
  kontroller.shallow_parent = @shallow_parent
66
70
  kontroller.model_namespace = @model_namespace
67
- kontroller.before_filter :load_object, :only => (@ok_actions & SINGULAR_PRELOADED_ACTIONS) + @custom_member_actions
68
- kontroller.before_filter :load_objects, :only => (@ok_actions & PLURAL_ACTIONS) + @custom_collection_actions
69
- kontroller.before_filter :load_parent_object, :only => @ok_actions + @custom_member_actions + @custom_collection_actions
71
+ kontroller.before_action :load_object, :only => (@ok_actions & SINGULAR_PRELOADED_ACTIONS) + @custom_member_actions
72
+ kontroller.before_action :load_objects, :only => (@ok_actions & PLURAL_ACTIONS) + @custom_collection_actions
73
+ kontroller.before_action :load_parent_object, :only => @ok_actions + @custom_member_actions + @custom_collection_actions
70
74
  end
71
75
 
72
76
  # :call-seq:
73
77
  # actions(*available_actions)
74
78
  # actions :all
75
- #
79
+ #
76
80
  # Adds the default RESTful actions to the controller.
77
81
  #
78
82
  # If the only argument is <tt>:all</tt>,
@@ -108,25 +112,40 @@ module Resourceful
108
112
  available_actions.each { |action| @ok_actions << action.to_sym }
109
113
  end
110
114
  alias build actions
111
-
115
+
112
116
  # :call-seq:
113
117
  # member_actions(*available_actions)
114
- #
115
- # Registers custom member actions which will use the load_object before_filter.
118
+ # Registers custom member actions which will use the load_object before_action.
116
119
  # These actions are not created, but merely registered for filtering.
117
120
  def member_actions(*available_actions)
118
121
  available_actions.each { |action| @custom_member_actions << action.to_sym }
119
122
  end
120
-
123
+
121
124
  # :call-seq:
122
125
  # collection_actions(*available_actions)
123
- #
124
- # Registers custom collection actions which will use the load_objects before_filter.
126
+ #
127
+ # Registers custom collection actions which will use the load_objects before_action.
125
128
  # These actions are not created, but merely registered for filtering.
126
129
  def collection_actions(*available_actions)
127
130
  available_actions.each { |action| @custom_collection_actions << action.to_sym }
128
131
  end
129
132
 
133
+ # :call-seq:
134
+ # permitted_params(*params_allowed)
135
+ #
136
+ # When using strong parameters, specifies which params are permitted
137
+ #
138
+ # If the only argument is <tt>:all</tt>,
139
+ # all parameters are permitted
140
+ def permitted_params(*params_permitted)
141
+ if params_permitted.first == :all
142
+ @permitted_params = params_permitted.first
143
+ else
144
+ @permitted_params = [] unless @permitted_params.is_a?(Array)
145
+ params_permitted.each { |param| @permitted_params << param.to_sym }
146
+ end
147
+ end
148
+
130
149
  # :call-seq:
131
150
  # before(*events) { ... }
132
151
  #
@@ -148,11 +167,11 @@ module Resourceful
148
167
  # to the current object's title
149
168
  # for the show and edit actions.
150
169
  #
151
- # Successive before blocks for the same action will be chained and executed
170
+ # Successive before blocks for the same action will be chained and executed
152
171
  # in order when the event occurs.
153
172
  #
154
173
  # For example:
155
- #
174
+ #
156
175
  # before :show, :edit do
157
176
  # @page_title = current_object.title
158
177
  # end
@@ -161,7 +180,7 @@ module Resourceful
161
180
  # @side_bar = true
162
181
  # end
163
182
  #
164
- # These before blocks will both be executed for the show action and in the
183
+ # These before blocks will both be executed for the show action and in the
165
184
  # same order as they were defined.
166
185
  def before(*events, &block)
167
186
  add_callback :before, *events, &block
@@ -230,7 +249,7 @@ module Resourceful
230
249
  # end
231
250
  #
232
251
  # This is the same as
233
- #
252
+ #
234
253
  # response_for :new do |format|
235
254
  # format.html { render :action => 'edit' }
236
255
  # end
@@ -277,8 +296,8 @@ module Resourceful
277
296
  #
278
297
  # Then GET /posts/12.yaml would render
279
298
  #
280
- # ---
281
- # post:
299
+ # ---
300
+ # post:
282
301
  # title: Cool Stuff
283
302
  # rendered_content: |-
284
303
  # <p>This is a post.</p>
@@ -331,7 +350,7 @@ module Resourceful
331
350
  :only => [:show, :index]
332
351
  }.merge(Hash === formats.last ? formats.pop : {})
333
352
  raise "Must specify :attributes option" unless options[:attributes]
334
-
353
+
335
354
  Array(options.delete(:only)).each do |action|
336
355
  @publish[action] ||= []
337
356
  formats.each do |format|
@@ -370,7 +389,7 @@ module Resourceful
370
389
  @shallow_parent = options[:shallow]
371
390
  end
372
391
  end
373
-
392
+
374
393
  # Specifies a namespace for the resource model. It can be given as a
375
394
  # Module::NameSpace, 'Module::NameSpace' (in a string), or
376
395
  # 'module/name_space' (underscored form).
@@ -387,7 +406,7 @@ module Resourceful
387
406
  end
388
407
 
389
408
  private
390
-
409
+
391
410
  def apply_publish
392
411
  @publish.each do |action, types|
393
412
  @responses[action.to_sym] ||= []
@@ -395,10 +414,10 @@ module Resourceful
395
414
  end
396
415
  end
397
416
 
398
- def add_callback(type, *events, &block)
417
+ def add_callback(type, *events, &block)
399
418
  events.each do |event|
400
419
  @callbacks[type][event.to_sym] ||= []
401
- @callbacks[type][event.to_sym] << block
420
+ @callbacks[type][event.to_sym] << block
402
421
  end
403
422
  end
404
423
  end
@@ -183,7 +183,16 @@ module Resourceful
183
183
  # of the current object.
184
184
  # This is only meaningful for +create+ or +update+.
185
185
  def object_parameters
186
- params[namespaced_model_name.underscore.tr('/', '_')]
186
+ if params.respond_to?(:permit) && self.class.permitted_params && params[:action].to_s != "new"
187
+ permitable_method = if self.class.permitted_params == :all
188
+ [:permit!]
189
+ else
190
+ [:permit, self.class.permitted_params]
191
+ end
192
+ params.require(namespaced_model_name.underscore.tr('/', '_')).send(*permitable_method)
193
+ else
194
+ params[namespaced_model_name.underscore.tr('/', '_')]
195
+ end
187
196
  end
188
197
 
189
198
  # Returns a list of the names of all the potential parents of the current model.
@@ -194,7 +203,7 @@ module Resourceful
194
203
  #
195
204
  # Note that the parents must be declared via Builder#belongs_to.
196
205
  def parent_names
197
- self.class.parents
206
+ self.class.parent_controllers
198
207
  end
199
208
 
200
209
  # Returns true if an appropriate parent id parameter has been supplied.
@@ -333,7 +342,7 @@ module Resourceful
333
342
  # Assigns the current parent object, as given by parent_objects,
334
343
  # to its proper instance variable, as given by parent_name.
335
344
  #
336
- # This is automatically added as a before_filter.
345
+ # This is automatically added as a before_action.
337
346
  # You shouldn't need to use it directly unless you're creating a new action.
338
347
  def load_parent_object
339
348
  instance_variable_set("@#{parent_name}", parent_object) if parent?
@@ -341,11 +350,11 @@ module Resourceful
341
350
  end
342
351
 
343
352
  # Renders a 422 error if no parent id is given.
344
- # This is meant to be used with before_filter
353
+ # This is meant to be used with before_action
345
354
  # to ensure that some actions are only called with a parent id.
346
355
  # For example:
347
356
  #
348
- # before_filter :ensure_parent_exists, :only => [:create, :update]
357
+ # before_action :ensure_parent_exists, :only => [:create, :update]
349
358
  #
350
359
  def ensure_parent_exists
351
360
  return true if parent?
@@ -11,14 +11,15 @@ module Resourceful
11
11
  def self.extended(base)
12
12
  base.class_attribute :resourceful_callbacks
13
13
  base.class_attribute :resourceful_responses
14
- base.class_attribute :parents
14
+ base.class_attribute :parent_controllers
15
15
  base.class_attribute :shallow_parent
16
16
  base.class_attribute :model_namespace
17
17
  base.class_attribute :made_resourceful
18
-
18
+ base.class_attribute :permitted_params
19
+
19
20
  base.resourceful_callbacks = {}
20
21
  base.resourceful_responses = {}
21
- base.parents = []
22
+ base.parent_controllers = []
22
23
  base.model_namespace = nil
23
24
  base.made_resourceful = false
24
25
  end
@@ -53,7 +54,7 @@ module Resourceful
53
54
  # current_object.current_user = current_user
54
55
  # end
55
56
  # end
56
- #
57
+ #
57
58
  def make_resourceful(options = {}, &block)
58
59
  # :stopdoc:
59
60
  include Resourceful::Base
data/spec/builder_spec.rb CHANGED
@@ -39,8 +39,8 @@ describe Resourceful::Builder, " applied without any modification" do
39
39
  @kontroller.made_resourceful.should be_true
40
40
  end
41
41
 
42
- it "should set load_parent_object as a before_filter for no actions" do
43
- @kontroller.expects(:before_filter).with(:load_parent_object, :only => [])
42
+ it "should set load_parent_object as a before_action for no actions" do
43
+ @kontroller.expects(:before_action).with(:load_parent_object, :only => [])
44
44
  @builder.apply
45
45
  end
46
46
  end
@@ -67,8 +67,8 @@ describe Resourceful::Builder, " with some actions set" do
67
67
  (@kontroller.hidden_actions & @actions).should be_empty
68
68
  end
69
69
 
70
- it "should set load_parent_object as a before_filter for the given actions" do
71
- @kontroller.expects(:before_filter).with(:load_parent_object, :only => [:show, :index, :new, :create])
70
+ it "should set load_parent_object as a before_action for the given actions" do
71
+ @kontroller.expects(:before_action).with(:load_parent_object, :only => [:show, :index, :new, :create])
72
72
  @builder.apply
73
73
  end
74
74
  end
@@ -1,37 +1,41 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
1
+ require_relative './spec_helper'
2
2
 
3
3
  describe Resourceful::Serialize, ".normalize_attributes" do
4
+ def expect_normalize(object)
5
+ expect(Resourceful::Serialize.normalize_attributes(object))
6
+ end
7
+
4
8
  it "should return nil if given nil" do
5
- Resourceful::Serialize.normalize_attributes(nil).should be_nil
9
+ expect_normalize(nil).to be_nil
6
10
  end
7
11
 
8
12
  it "should return a basic hash if given a non-injectable attribute" do
9
- Resourceful::Serialize.normalize_attributes(:foo).should == {:foo => nil}
10
- Resourceful::Serialize.normalize_attributes(12).should == {12 => nil}
13
+ expect_normalize(:foo).to eq({:foo => nil})
14
+ expect_normalize(12).to eq({12 => nil})
11
15
  end
12
16
 
13
17
  it "should return a basic hash with a symbol key if given a string attribute" do
14
- Resourceful::Serialize.normalize_attributes("foo").should == {:foo => nil}
18
+ expect_normalize("foo").to eq({:foo => nil})
15
19
  end
16
20
 
17
21
  it "should preserve hashes" do
18
- Resourceful::Serialize.normalize_attributes({:foo => nil, :bar => nil, :baz => nil}).should ==
19
- {:foo => nil, :bar => nil, :baz => nil}
20
- Resourceful::Serialize.normalize_attributes({:foo => 3, :bar => 1, :baz => 4}).should ==
21
- {:foo => 3, :bar => 1, :baz => 4}
22
- Resourceful::Serialize.normalize_attributes({:foo => 3, :bar => 1, :baz => [:foo, :bar]}).should ==
23
- {:foo => 3, :bar => 1, :baz => [:foo, :bar]}
22
+ expect_normalize({:foo => nil, :bar => nil, :baz => nil}).to eq({:foo => nil, :bar => nil, :baz => nil})
23
+ expect_normalize({:foo => 3, :bar => 1, :baz => 4}).to eq({:foo => 3, :bar => 1, :baz => 4})
24
+ expect_normalize({:foo => 3, :bar => 1, :baz => [:foo, :bar]}).to eq({:foo => 3, :bar => 1, :baz => [:foo, :bar]})
24
25
  end
25
26
 
26
27
  it "should merge injectable attributes into one big hash" do
27
- Resourceful::Serialize.normalize_attributes([:foo, :bar, :baz]).should ==
28
- {:foo => nil, :bar => nil, :baz => nil}
29
- Resourceful::Serialize.normalize_attributes([:foo, :bar, {:baz => nil},
30
- :boom, {:bop => nil, :blat => nil}]).should ==
31
- {:foo => nil, :bar => nil, :baz => nil, :boom => nil, :bop => nil, :blat => nil}
32
- Resourceful::Serialize.normalize_attributes([:foo, :bar, {:baz => 12},
33
- :boom, {:bop => "foo", :blat => [:fee, :fi, :fo]}]).should ==
34
- {:foo => nil, :bar => nil, :baz => 12, :boom => nil, :bop => "foo", :blat => [:fee, :fi, :fo]}
28
+ expect_normalize([:foo, :bar, :baz]).to eq({:foo => nil, :bar => nil, :baz => nil})
29
+ expect_normalize(
30
+ [:foo, :bar, {:baz => nil}, :boom, {:bop => nil, :blat => nil}]
31
+ ).to eq(
32
+ {:foo => nil, :bar => nil, :baz => nil, :boom => nil, :bop => nil, :blat => nil}
33
+ )
34
+ expect_normalize(
35
+ [:foo, :bar, {:baz => 12}, :boom, {:bop => "foo", :blat => [:fee, :fi, :fo]}]
36
+ ).to eq(
37
+ {:foo => nil, :bar => nil, :baz => 12, :boom => nil, :bop => "foo", :blat => [:fee, :fi, :fo]}
38
+ )
35
39
  end
36
40
  end
37
41
 
@@ -63,9 +67,9 @@ describe Array, " of serializable objects" do
63
67
 
64
68
  it "should follow deep attributes for #to_serializable" do
65
69
  @array.to_serializable([:fur, {:friend => :name}]).should ==
66
- [{'fur' => 'brown', 'friend' => {'name' => 'rex'}},
70
+ [{'fur' => 'brown', 'friend' => {'name' => 'rex'}},
67
71
  {'fur' => 'yellow', 'friend' => {'name' => 'rover'}},
68
- {'fur' => 'green', 'friend' => {'name' => 'fido'}}]
72
+ {'fur' => 'green', 'friend' => {'name' => 'fido'}}]
69
73
  end
70
74
 
71
75
  it "should raise an error if #serialize is called without the :attributes option" do
@@ -74,9 +78,9 @@ describe Array, " of serializable objects" do
74
78
 
75
79
  it "should serialize to a hash with a pluralized root for #serialize" do
76
80
  YAML.load(@array.serialize(:yaml, :attributes => [:fur, {:friend => :name}])).should ==
77
- {"cats" => [{'fur' => 'brown', 'friend' => {'name' => 'rex'}},
81
+ {"cats" => [{'fur' => 'brown', 'friend' => {'name' => 'rex'}},
78
82
  {'fur' => 'yellow', 'friend' => {'name' => 'rover'}},
79
- {'fur' => 'green', 'friend' => {'name' => 'fido'}}]}
83
+ {'fur' => 'green', 'friend' => {'name' => 'fido'}}]}
80
84
  end
81
85
 
82
86
  it "should serialize to an XML document with a pluralized root for #serialize(:xml, ...)" do
@@ -92,7 +96,7 @@ describe Array, " of serializable objects" do
92
96
  end
93
97
  end
94
98
 
95
- describe ActiveRecord::Base, " with a few attributes and an association" do
99
+ describe ActiveModel::Base, " with a few attributes and an association" do
96
100
  before :each do
97
101
  @person = stub_model("Person")
98
102
  @party_hat = stub_model("PartyHat")
@@ -124,7 +128,7 @@ describe ActiveRecord::Base, " with a few attributes and an association" do
124
128
  doc = REXML::Document.new(@model.serialize(:xml, :attributes => [:name, :eye_color, {:party_hat => :pattern}]),
125
129
  :ignore_whitespace_nodes => :all)
126
130
  doc.root.name.should == "person"
127
- doc.root.children.find { |e| e.name == "name" }.text.should == "joe"
131
+ doc.root.children.find { |e| e.name == "name" }.text.should == "joe"
128
132
  doc.root.children.find { |e| e.name == "eye-color" }.text.should == "blue"
129
133
 
130
134
  hat = doc.root.children.find { |e| e.name == "party-hat" }
metadata CHANGED
@@ -1,26 +1,25 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: make_resourceful
3
- version: !ruby/object:Gem::Version
4
- version: 1.0.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0.pre.beta
5
5
  platform: ruby
6
- authors:
7
- - Hampton Catlin
8
- autorequire:
6
+ authors:
7
+ - Hampton Lintorn-Catlin
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2014-05-06 00:00:00 Z
11
+ date: 2024-06-26 00:00:00.000000000 Z
13
12
  dependencies: []
14
-
15
- description: " Take back control of your Controllers. Make them awesome. Make them sleek. Make them resourceful.\n"
13
+ description: " Take back control of your Controllers. Make them awesome. Make
14
+ them sleek. Make them resourceful.\n"
16
15
  email: hcatlin@gmail.com
17
16
  executables: []
18
-
19
17
  extensions: []
20
-
21
18
  extra_rdoc_files: []
22
-
23
- files:
19
+ files:
20
+ - README.rdoc
21
+ - Rakefile
22
+ - VERSION
24
23
  - lib/make_resourceful.rb
25
24
  - lib/resourceful/base.rb
26
25
  - lib/resourceful/builder.rb
@@ -46,9 +45,6 @@ files:
46
45
  - lib/resourceful/maker.rb
47
46
  - lib/resourceful/response.rb
48
47
  - lib/resourceful/serialize.rb
49
- - Rakefile
50
- - Readme.rdoc
51
- - VERSION
52
48
  - spec/accessors_spec.rb
53
49
  - spec/actions_spec.rb
54
50
  - spec/base_spec.rb
@@ -62,31 +58,27 @@ files:
62
58
  - spec/urls_spec.rb
63
59
  homepage: http://github.com/hcatlin/make_resourceful
64
60
  licenses: []
65
-
66
61
  metadata: {}
67
-
68
- post_install_message:
62
+ post_install_message:
69
63
  rdoc_options: []
70
-
71
- require_paths:
64
+ require_paths:
72
65
  - lib
73
- required_ruby_version: !ruby/object:Gem::Requirement
74
- requirements:
75
- - &id001
76
- - ">="
77
- - !ruby/object:Gem::Version
78
- version: "0"
79
- required_rubygems_version: !ruby/object:Gem::Requirement
80
- requirements:
81
- - *id001
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
82
76
  requirements: []
83
-
84
- rubyforge_project:
85
- rubygems_version: 2.0.14
86
- signing_key:
77
+ rubygems_version: 3.5.3
78
+ signing_key:
87
79
  specification_version: 4
88
80
  summary: An elegant, structured way to build ActionPack Controllers
89
- test_files:
81
+ test_files:
90
82
  - spec/accessors_spec.rb
91
83
  - spec/actions_spec.rb
92
84
  - spec/base_spec.rb
@@ -98,4 +90,3 @@ test_files:
98
90
  - spec/responses_spec.rb
99
91
  - spec/serialize_spec.rb
100
92
  - spec/urls_spec.rb
101
- has_rdoc:
File without changes