On Hyperstack, delete method doesn't update has_many relationship in database

59 Views Asked by At

When I use delete method to update a has_many relationship in a model on Hyperstack, the association is not updated in the database, and the association is deleted only on the front end side.

I have installed rails-hyperstack gem 'edge' branch, on rails 5.1.7

In Main component in this code, Agent#deassign(number) is called when clicking the number in the page.

I am trying to use delete method in Agent#deassign(number) method in this code to delete the association with an issue.

app\hyperstack\components\main.rb

class Main < HyperComponent
  before_mount do
    @current_agent = Agent.first
  end

  render(UL) do
    @current_agent.issues.pluck(:number).each do |num|
      LI do
        num.to_s
      end
        .on(:click) do
          @current_agent.deassign(num)
        end
    end
  end
end

app\hyperstack\models\issue.rb

class Issue < ApplicationRecord
  belongs_to :agent
end

app\hyperstack\models\agent.rb

class Agent < ApplicationRecord
  has_many :issues

  def deassign(number)
    issue_to_deassign = issues.detect { |issue| issue.number == number }
    issues.delete(issue_to_deassign)
  end
end

app\db\schema.rb

...
  create_table "agents", force: :cascade do |t|
    t.string "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
...
  create_table "issues", force: :cascade do |t|
    t.integer "number"
    t.integer "agent_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["agent_id"], name: "index_issues_on_agent_id"
  end

The issue is deleted from the agent.issues array on the front end, and the number disappears from the page as expected.

But the association isn't updated in the database unexpectedly, and the number re-appears when I reload the page.

1

There are 1 best solutions below

1
On BEST ANSWER

Unlike the normal serverside ActiveRecord API you need to explicitly save the item that was removed

issues.delete(issues_to_deassign).save

WHY?

The problem is that deleting an item implies a database save will occur.

Because the browser must be asynchronous with the server, Hyperstack returns a promise for any AR methods that update the database (i.e. save, update, create, etc.) The promise will then resolve when the database update completes.

However the expectation is that the delete method returns the object that was just deleted, thus we have a contradiction.

So there was 3 design choices.

1. Break how delete works, and do the save and return a promise;
2. Have delete do the save, but instead of a promise return the deleted item;
3. Have delete return the item, and let the developer do the save explicitly.

Options 1 and 2, are not good since the make the delete operation inflexible.

Option 3, while breaking the standard semantics of ActiveRecord allows those semantics to be easily implemented if desired (i.e. by adding save to the end) without sacrificing flexibility