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.:
For uploading avatars we base64 encode them and assigned to a data_avatar= then on the server process, save, and assign the real file to avatar.
To enable partial validations during a very long signup flow we had a force_validate= that took an array of fields, then we checked that on the server with conditional validations.
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
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 doserver_method(:ivar) {}
which for some reason enabledivar = "bar"
to work. In lap28 it doesn't work at all. I'm assuming Hyperloop uses the columns has to decide what is assignable.This was probably never intended behaviour but it is useful. E.g.:
data_avatar=
then on the server process, save, and assign the real file toavatar
.force_validate=
that took an array of fields, then we checked that on the server with conditional validations.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.