Giter VIP home page Giter VIP logo

Comments (4)

richmolj avatar richmolj commented on May 21, 2024 1

I'm definitely open to more options/injectables around persistence. That said, I'm not sure I agree with that abstraction - I like the premise of an OrderResource persists an Order, an AddressResource persists an Address, and a CompoundOrderResource is persisted by a CompoundOrderService that coordinates multiple resources. Cross-pollinating these sounds like we'd end up with some confusing "who does what where" issues, and some "unexpected side-effect" issues similar to what you've seen before with callbacks.

I do think there is probably something to the idea of a JsonapiCompliable::CompoundResource concept, but I'd like to hear more about these scenarios and problems with the existing paradigm before digging too deep. Maybe you could start down the CompoundOrderResource route and let me know any problems you run into?

from graphiti.

richmolj avatar richmolj commented on May 21, 2024

Hi Derek - great question. I think I have an answer for you, the documentation just hasn't caught up yet. In your example, you could do something like this:

class AddressResource < JsonapiCompliable::Resource
  # ... code ...
  def create(attributes, parent) # note the optional second arg here
    address = Address.new(attributes)
    if parent.is_a?(Order)
      address.geocode
        .time_in_new_timezone(parent.some_time, address.timezone)
    end
    address.save
    address
  end
end

Note the check on parent here - since multiple objects could (in theory) sidepost an address, we should verify it's an Order doing the sideposting.

Another option would be the after_save hooks within the parent. I haven't written a how-to yet, but you can see examples in the tests. One way:

# OrderResource
belongs_to :address,
  foreign_key: :order_id,
  scope: -> { Address.all },
  resource: AddressResource do
    after_save only: [:create, update] do |order, addresses|
      # addresses is always an array regardless of has-many/belongs-to
      address = addresses.first
      address.geocode(order.some_time, address.timezone)
      address.save
    end

For both of these examples, you'll already be within a transaction. Make sure to define #transaction in your adapter if not using activerecord.

Does either of those work for you?

from graphiti.

richmolj avatar richmolj commented on May 21, 2024

And by the way, as you noted earlier - another option is to simply post a CompoundOrder object, rather than sideposting the address. In this case you'd have a CompoundOrder resource and the attributes could be whatever structure you want, and you could do whatever you want within the relevant resource methods. I think this is less than ideal, but it's what a lot of RESTful folks did/do before jsonapi introduced sideposting, so no worse than the status quo as a last resort.

from graphiti.

derekcannon avatar derekcannon commented on May 21, 2024

Thanks for the quick reply! Having access to the parent is definitely helpful. I want to avoid callbacks as much as possible; it's gotten us into a lot of trouble in our past API.

I am thinking at this point the compound object would be best. Ideally, I'd like to define a central place where things are happening to an order, so it's easy to see what effects are taking place.

Another option, for future consideration, might be the ability to specify which resource handles the create/update for a relationship. Something like:

# app/resources/order_resource.rb
class OrderResource < ApplicationResource
  type :orders
  model Order

  has_one :address,
          resource: AddressResource,
          persisted_by: :self, # something to specify OrderResource is handling address params
          scope: -> { Address.all },
          foreign_key: :address_id
end

This way, AddressResource can operate as normal in any situation and not know about the custom requirements for OrderResource, while OrderResource is smart enough to handle address params in a certain way. What do you think?

from graphiti.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.