I want to infer a decorator in a controller, so I generate a decorator the normal way (rails g decorator) and infer it in the controller. However, when I test with Postman, I get the error:
Could not infer a decorator for Employers::Job
.
The error message shows that my syntax in the controller is incorrect (where .decorate
is used), I don't know where I am going wrong.
I have tried changing the way of writing and specifying the decorator explicitly ( @job = Employers::JobDecorator.find(params[:id]).decorate
), but again this gives a NoMethodError (undefined method `find' for Employers::JobDecorator:Class).
This is part of the controller:
def show
@job = @employer.jobs.find(params[:id])
render json: @job
end
end
This is the decorator at the beginning:
def attributes
#somethings
end
UPDATE 2
Thanks to the suggestion in the comments, things changed after I used Employers::JobDecorator.decorate(@job)
in the controller, but I got a new error. The message says undefined method 'attributes' for nil:NilClass
, the source is a line of code from the following file:
#app/decorators/employer/job_decorator.rb
def attributes
super.merge(
{
id: nil,
emp: nil,
}).delete_if { |k, v|
['class_name'].include?(k)
}
end
What is the reason for this?
UPDATE 3
Following the advice of the comments, I got back to the previous error after changing some of the decorators to the following.
def attrs
model.attributes.merge(
{
The error is "NoMethodError in Employers::JobController#show", and the file pointed to is one of the lines in "config/initializer/active_model/serialization.rb" (last line extracted below):
module ActiveModel
module Serialization
def serializable_hash(options = nil)
options ||= {}
attribute_names = attributes.keys
UPDATE 4
If I change the way decorator is written, the result is still similar to "undefined method `id' for #Employers::JobDecorator:0x00007ff3cdd3f748"
class Employers::JobDecorator < Draper::Decorator
delegate_all
def attributes
{
id: nil,
name: nil,
slug: nil
}
end
end
UPDATE 5
I suspect the reason is that @job is nil, so I added something to the controller, finally solved the problem. I got it in the wrong direction.
Draper infers
the decorator from the object that is decorated and in your scenario is Employers::Job
.
Because the decorator you want to be used has a totally different name, Api::V2::Employers::JobDecorator
, you need to explicitly specify it.
So, Api::V2::Employers::JobDecorator.decorate(@job)
is what you need.
More information, here