hyperstack-org / hyperstack-org/hyperstack

Client-side ability to refresh a scope

Aperta
#229 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
enhancement
Lingua principale
JavaScript
Stelle
538
Fork
41
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

In some circumstances, it would be very useful for the client to 'refresh' a scope on a model where the client believed a refresh would render new results.

An example would be where the client performed an action (called an API for an example) which the programmer knew modified data outside of the current scope (or the scopes children or even further down the parent-child tree from the scope) and when the API promise resolved, a method could be called which would effectively cause the scope the be refreshed and the UI re-rendered if needed.

Here is an example:

We have a simple model with a scope which is being used to list all workouts for a user used :
```
class Workout < ApplicationRecord
has_many :exercises
belongs_to :user
scope :for_user, ->(id) { where(user_id: id) }
end
```
And an API call based on a Button being pressed in the UI:
```
def generate_workout
HTTP.get("/bridge/generate_workout",
data: { user_id: user.id }).then do |resp|
# alert "pass"
end.fail do |resp|
puts resp.json
alert "failed to generate workout"
end
end
```
Which calls a controller API method (simplified for this example):
```
def generate_workout
params.permit(:user_id)
user_id = params[:user_id]
user = User.find user_id
value = user.generate_workout!
return_code = value ? 200 : 400
render json: { error: @error || "" }, status: return_code
end
```
Which in turn calls a method on a model:
```
def generate_workout!
# select build_workout_for_user is a SQL function whcih acts outside of the Rails context
value = ActiveRecord::Base.connection.execute("select build_workout_for_user(#{self.id})").values
return false if value.first.first == -1
return true
end
```

The code above all work's but the user's list of Workouts do not refresh as the SQL function which is building a workout (making many changes to many tables) happens outside of the Rails context at the Postgres level.

The workaround (today) is to push a notification to the client (from the API method) like this:
```
def generate_workout!
value = ActiveRecord::Base.connection.execute("select build_workout_for_user(#{self.id})").values
return false if value.first.first == -1

workout = Workout.for_user(self.id).last
ReactiveRecord::Broadcast.after_commit :create, workout

return true
end
```

The problem with this workaround is that only the new Workout is pushed (so it is displayed), but the SQL function actually changed other data as well which is not refreshed, nor are the fields of the new Workout fetched - just the fact that a new one has been created is displayed in the UI.

The proposed solution should be that the client could request that a scope be refreshed (in this case, when the promise resolves).

```
HTTP.get("/bridge/generate_workout",
data: { user_id: user.id }).then do |resp|
# now refresh the scope
Workout.for_user(user.id).reload! # <---- this new line
end.fail do |resp|
puts resp.json
alert "faild to generate workout"
end
```

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.