ruby-hyperloop / reactive-record

The project has moved to Hyperstack!!
https://hyperstack.org/
MIT License
14 stars 2 forks source link

add valid? and invalid? methods #7

Open catmando opened 8 years ago

catmando commented 8 years ago

Probably easiest way to do this without major refactoring is to use the existing save mechanism.

Currently save client passes a "validate" param to the server which is either truthy/falsy.

What we can do is pass :validate_only in the valid param, and call (from the client) the save server side method (inisomorphic_base). This will run the whole save process which is wrapped in a transaction. At the bottom of the save method, it checks the save parameter. Right at that point it should first check the validate parameter and if it is :validate_only then raise and internally defined error class called ValidRollback. Then catch this error outside the transaction block, and report that the record is valid.

Likewise if an error is raised, then right at the normal rescue, we need to check and see if if the exception is because of an invalid record, capture what ever is invalid and report this back to the client.

summary of changes:

client side:

# instance methods module:
def valid?(&block)
  @backing_record.valid?(&block)
end
def invalid?(&block)
  if block
    valid? { |valid| block.call !valid }
  else
    valid?.then { |valid| !valid } # I think.... maybe its Promise.new(!valid)
  end
end

# isomorphic methods:

# add this method at about # line 331
      def valid?(validate, &block)
            models, associations, backing_records = self.class.gather_records([self], force, self)
            backing_records.each { |id, record| record.saving! }
            promise = Promise.new
            HTTP.post(`window.ReactiveRecordEnginePath`+"/save",
              payload: {
                json: {
                  models:       models,
                  associations: associations,
                  validate:     :validate_only
                }.to_json
              }
            ).then do |response|
              begin
                response.json[:models] = response.json[:saved_models].collect do |item|
                  backing_records[item[0]].ar_instance
                end

                response.json[:saved_models].each do | item |
                  backing_records[item[0]].errors! item[3]
                end

                yield response.json[:valid] if block
                promise.resolve response.json[:valid]

                backing_records.each { |id, record| record.saved! }
            end
            promise
      end

# approx line 538:
          # add this check:
          if validate == "validate_only" # I think this is a string at this point
            Raise ValidationRollback
         elsif save
            {success: true, saved_models: saved_models }
          else
            vectors.each { |vector, model| model.reload unless model.nil? or model.new_record? or model.frozen? }
            vectors
          end

# approx line 551:
      rescue ValidationRollback
        {valid: true, valid_models: saved_models}
      rescue Exception => e
        if e.message == ""Could not save all models" && validate == "validate_only"
          {valid: false, valid_models: saved_models}
        else
          ...carry on