Closed thomassnielsen closed 9 years ago
You will have the most control over the returned object if you override the CreateResourceOperation
or create an another operation to use instead based off of CreateResourceOperation
.
The Request
class is what creates the operations. In the controller you could change the action param from create
to say create_or_find
. Then you could then patch the Request
class with a setup_ create_or_find_action
method that would be automatically called based on the action param. In the setup_ create_or_find_action
you could use your custom Operation.
I think that should work, but no promises.
I wasn't able to find an override point for params[:action]
that was early enough. Even in before_action
, the @request
on the controller already had a CreateResourceOperation
queued up.
I ended up with this different but pretty decent solution once I understood more about what Request does:
def create
case params[:data][:attributes][:status]
when 'makeme'
order = Order.find_by status: 'draft', user: current_user
if order.present?
@request.operations = [] # Remove create operation
params[:id] = order.id
@request.setup_show_action params
end
when 'makenew'
order = Order.find_by status: 'draft', user: current_user
if order.present?
order.status = 'stalled'
order.save
end
end
super
end
This works well for us, and unless this becomes a common use case, it might not be worth the hassle to implement it as a feature in JR. Is there a common place to collect DYI solutions like this? I see that quite a few libraries use the Wiki for how-tos. If not, I'll try to throw together a blog post with some more details that people might stumble upon when googling, and link it from this issue.
I wasn't able to find an override point for params[:action] that was early enough. Even in before_action, the @request on the controller already had a CreateResourceOperation queued up.
Try prepend_before_action
. But what you have looks pretty clean too.
Is there a common place to collect DYI solutions like this? I see that quite a few libraries use the Wiki for how-tos. If not, I'll try to throw together a blog post with some more details that people might stumble upon when googling, and link it from this issue.
The Wiki pages would be good for this type of thing. I'll look into setting that up.
Added example to the wiki.
Hello! Can you tell me what's the recommended way to do this now? The example in the wiki doesn't work anymore. I've created a custom operation processor (code below) and it works fine, but the note on the bottom of this page kinda scared me :grin:
Note: The authors of this gem expect the most common uses cases to be handled using the callbacks. It is likely that the internal functionality of the operation processing methods will change, at least for several revisions. Effort will be made to call this out in release notes. You have been warned.
I would implement this using the callbacks but I'm not sure how, and overriding the controller action seems to me as risky as the operation processor.
Here's the code for my operation processor:
class MyCustomProcessor < JSONAPI::Processor
def create_resource
resource = resource_klass.find({}, params).first
if resource.nil?
super
else
JSONAPI::ResourceOperationResult.new(:ok, resource)
end
end
end
Keep up the good work guys and stay awesome! :smile:
Hello! Can you tell me what's the recommended way to do this now? The example in the wiki doesn't work anymore. I've created a custom operation processor (code below) and it works fine, but the note on the bottom of this page kinda scared me š
Note: The authors of this gem expect the most common uses cases to be handled using the callbacks. It is likely that the internal functionality of the operation processing methods will change, at least for several revisions. Effort will be made to call this out in release notes. You have been warned.
I would implement this using the callbacks but I'm not sure how, and overriding the controller action seems to me as risky as the operation processor.
Here's the code for my operation processor:
class MyCustomProcessor < JSONAPI::Processor def create_resource resource = resource_klass.find({}, params).first if resource.nil? super else JSONAPI::ResourceOperationResult.new(:ok, resource) end end end
Keep up the good work guys and stay awesome! š
Hey, thanks for the code, I was just wondering where exactly does this go/how to implement it?
@jesster2k10 Hey :wave: I'm not sure now but as far as I remember, it should automatically use your custom processor, as long as you name it properly. The docs say:
The processor is created based on the resource name, including the namespace
For instance if you called your resource NotificationResource
, your custom processor should be named NotificationProcessor
and be in the same namespace.
We've got a use case (for backwards compatibility) that requires us to return an existing object in certain cases when the client runs a create (POST) request.
As far as I can tell, this is neither explicitly allowed or forbidden by the JSONAPI spec.
Our current workaround is to override self.create on the resource and detect if the client will accept an existing object or not:
This works, except that we want the resource to be returned untouched. Using this method, the resource tries to update the resource with the data from the POST request (which we don't want in this case). Is there a better way to do this?
I know this is a very specific use case, but I wonder if there is or could be a point to override that would make this a bit cleaner. Something like returning a resource that behaves like it was called with a show operation.