-
Notifications
You must be signed in to change notification settings - Fork 18
3 Book Operation examples
@barriehadfield
This example raises some interesting questions
-
currently
acting_user
is defined for the sake of regulation only, and is only available on the server side, inside of regulation. But you are the second person to intuitively believe it should be there... So there is some work to be done to make that happen 👍 -
When sending models back to the server should we send the unsaved state or the last saved state? Both are possible, but certainly just referencing the model in its last saved state is easier. However imagine you were running on the server and you added a
book
to a cart, and then without saving the cart invoked an operation on the cart. You would certainly expect the operation to accept the in-memory cart, and then do stuff to it. So I think in fact we need to send the current unsaved state to the server. If the server saves it, the changes will get reflected by synchromesh. -
This leads to the next point. Lets say an operation is currently authorized for the acting_user. Okay fine. But lets say inside that operation we attempt to access some data that is NOT authorized for that user. Do we accept that as okay or abort and rollback.
# Use case: we have a list of books and want to add one to the users basket
module Components
module Books
class List < React::Component::Base
render(DIV) do
Book.all.each do |book|
li { "Add #{book.name}" }.on(:click) do
AddBookToBasket(book: book) do |outcome|
alert "Failed to add the book" unless outcome.success?
end
end
end
end
end
end
end
module Operations
module Books
class AddBookToBasket < HyperLoop::Operation
param :book, type: Book
def execute
# unless acting_user.basket.include? book
# no need for the unless... if book is already in the basket the next to lines
# will do nothing anyway
acting_user.basket << book #(just like active record, only pushes if book is not already there)
acting_user.save #(unlike active record, we don't save unless there are changes to save)
# end
unless book.interested_users.include? acting_user
book.interested_users << acting_user
book.save
EmailUserAboutBook(book: params.book, user: acting_user)
# would it be better to make this whole execute block server only?
# guess that is my choice - new Operation or make this execute server only
end
# This feels better to me BTW (see my version of the operation below):
UpdateInterestedUsers(book: params.book)
end
end
class UpdateInterestedUsers < HyperLoop::Operation
param :book, type: Book
allow_remote_operation { acting_user }
def execute
return if params.book.interested_users.include? acting_user
params.book.interested_users << acting_user
params.book.save
UserMailer.book_email(acting_user, params.book)
end
end
class EmailUserAboutBook < HyperLoop::Operation
param :book, type: Book
param :user, type: User
allow_operation { acting_user }
execute(:server) do
# client code knows nothing about UserMailer...
UserMailer.book_email(params.user, params.book)
end
end
end
end