solidus icon indicating copy to clipboard operation
solidus copied to clipboard

Fix Spree::Api:LineItemsController#create handling validation errors

Open RyanofWoods opened this issue 3 years ago β€’ 10 comments

Spree::Api:LineItemsController#create calls #add on an OrderContents instance which eventually call #save!. This raises errors if validation fails. #create was not handling these validation errors. In fact, it had an if statement checking for errors on a LineItem, but this could never be returned if errors were raised.

Note, the validation errors have been pushed onto @order. This is also in preparation for when this method will gain the ability to create multiple LineItems from one API request.


I can include changes to the documentation if the code looks good πŸ‘

Checklist:

  • [x] I have followed Pull Request guidelines
  • [x] I have added a detailed description into each commit message
  • [ ] I have updated Guides and README accordingly to this change (if needed)
  • [x] I have added tests to cover this change (if needed)

RyanofWoods avatar Sep 24 '21 10:09 RyanofWoods

@RyanofWoods thanks for this PR! I think it makes sense, although I would like to discuss some doubts that come to my mind.

The first one is about the fact that the focus changes from the line item to the order. Also, I'm wondering if we should add another action (i.e. batch_create) for creating multiple line items and leave this one for a single one.

Then, I wonder if changing the implementation of OrderContents#add to call save instead of save! could fix the issue here without much change to the controller action. I don't see the failure case tested on OrderContents specs, so I guess we're underspecifying the behavior and there may be an opportunity to fix that. WDYT?

spaghetticode avatar Oct 06 '21 13:10 spaghetticode

Hi @spaghetticode, thanks for the review! πŸ™‚

Having another action for adding multiple items would probably be best πŸ‘ If a method gets added to the OrderContents class then the API and Frontend can both utilize it.

Having the OrdersContent use #save instead of #save! would allow more simple logic when adding a variant, instead of having to catch the error and then insert it back in like here. If the change gets done for #add_to_line_item then I think we should do it here for #remove_from_line_item to have consistency.

Do you think there's more of a risk of developers not handling the errors if it doesn't raise? Or it is something we shouldn't worry about.

Note, this change would mean updating the frontend code, however, I currently have a PR open to move this logic out πŸ€” https://github.com/solidusio/solidus/pull/4102

RyanofWoods avatar Oct 07 '21 06:10 RyanofWoods

@RyanofWoods thanks for the detailed explanation ❀️

Well, given that the frontend is leveraging the current behavior I think that changing the way OrderContents#add works becomes less desirable, dealing with the side effects there would complicate things, also considering that AFAIK we tend to limit breaking changes on the frontend.

On the other hand, I think it's still possible to avoid answering with the order in favor of the line item (thus keeping the existing interface also in case of error) with something like this:

def create
  variant = Spree::Variant.find(params[:line_item][:variant_id])

  @line_item = begin
    @order.contents.add(
      variant,
      params[:line_item][:quantity] || 1,
      options: line_item_params[:options].to_h
    )
  rescue ActiveRecord::RecordInvalid => error
    error.record
  end

  if @line_item.persisted?
    respond_with(@line_item, status: 201, default_template: :show)
  else
    invalid_resource!(@line_item)
  end
end

Disclaimer: I didn't try this code thoroughly, so there may be something I'm overlooking

spaghetticode avatar Oct 08 '21 16:10 spaghetticode

Hi @spaghetticode. Sorry for the very late response. I have been thinking about this more deeply.

I am thinking that in the long-term it would be more preferable and be more in line with Solidus to have #save rather than #save!. Do you agree?

If so, perhaps there's a way to achieve this change by using the solidus_starter_frontend.

RyanofWoods avatar Oct 25 '21 07:10 RyanofWoods

@RyanofWoods yes, in general I think using #save would be better so we don't have to resort to error handling, but it would mean much more work, and I'm not sure I'm getting your reference to the solidus_starter_frontend. Also, if we decide to go that way, I think it would be better done in another PR so we don't broaden the scope of this fix too much.

spaghetticode avatar Oct 29 '21 15:10 spaghetticode

The idea is to deprecate solidus_frontend eventually, so maybe we should not worry too much about it. However, changing #add to return false would be a breaking change in itself, so we should manage it accordingly.

I agree that it'd be best to keep the interface for the current end-point and create a new one for the batch action.

waiting-for-dev avatar Nov 08 '21 08:11 waiting-for-dev

BTW, we should make sure that the raising on #add is not used to abort a transaction somewhere else.

waiting-for-dev avatar Nov 08 '21 09:11 waiting-for-dev

Hey, @RyanofWoods! Would you still like to work on it? As a minimal change, we could fix rendering the validation errors to the end-user instead of raising them.

waiting-for-dev avatar Jun 09 '22 10:06 waiting-for-dev

Hey, @RyanofWoods, pinging you again, in case you'd like to complete it πŸ™‚

waiting-for-dev avatar Aug 24 '22 08:08 waiting-for-dev

I will look into this again soon (friday or after my two weeks vacation) @waiting-for-dev

RyanofWoods avatar Aug 24 '22 09:08 RyanofWoods

Codecov Report

Merging #4177 (5946a34) into main (afa4d89) will increase coverage by 0.00%. The diff coverage is 100.00%.

@@           Coverage Diff           @@
##             main    #4177   +/-   ##
=======================================
  Coverage   88.67%   88.67%           
=======================================
  Files         564      564           
  Lines       13894    13894           
=======================================
+ Hits        12320    12321    +1     
+ Misses       1574     1573    -1     
Impacted Files Coverage Ξ”
...app/controllers/spree/api/line_items_controller.rb 96.96% <100.00%> (+3.03%) :arrow_up:

:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more

codecov[bot] avatar Oct 31 '22 14:10 codecov[bot]

Rebased

RyanofWoods avatar Jul 21 '23 15:07 RyanofWoods