Weird question for y'all... this time it's more of...
# support
g
Weird question for y'all... this time it's more of a "what's the solidus way to handle this" question We've got checkout pulled onto 1 page. It's terrible, I don't like it, but it is what it is. For this, though, I don't think that makes a difference, just mentioning it on the off chance it does. It's a sort of "stepped" one-page checkout, where it still steps through all the different parts solidus needs, but it shows everything on 1 page. We needed to add an extra address to the order. We have the billing address and the shipping address, but we needed a "subscriber address" that could be different. We also needed some extra fields attached to that address. That part wasn't too bad, I added a new address attributes in
spree.rb
, set up the association with the new address to the order, all the new fields show up just like I want them to. The fun comes from the client wanting to move one of the new fields to a different section in the checkout. It worked perfectly when it was in the address step, but they want it all the way out on the confirm step. I've got some code in the update method of
checkouts_controller.rb
that logs out the value I want, has everything I need, but when I try to save the value (still associated with the address for now) I get:
Copy code
ActiveRecord::ReadOnlyRecord in CheckoutsController#update
Spree::Address is marked as readonly
The code I'm trying to use is:
Copy code
@order.sub_address.lockbox_code = params['order']['checkout_confirm_attributes']['lockbox_code']
                    @order.save!
I've also tried instantiating a Spree::Address model specifically to update it directly instead of through the relationships, in case that made a difference, but it gave the same result. I saw this but that looks like how the controller is doing it now:
Copy code
Spree::OrderUpdateAttributes.new(@order, update_params, request_env: request.headers.env).apply
but while I work on that I was wondering if I was just taking the wrong approach entirely 😛
k
Addresses are read only so you can’t just edit them. Under the hood, the order is creating a new address when you change it, see https://github.com/solidusio/solidus/blob/main/core/app/models/spree/order.rb#L645-L651. Maybe it’s a matter of defining a similar method, but for your sub_address, like
Copy code
def sub_address_attributes=(attributes)
      self.sub_address = Spree::Address.immutable_merge(sub_address, attributes)
    end
At that point, your code should allow to save it!
g
You're correct! I was able to save it on the address step, and I do remember needing the piece you mention to be able to do that. I was only having an issue with one of the extra fields that I was trying to pass through in a different step of the checkout. They wanted the "lock box code" to not be entered with the address (where it worked as expected), they wanted the customer to be able to enter it on the "confirm" step instead (for... reasons). I was able to get it to save with this:
Copy code
new_params[:sub_address_attributes][:lockbox_code] = params['order']['checkout_confirm_attributes']['lockbox_code']
Spree::OrderUpdateAttributes.new(@order, new_params, request_env: request.headers.env).apply
After testing this, I saw the value that I entered in the confirm step get saved and appear in the admin.