ruby-hyperloop / hyper-mesh

The project has moved to Hyperstack!! - Synchronization of active record models across multiple clients using Pusher, ActionCable, or Polling
https://hyperstack.org/
MIT License
22 stars 12 forks source link

Inability to set instance variables remotely regression #105

Open sfcgeorge opened 6 years ago

sfcgeorge commented 6 years ago

In a few places we have used attr_accessor to allow us to set flags and whatnot remotely. In old versions this just worked, aka you assign on the client and it gets sent via execute_remote and is assigned on the server. In lap27 it changed slightly, you'd have to do server_method(:ivar) {} which for some reason enabled ivar = "bar" to work. In lap28 it doesn't work at all. I'm assuming Hyperloop uses the columns has to decide what is assignable.

user.field = "foo" # setting a field works
user.ivar = "bar" # setting an instance variable doesn't get sent to server

This was probably never intended behaviour but it is useful. E.g.:

My temporary workaround is to screw with public_columns_hash to add the virtual attributes we need. This seems brittle so it would be nice to have a supported way of sending ivars over Hypermesh.

  module ActiveRecord
    class Base
      def self.public_columns_hash
        return @public_columns_hash if @public_columns_hash && Rails.env.production?
        files = []
        Hyperloop.public_model_directories.each do |dir|
          dir_length = Rails.root.join(dir).to_s.length + 1
          Dir.glob(Rails.root.join(dir, '**', '*.rb')).each do |file|
            require_dependency(file) # still the file is loaded to make sure for development and test env
            files << file[dir_length..-4]
          end
        end
        @public_columns_hash = {}
        # descendants only works for already loaded models!
        descendants.each do |model|
          if files.include?(model.name.underscore) && model.name.underscore != 'application_record'
            @public_columns_hash[model.name] = model.columns_hash.clone rescue nil # why rescue? | extremely important .clone
            begin
              @public_columns_hash[model.name]["force_validate"] = User.columns_hash["first_name"].clone # just stealing a string field as a template
              @public_columns_hash[model.name]["force_validate"].instance_variable_set(:@name, "force_validate") # correct the name
              @public_columns_hash[model.name]["force_validate"].instance_variable_set(:@table_name, model.table_name) # correct the table
            rescue
            end
          end
        end
        @public_columns_hash
      end
    end
  end