hyper-model 0.6.0 → 0.99.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +35 -41
- data/.rspec +2 -0
- data/.travis.yml +33 -0
- data/CHANGELOG.md +34 -0
- data/DOCS.md +735 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +298 -224
- data/{LICENSE → LICENSE.txt} +6 -6
- data/README.md +51 -2
- data/Rakefile +18 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/codeship.database.yml +18 -0
- data/hyper-model.gemspec +62 -36
- data/lib/active_model_client_stubs.rb +16 -0
- data/lib/active_record_base.rb +331 -0
- data/{examples/chat-app/app/assets/images/.keep → lib/acts_as_string.rb} +0 -0
- data/lib/enumerable/pluck.rb +6 -0
- data/lib/hyper-model.rb +59 -8
- data/lib/hyper_model/version.rb +3 -0
- data/lib/hyper_react/input_tags.rb +47 -0
- data/lib/hyperloop/model/load.rb +1 -1
- data/lib/kernel/itself.rb +5 -0
- data/lib/object/tap.rb +7 -0
- data/lib/opal/equality_patches.rb +15 -0
- data/lib/opal/parse_patch.rb +14 -0
- data/lib/opal/set_patches.rb +8 -0
- data/lib/reactive_record/active_record/aggregations.rb +69 -0
- data/lib/reactive_record/active_record/associations.rb +118 -0
- data/lib/reactive_record/active_record/base.rb +10 -0
- data/lib/reactive_record/active_record/class_methods.rb +406 -0
- data/lib/reactive_record/active_record/error.rb +31 -0
- data/lib/reactive_record/active_record/errors.rb +374 -0
- data/lib/reactive_record/active_record/instance_methods.rb +187 -0
- data/lib/reactive_record/active_record/public_columns_hash.rb +44 -0
- data/lib/reactive_record/active_record/reactive_record/backing_record_inspector.rb +36 -0
- data/lib/reactive_record/active_record/reactive_record/base.rb +416 -0
- data/lib/reactive_record/active_record/reactive_record/collection.rb +558 -0
- data/lib/reactive_record/active_record/reactive_record/column_types.rb +75 -0
- data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +236 -0
- data/lib/reactive_record/active_record/reactive_record/getters.rb +133 -0
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +576 -0
- data/lib/reactive_record/active_record/reactive_record/lookup_tables.rb +54 -0
- data/lib/reactive_record/active_record/reactive_record/operations.rb +107 -0
- data/lib/reactive_record/active_record/reactive_record/scoped_collection.rb +62 -0
- data/lib/reactive_record/active_record/reactive_record/setters.rb +194 -0
- data/lib/reactive_record/active_record/reactive_record/unscoped_collection.rb +16 -0
- data/lib/reactive_record/active_record/reactive_record/while_loading.rb +343 -0
- data/lib/reactive_record/active_record_error.rb +4 -0
- data/lib/reactive_record/broadcast.rb +223 -0
- data/lib/reactive_record/engine.rb +11 -0
- data/lib/reactive_record/interval.rb +190 -0
- data/lib/reactive_record/permissions.rb +117 -0
- data/lib/reactive_record/pry.rb +13 -0
- data/lib/reactive_record/reactive_scope.rb +18 -0
- data/lib/reactive_record/scope_description.rb +121 -0
- data/lib/reactive_record/serializers.rb +7 -0
- data/lib/reactive_record/server_data_cache.rb +478 -0
- data/path_release_steps.md +9 -0
- metadata +399 -109
- data/CODE_OF_CONDUCT.md +0 -49
- data/examples/chat-app/.gitignore +0 -21
- data/examples/chat-app/Gemfile +0 -62
- data/examples/chat-app/Gemfile.lock +0 -309
- data/examples/chat-app/README.md +0 -3
- data/examples/chat-app/Rakefile +0 -6
- data/examples/chat-app/app/assets/config/manifest.js +0 -3
- data/examples/chat-app/app/assets/javascripts/application.js +0 -3
- data/examples/chat-app/app/assets/stylesheets/application.scss +0 -33
- data/examples/chat-app/app/controllers/application_controller.rb +0 -3
- data/examples/chat-app/app/controllers/home_controller.rb +0 -5
- data/examples/chat-app/app/hyperloop/components/app.rb +0 -12
- data/examples/chat-app/app/hyperloop/components/formatted_div.rb +0 -15
- data/examples/chat-app/app/hyperloop/components/input_box.rb +0 -26
- data/examples/chat-app/app/hyperloop/components/message.rb +0 -29
- data/examples/chat-app/app/hyperloop/components/messages.rb +0 -8
- data/examples/chat-app/app/hyperloop/components/nav.rb +0 -30
- data/examples/chat-app/app/hyperloop/models/application_record.rb +0 -3
- data/examples/chat-app/app/hyperloop/models/message.rb +0 -6
- data/examples/chat-app/app/hyperloop/operations/operations.rb +0 -13
- data/examples/chat-app/app/hyperloop/stores/message_store.rb +0 -17
- data/examples/chat-app/app/policies/application_policy.rb +0 -9
- data/examples/chat-app/app/views/layouts/application.html.erb +0 -12
- data/examples/chat-app/bin/bundle +0 -3
- data/examples/chat-app/bin/rails +0 -9
- data/examples/chat-app/bin/rake +0 -9
- data/examples/chat-app/bin/setup +0 -34
- data/examples/chat-app/bin/spring +0 -17
- data/examples/chat-app/bin/update +0 -29
- data/examples/chat-app/config.ru +0 -5
- data/examples/chat-app/config/application.rb +0 -12
- data/examples/chat-app/config/boot.rb +0 -3
- data/examples/chat-app/config/cable.yml +0 -9
- data/examples/chat-app/config/database.yml +0 -25
- data/examples/chat-app/config/environment.rb +0 -5
- data/examples/chat-app/config/environments/development.rb +0 -56
- data/examples/chat-app/config/environments/production.rb +0 -86
- data/examples/chat-app/config/environments/test.rb +0 -42
- data/examples/chat-app/config/initializers/application_controller_renderer.rb +0 -6
- data/examples/chat-app/config/initializers/assets.rb +0 -11
- data/examples/chat-app/config/initializers/backtrace_silencers.rb +0 -7
- data/examples/chat-app/config/initializers/cookies_serializer.rb +0 -5
- data/examples/chat-app/config/initializers/filter_parameter_logging.rb +0 -4
- data/examples/chat-app/config/initializers/hyperloop.rb +0 -6
- data/examples/chat-app/config/initializers/inflections.rb +0 -16
- data/examples/chat-app/config/initializers/mime_types.rb +0 -4
- data/examples/chat-app/config/initializers/new_framework_defaults.rb +0 -24
- data/examples/chat-app/config/initializers/session_store.rb +0 -3
- data/examples/chat-app/config/initializers/wrap_parameters.rb +0 -14
- data/examples/chat-app/config/locales/en.yml +0 -23
- data/examples/chat-app/config/puma.rb +0 -47
- data/examples/chat-app/config/routes.rb +0 -5
- data/examples/chat-app/config/secrets.yml +0 -22
- data/examples/chat-app/config/spring.rb +0 -6
- data/examples/chat-app/db/migrate/20170319194429_create_message.rb +0 -9
- data/examples/chat-app/db/schema.rb +0 -48
- data/examples/chat-app/db/seeds.rb +0 -7
- data/examples/chat-app/lib/assets/.keep +0 -0
- data/examples/chat-app/lib/tasks/.keep +0 -0
- data/examples/chat-app/log/.keep +0 -0
- data/examples/chat-app/public/404.html +0 -67
- data/examples/chat-app/public/422.html +0 -67
- data/examples/chat-app/public/500.html +0 -66
- data/examples/chat-app/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/chat-app/public/apple-touch-icon.png +0 -0
- data/examples/chat-app/public/favicon.ico +0 -0
- data/examples/chat-app/public/robots.txt +0 -5
- data/examples/chat-app/test/controllers/.keep +0 -0
- data/examples/chat-app/test/fixtures/.keep +0 -0
- data/examples/chat-app/test/fixtures/files/.keep +0 -0
- data/examples/chat-app/test/helpers/.keep +0 -0
- data/examples/chat-app/test/integration/.keep +0 -0
- data/examples/chat-app/test/mailers/.keep +0 -0
- data/examples/chat-app/test/models/.keep +0 -0
- data/examples/chat-app/test/test_helper.rb +0 -10
- data/examples/chat-app/tmp/.keep +0 -0
- data/examples/chat-app/vendor/assets/javascripts/.keep +0 -0
- data/examples/chat-app/vendor/assets/stylesheets/.keep +0 -0
- data/lib/hyperloop/model/version.rb +0 -5
File without changes
|
data/lib/hyper-model.rb
CHANGED
@@ -1,14 +1,65 @@
|
|
1
|
-
require
|
1
|
+
require 'set'
|
2
2
|
require 'hyperloop-config'
|
3
|
-
|
4
|
-
Hyperloop.import 'hyper-component'
|
5
|
-
Hyperloop.import 'hyper-model'
|
6
|
-
|
3
|
+
require 'hyper-component'
|
7
4
|
if RUBY_ENGINE == 'opal'
|
8
|
-
require 'hyper-
|
5
|
+
require 'hyper-operation'
|
6
|
+
require 'active_support'
|
7
|
+
require 'time'
|
8
|
+
require 'date'
|
9
|
+
require 'kernel/itself' unless Object.instance_methods.include?(:itself)
|
10
|
+
require 'object/tap'
|
11
|
+
require 'active_model_client_stubs'
|
12
|
+
require "reactive_record/active_record_error"
|
13
|
+
require "reactive_record/active_record/errors"
|
14
|
+
require "reactive_record/active_record/error"
|
15
|
+
require "reactive_record/server_data_cache"
|
16
|
+
require "reactive_record/active_record/reactive_record/while_loading"
|
17
|
+
require "reactive_record/active_record/reactive_record/operations"
|
18
|
+
require 'reactive_record/broadcast'
|
19
|
+
require "reactive_record/active_record/reactive_record/isomorphic_base"
|
20
|
+
require 'reactive_record/active_record/reactive_record/dummy_value'
|
21
|
+
require 'reactive_record/active_record/reactive_record/column_types'
|
22
|
+
require "reactive_record/active_record/aggregations"
|
23
|
+
require "reactive_record/active_record/associations"
|
24
|
+
require "reactive_record/active_record/reactive_record/backing_record_inspector"
|
25
|
+
require "reactive_record/active_record/reactive_record/getters"
|
26
|
+
require "reactive_record/active_record/reactive_record/setters"
|
27
|
+
require "reactive_record/active_record/reactive_record/lookup_tables"
|
28
|
+
require "reactive_record/active_record/reactive_record/base"
|
29
|
+
require "reactive_record/active_record/reactive_record/collection"
|
30
|
+
require "reactive_record/active_record/reactive_record/scoped_collection"
|
31
|
+
require "reactive_record/active_record/reactive_record/unscoped_collection"
|
32
|
+
require "reactive_record/interval"
|
33
|
+
require_relative 'active_record_base'
|
34
|
+
require_relative 'reactive_record/scope_description'
|
35
|
+
require "reactive_record/active_record/class_methods"
|
36
|
+
require "reactive_record/active_record/instance_methods"
|
37
|
+
require "reactive_record/active_record/base"
|
38
|
+
require 'hyper_react/input_tags'
|
9
39
|
require 'hyperloop/model/load'
|
40
|
+
require_relative 'hyper_model/version'
|
41
|
+
require_relative 'opal/parse_patch'
|
42
|
+
require_relative 'opal/set_patches'
|
43
|
+
require_relative 'opal/equality_patches'
|
44
|
+
React::IsomorphicHelpers.log(
|
45
|
+
"The gem 'hyper-mesh' is deprecated. Use gem 'hyper-model' instead.", :warning
|
46
|
+
) unless defined? Hyperloop::Model
|
10
47
|
else
|
11
48
|
require 'opal'
|
12
|
-
require 'hyper-
|
13
|
-
|
49
|
+
require 'hyper-operation'
|
50
|
+
require "reactive_record/permissions"
|
51
|
+
require "reactive_record/server_data_cache"
|
52
|
+
require "reactive_record/active_record/reactive_record/operations"
|
53
|
+
require 'reactive_record/broadcast'
|
54
|
+
require "reactive_record/active_record/reactive_record/isomorphic_base"
|
55
|
+
require "reactive_record/active_record/public_columns_hash"
|
56
|
+
require "reactive_record/serializers"
|
57
|
+
require "reactive_record/pry"
|
58
|
+
require_relative 'active_record_base'
|
59
|
+
require 'hyper_model/version'
|
60
|
+
|
61
|
+
Opal.append_path File.expand_path('../sources/', __FILE__).untaint
|
62
|
+
Opal.append_path File.expand_path('../', __FILE__).untaint
|
63
|
+
Opal.append_path File.expand_path('../../vendor', __FILE__).untaint
|
14
64
|
end
|
65
|
+
require 'enumerable/pluck'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Special handling of input tags so they ignore defaultValue (and defaultChecked) values while loading.
|
2
|
+
# This is accomplished by adding a react 'key prop' that tracks whether the default value is loading.
|
3
|
+
# When the default value transitions from loading to loaded the key will be updated causing react to
|
4
|
+
# remount the component with the new default value.
|
5
|
+
# To handle cases where defaultValue (or defaultChecked) is an expression, a proc (or lambda) can be
|
6
|
+
# provided for the default value. The proc will be called, and if it raises the waiting_on_resources
|
7
|
+
# flag then we know that within that expression there is a value still being loaded, and the react
|
8
|
+
# key will be set accordingly.
|
9
|
+
|
10
|
+
module React
|
11
|
+
module Component
|
12
|
+
module Tags
|
13
|
+
%i[INPUT SELECT TEXTAREA].each do |component|
|
14
|
+
remove_method component
|
15
|
+
send(:remove_const, component)
|
16
|
+
tag = component.downcase
|
17
|
+
klass = Class.new(Hyperloop::Component) do
|
18
|
+
collect_other_params_as :opts
|
19
|
+
render do
|
20
|
+
opts = props.dup # should be opts = params.opts.dup but requires next release candiate of hyper-react
|
21
|
+
default_value = opts[:defaultValue] || opts[:defaultChecked]
|
22
|
+
if default_value.respond_to? :call
|
23
|
+
begin
|
24
|
+
saved_waiting_on_resources = React::RenderingContext.waiting_on_resources
|
25
|
+
React::RenderingContext.waiting_on_resources = false
|
26
|
+
default_value = default_value.call
|
27
|
+
opts[:key] = React::RenderingContext.waiting_on_resources
|
28
|
+
if opts[:defaultValue]
|
29
|
+
opts[:defaultValue] = default_value
|
30
|
+
else
|
31
|
+
opts[:defaultChecked] = default_value
|
32
|
+
end
|
33
|
+
ensure
|
34
|
+
React::RenderingContext.waiting_on_resources = !!saved_waiting_on_resources
|
35
|
+
end
|
36
|
+
else
|
37
|
+
opts[:key] = !!default_value.loading?
|
38
|
+
end
|
39
|
+
opts[:value] = opts[:value].to_s if opts.key? :value # this may not be needed
|
40
|
+
React::RenderingContext.render(tag, opts) { children.each(&:render) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
const_set component, klass
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/hyperloop/model/load.rb
CHANGED
data/lib/object/tap.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Date
|
2
|
+
alias broken_equals ==
|
3
|
+
def ==(other)
|
4
|
+
return false unless other.is_a?(Date)
|
5
|
+
broken_equals(other)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Time
|
10
|
+
alias broken_equals ==
|
11
|
+
def ==(other)
|
12
|
+
return false unless other.is_a?(Time)
|
13
|
+
broken_equals(other)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
JSON.parse("test")
|
3
|
+
rescue Exception => e
|
4
|
+
JSON.class_eval do
|
5
|
+
class << self
|
6
|
+
alias old_parse parse
|
7
|
+
end
|
8
|
+
def self.parse(*args, &block)
|
9
|
+
old_parse(*args, &block)
|
10
|
+
rescue Exception => e
|
11
|
+
raise StandardError.new e.message
|
12
|
+
end
|
13
|
+
end unless e.is_a? StandardError
|
14
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def self.reflect_on_all_aggregations
|
6
|
+
base_class.instance_eval { @aggregations ||= [] }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.reflect_on_aggregation(attribute)
|
10
|
+
reflect_on_all_aggregations.detect { |aggregation| aggregation.attribute == attribute }
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
module Aggregations
|
16
|
+
|
17
|
+
class AggregationReflection
|
18
|
+
|
19
|
+
attr_reader :klass_name
|
20
|
+
attr_reader :attribute
|
21
|
+
attr_reader :mapped_attributes
|
22
|
+
attr_reader :constructor
|
23
|
+
|
24
|
+
def construct(args)
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(owner_class, macro, name, options = {})
|
29
|
+
owner_class.reflect_on_all_aggregations << self
|
30
|
+
@owner_class = owner_class
|
31
|
+
@constructor = options[:constructor] || :new
|
32
|
+
@klass_name = options[:class_name] || name.camelize
|
33
|
+
@attribute = name
|
34
|
+
if options[:mapping].respond_to? :collect
|
35
|
+
@mapped_attributes = options[:mapping].collect(&:last)
|
36
|
+
else
|
37
|
+
ReactiveRecord::Base.log("improper aggregate definition #{@owner_class}, :#{name}, class_name: #{@klass_name} - missing mapping", :error)
|
38
|
+
@mapped_attributes = []
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def klass
|
43
|
+
@klass ||= Object.const_get(@klass_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def serialize(object)
|
47
|
+
if object.nil?
|
48
|
+
object # return dummy value if that is what we got
|
49
|
+
else
|
50
|
+
@mapped_attributes.collect { |attr| object.send(attr) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def deserialize(array)
|
55
|
+
if array.nil?
|
56
|
+
array # return dummy value if that is what we got
|
57
|
+
elsif @constructor.respond_to?(:call)
|
58
|
+
@constructor.call(*array)
|
59
|
+
else
|
60
|
+
klass.send(@constructor, *array)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def self.reflect_on_all_associations
|
6
|
+
base_class.instance_eval { @associations ||= superclass.instance_eval { (@associations && @associations.dup) || [] } }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.reflect_on_association(attr)
|
10
|
+
reflection_finder { |assoc| assoc.attribute == attr }
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.reflect_on_association_by_foreign_key(key)
|
14
|
+
reflection_finder { |assoc| assoc.association_foreign_key == key }
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.reflection_finder(&block)
|
18
|
+
found = reflect_on_all_associations.detect do |assoc|
|
19
|
+
assoc.owner_class == self && yield(assoc)
|
20
|
+
end
|
21
|
+
if found
|
22
|
+
found
|
23
|
+
elsif superclass == Base
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
superclass.reflection_finder(&block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
module Associations
|
33
|
+
|
34
|
+
class AssociationReflection
|
35
|
+
|
36
|
+
attr_reader :association_foreign_key
|
37
|
+
attr_reader :attribute
|
38
|
+
attr_reader :macro
|
39
|
+
attr_reader :owner_class
|
40
|
+
attr_reader :source
|
41
|
+
|
42
|
+
def initialize(owner_class, macro, name, options = {})
|
43
|
+
owner_class.reflect_on_all_associations << self
|
44
|
+
@owner_class = owner_class
|
45
|
+
@macro = macro
|
46
|
+
@options = options
|
47
|
+
@klass_name = options[:class_name] || (collection? && name.camelize.sub(/s$/, '')) || name.camelize
|
48
|
+
@association_foreign_key = options[:foreign_key] || (macro == :belongs_to && "#{name}_id") || "#{@owner_class.name.underscore}_id"
|
49
|
+
@source = options[:source] || @klass_name.underscore if options[:through]
|
50
|
+
@attribute = name
|
51
|
+
end
|
52
|
+
|
53
|
+
def through_association
|
54
|
+
return unless @options[:through]
|
55
|
+
@through_association ||= @owner_class.reflect_on_all_associations.detect do |association|
|
56
|
+
association.attribute == @options[:through]
|
57
|
+
end
|
58
|
+
raise "Through association #{@options[:through]} for "\
|
59
|
+
"#{@owner_class}.#{attribute} not found." unless @through_association
|
60
|
+
@through_association
|
61
|
+
end
|
62
|
+
|
63
|
+
alias through_association? through_association
|
64
|
+
|
65
|
+
def through_associations
|
66
|
+
# find all associations that use the inverse association as the through association
|
67
|
+
# that is find all associations that are using this association in a through relationship
|
68
|
+
@through_associations ||= klass.reflect_on_all_associations.select do |assoc|
|
69
|
+
assoc.through_association && assoc.inverse == self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def source_associations
|
74
|
+
# find all associations that use this association as the source
|
75
|
+
# that is final all associations that are using this association as the source in a
|
76
|
+
# through relationship
|
77
|
+
@source_associations ||= owner_class.reflect_on_all_associations.collect do |sibling|
|
78
|
+
sibling.klass.reflect_on_all_associations.select do |assoc|
|
79
|
+
assoc.source == attribute
|
80
|
+
end
|
81
|
+
end.flatten
|
82
|
+
end
|
83
|
+
|
84
|
+
def inverse
|
85
|
+
@inverse ||=
|
86
|
+
through_association ? through_association.inverse : find_inverse
|
87
|
+
end
|
88
|
+
|
89
|
+
def inverse_of
|
90
|
+
@inverse_of ||= inverse.attribute
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_inverse
|
94
|
+
klass.reflect_on_all_associations.each do |association|
|
95
|
+
next if association.association_foreign_key != @association_foreign_key
|
96
|
+
next if association.klass != @owner_class
|
97
|
+
next if association.attribute == attribute
|
98
|
+
return association if klass == association.owner_class
|
99
|
+
end
|
100
|
+
raise "Association #{@owner_class}.#{attribute} "\
|
101
|
+
"(foreign_key: #{@association_foreign_key}) "\
|
102
|
+
"has no inverse in #{@klass_name}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def klass
|
106
|
+
@klass ||= Object.const_get(@klass_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
def collection?
|
110
|
+
[:has_many].include? @macro
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,406 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
alias _new_without_sti_type_cast new
|
6
|
+
|
7
|
+
def new(*args, &block)
|
8
|
+
_new_without_sti_type_cast(*args, &block).cast_to_current_sti_type
|
9
|
+
end
|
10
|
+
|
11
|
+
def base_class
|
12
|
+
unless self < Base
|
13
|
+
raise ActiveRecordError, "#{name} doesn't descend from ActiveRecord"
|
14
|
+
end
|
15
|
+
|
16
|
+
if superclass == Base || superclass.abstract_class?
|
17
|
+
self
|
18
|
+
else
|
19
|
+
superclass.base_class
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def abstract_class?
|
24
|
+
defined?(@abstract_class) && @abstract_class == true
|
25
|
+
end
|
26
|
+
|
27
|
+
def primary_key
|
28
|
+
@primary_key_value ||= (self == base_class) ? :id : base_class.primary_key
|
29
|
+
end
|
30
|
+
|
31
|
+
def primary_key=(val)
|
32
|
+
@primary_key_value = val.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def inheritance_column
|
36
|
+
return nil if @no_inheritance_column
|
37
|
+
@inheritance_column_value ||=
|
38
|
+
if self == base_class
|
39
|
+
@inheritance_column_value || 'type'
|
40
|
+
else
|
41
|
+
superclass.inheritance_column.tap { |v| @no_inheritance_column = !v }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def inheritance_column=(name)
|
46
|
+
@no_inheritance_column = !name
|
47
|
+
@inheritance_column_value = name
|
48
|
+
end
|
49
|
+
|
50
|
+
def model_name
|
51
|
+
@model_name ||= ActiveModel::Name.new(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
def find(id)
|
55
|
+
ReactiveRecord::Base.find(self, primary_key => id)
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_by(opts = {})
|
59
|
+
dealiased_opts = {}
|
60
|
+
opts.each { |attr, value| dealiased_opts[_dealias_attribute(attr)] = value }
|
61
|
+
ReactiveRecord::Base.find(self, dealiased_opts)
|
62
|
+
end
|
63
|
+
|
64
|
+
def enum(*args)
|
65
|
+
# when we implement schema validation we should also implement value checking
|
66
|
+
end
|
67
|
+
|
68
|
+
def serialize(attr, *args)
|
69
|
+
ReactiveRecord::Base.serialized?[self][attr] = true
|
70
|
+
end
|
71
|
+
|
72
|
+
def _dealias_attribute(new)
|
73
|
+
if self == base_class
|
74
|
+
_attribute_aliases[new] || new
|
75
|
+
else
|
76
|
+
_attribute_aliases[new] ||= superclass._dealias_attribute(new)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def _attribute_aliases
|
81
|
+
@_attribute_aliases ||= {}
|
82
|
+
end
|
83
|
+
|
84
|
+
def alias_attribute(new_name, old_name)
|
85
|
+
['', '=', '_changed?'].each do |variant|
|
86
|
+
define_method("#{new_name}#{variant}") { |*args, &block| send("#{old_name}#{variant}", *args, &block) }
|
87
|
+
end
|
88
|
+
_attribute_aliases[new_name] = old_name
|
89
|
+
end
|
90
|
+
|
91
|
+
# ignore any of these methods if they get called on the client. This list should be trimmed down to include only
|
92
|
+
# methods to be called as "macros" such as :after_create, etc...
|
93
|
+
SERVER_METHODS = [
|
94
|
+
:regulate_relationship, :regulate_scope,
|
95
|
+
:attribute_type_decorations, :defined_enums, :_validators, :timestamped_migrations, :lock_optimistically, :lock_optimistically=,
|
96
|
+
:local_stored_attributes=, :lock_optimistically?, :attribute_aliases?, :attribute_method_matchers?, :defined_enums?,
|
97
|
+
:has_many_without_reactive_record_add_changed_method, :has_many_with_reactive_record_add_changed_method,
|
98
|
+
:belongs_to_without_reactive_record_add_changed_method, :belongs_to_with_reactive_record_add_changed_method,
|
99
|
+
:cache_timestamp_format, :composed_of_with_reactive_record_add_changed_method, :schema_format, :schema_format=,
|
100
|
+
:error_on_ignored_order_or_limit, :error_on_ignored_order_or_limit=, :timestamped_migrations=, :dump_schema_after_migration,
|
101
|
+
:dump_schema_after_migration=, :dump_schemas, :dump_schemas=, :warn_on_records_fetched_greater_than=,
|
102
|
+
:belongs_to_required_by_default, :default_connection_handler, :connection_handler=, :default_connection_handler=,
|
103
|
+
:skip_time_zone_conversion_for_attributes, :skip_time_zone_conversion_for_attributes=, :time_zone_aware_types,
|
104
|
+
:time_zone_aware_types=, :protected_environments, :skip_time_zone_conversion_for_attributes?, :time_zone_aware_types?,
|
105
|
+
:partial_writes, :partial_writes=, :composed_of_without_reactive_record_add_changed_method, :logger, :partial_writes?,
|
106
|
+
:after_initialize, :record_timestamps, :record_timestamps=, :after_find, :after_touch, :before_save, :around_save,
|
107
|
+
:belongs_to_required_by_default=, :default_connection_handler?, :before_create, :around_create, :before_update, :around_update,
|
108
|
+
:after_save, :before_destroy, :around_destroy, :after_create, :after_destroy, :after_update, :_validation_callbacks,
|
109
|
+
:_validation_callbacks?, :_validation_callbacks=, :_initialize_callbacks, :_initialize_callbacks?, :_initialize_callbacks=,
|
110
|
+
:_find_callbacks, :_find_callbacks?, :_find_callbacks=, :_touch_callbacks, :_touch_callbacks?, :_touch_callbacks=, :_save_callbacks,
|
111
|
+
:_save_callbacks?, :_save_callbacks=, :_create_callbacks, :_create_callbacks?, :_create_callbacks=, :_update_callbacks,
|
112
|
+
:_update_callbacks?, :_update_callbacks=, :_destroy_callbacks, :_destroy_callbacks?, :_destroy_callbacks=, :record_timestamps?,
|
113
|
+
:pre_synchromesh_scope, :pre_synchromesh_default_scope, :do_not_synchronize, :do_not_synchronize?,
|
114
|
+
:logger=, :maintain_test_schema, :maintain_test_schema=, :scope, :time_zone_aware_attributes, :time_zone_aware_attributes=,
|
115
|
+
:default_timezone, :default_timezone=, :_attr_readonly, :warn_on_records_fetched_greater_than, :configurations, :configurations=,
|
116
|
+
:_attr_readonly?, :table_name_prefix=, :table_name_suffix=, :schema_migrations_table_name=, :internal_metadata_table_name,
|
117
|
+
:internal_metadata_table_name=, :primary_key_prefix_type, :_attr_readonly=, :pluralize_table_names=, :protected_environments=,
|
118
|
+
:ignored_columns=, :ignored_columns, :index_nested_attribute_errors, :index_nested_attribute_errors=, :primary_key_prefix_type=,
|
119
|
+
:table_name_prefix?, :table_name_suffix?, :schema_migrations_table_name?, :internal_metadata_table_name?, :protected_environments?,
|
120
|
+
:pluralize_table_names?, :ignored_columns?, :store_full_sti_class, :store_full_sti_class=, :nested_attributes_options,
|
121
|
+
:nested_attributes_options=, :store_full_sti_class?, :default_scopes, :default_scope_override, :default_scopes=, :default_scope_override=,
|
122
|
+
:nested_attributes_options?, :cache_timestamp_format=, :cache_timestamp_format?, :reactive_record_association_keys, :_validators=,
|
123
|
+
:has_many, :belongs_to, :composed_of, :belongs_to_without_reactive_record_add_is_method, :_rollback_callbacks, :_commit_callbacks,
|
124
|
+
:_before_commit_callbacks, :attribute_type_decorations=, :_commit_callbacks=, :_commit_callbacks?, :_before_commit_callbacks?,
|
125
|
+
:_before_commit_callbacks=, :_rollback_callbacks=, :_before_commit_without_transaction_enrollment_callbacks?,
|
126
|
+
:_before_commit_without_transaction_enrollment_callbacks=, :_commit_without_transaction_enrollment_callbacks,
|
127
|
+
:_commit_without_transaction_enrollment_callbacks?, :_commit_without_transaction_enrollment_callbacks=, :_rollback_callbacks?,
|
128
|
+
:_rollback_without_transaction_enrollment_callbacks?, :_rollback_without_transaction_enrollment_callbacks=,
|
129
|
+
:_rollback_without_transaction_enrollment_callbacks, :_before_commit_without_transaction_enrollment_callbacks, :aggregate_reflections,
|
130
|
+
:_reflections=, :aggregate_reflections=, :pluralize_table_names, :public_columns_hash, :attributes_to_define_after_schema_loads,
|
131
|
+
:attributes_to_define_after_schema_loads=, :table_name_suffix, :schema_migrations_table_name, :attribute_aliases,
|
132
|
+
:attribute_method_matchers, :connection_handler, :attribute_aliases=, :attribute_method_matchers=, :_validate_callbacks,
|
133
|
+
:_validate_callbacks?, :_validate_callbacks=, :_validators?, :_reflections?, :aggregate_reflections?, :include_root_in_json,
|
134
|
+
:_reflections, :include_root_in_json=, :include_root_in_json?, :local_stored_attributes, :default_scope, :table_name_prefix,
|
135
|
+
:attributes_to_define_after_schema_loads?, :attribute_type_decorations?, :defined_enums=, :suppress, :has_secure_token,
|
136
|
+
:generate_unique_secure_token, :store, :store_accessor, :_store_accessors_module, :stored_attributes, :reflect_on_aggregation,
|
137
|
+
:reflect_on_all_aggregations, :_reflect_on_association, :reflect_on_all_associations, :clear_reflections_cache, :reflections,
|
138
|
+
:reflect_on_association, :reflect_on_all_autosave_associations, :no_touching, :transaction, :after_commit, :after_rollback, :before_commit,
|
139
|
+
:before_commit_without_transaction_enrollment, :after_create_commit, :after_update_commit, :after_destroy_commit,
|
140
|
+
:after_commit_without_transaction_enrollment, :after_rollback_without_transaction_enrollment, :raise_in_transactional_callbacks,
|
141
|
+
:raise_in_transactional_callbacks=, :accepts_nested_attributes_for, :has_secure_password, :has_one, :has_and_belongs_to_many,
|
142
|
+
:before_validation, :after_validation, :serialize, :primary_key, :dangerous_attribute_method?, :get_primary_key, :quoted_primary_key,
|
143
|
+
:define_method_attribute, :reset_primary_key, :primary_key=, :define_method_attribute=, :attribute_names, :initialize_generated_modules,
|
144
|
+
:column_for_attribute, :define_attribute_methods, :undefine_attribute_methods, :instance_method_already_implemented?, :method_defined_within?,
|
145
|
+
:dangerous_class_method?, :class_method_defined_within?, :attribute_method?, :has_attribute?, :generated_attribute_methods,
|
146
|
+
:attribute_method_prefix, :attribute_method_suffix, :attribute_method_affix, :attribute_alias?, :attribute_alias, :define_attribute_method,
|
147
|
+
:update_counters, :locking_enabled?, :locking_column, :locking_column=, :reset_locking_column, :decorate_attribute_type,
|
148
|
+
:decorate_matching_attribute_types, :attribute, :define_attribute, :reset_counters, :increment_counter, :decrement_counter,
|
149
|
+
:validates_absence_of, :validates_length_of, :validates_size_of, :validates_presence_of, :validates_associated, :validates_uniqueness_of,
|
150
|
+
:validates_acceptance_of, :validates_confirmation_of, :validates_exclusion_of, :validates_format_of, :validates_inclusion_of,
|
151
|
+
:validates_numericality_of, :define_callbacks, :normalize_callback_params, :__update_callbacks, :get_callbacks, :set_callback,
|
152
|
+
:set_callbacks, :skip_callback, :reset_callbacks, :deprecated_false_terminator, :define_model_callbacks, :validate, :validators,
|
153
|
+
:validates_each, :validates_with, :clear_validators!, :validators_on, :validates, :_validates_default_keys, :_parse_validates_options,
|
154
|
+
:validates!, :_to_partial_path, :sanitize, :sanitize_sql, :sanitize_conditions, :quote_value, :sanitize_sql_for_conditions, :sanitize_sql_array,
|
155
|
+
:sanitize_sql_for_assignment, :sanitize_sql_hash_for_assignment, :sanitize_sql_for_order, :expand_hash_conditions_for_aggregates, :sanitize_sql_like,
|
156
|
+
:replace_named_bind_variables, :replace_bind_variables, :raise_if_bind_arity_mismatch, :replace_bind_variable, :quote_bound_value, :all,
|
157
|
+
:default_scoped, :valid_scope_name?, :scope_attributes?, :before_remove_const, :ignore_default_scope?, :unscoped, :build_default_scope,
|
158
|
+
:evaluate_default_scope, :ignore_default_scope=, :current_scope, :current_scope=, :scope_attributes, :base_class, :abstract_class?,
|
159
|
+
:finder_needs_type_condition?, :sti_name, :descends_from_active_record?, :abstract_class, :compute_type, :abstract_class=, :table_name, :columns,
|
160
|
+
:table_exists?, :columns_hash, :column_names, :attribute_types, :prefetch_primary_key?, :sequence_name, :quoted_table_name, :_default_attributes,
|
161
|
+
:type_for_attribute, :inheritance_column, :attributes_builder, :inheritance_column=, :reset_table_name, :table_name=, :reset_column_information,
|
162
|
+
:full_table_name_prefix, :full_table_name_suffix, :reset_sequence_name, :sequence_name=, :next_sequence_value, :column_defaults, :content_columns,
|
163
|
+
:readonly_attributes, :attr_readonly, :create, :create!, :instantiate, :find, :type_caster, :arel_table, :find_by, :find_by!, :initialize_find_by_cache,
|
164
|
+
:generated_association_methods, :arel_engine, :arel_attribute, :predicate_builder, :collection_cache_key, :relation_delegate_class,
|
165
|
+
:initialize_relation_delegate_cache, :enum, :collecting_queries_for_explain, :exec_explain, :i18n_scope, :lookup_ancestors, :human_attribute_name,
|
166
|
+
:references, :uniq, :maximum, :none, :exists?, :second, :limit, :order, :eager_load, :update, :delete_all, :destroy, :ids, :many?, :pluck, :third,
|
167
|
+
:delete, :fourth, :fifth, :forty_two, :second_to_last, :third_to_last, :preload, :sum, :take!, :first!, :last!, :second!, :offset, :select, :fourth!,
|
168
|
+
:third!, :third_to_last!, :fifth!, :where, :first_or_create, :second_to_last!, :forty_two!, :first, :having, :any?, :one?, :none?, :find_or_create_by,
|
169
|
+
:from, :first_or_create!, :first_or_initialize, :except, :find_or_create_by!, :find_or_initialize_by, :includes, :destroy_all, :update_all, :or,
|
170
|
+
:find_in_batches, :take, :joins, :find_each, :last, :in_batches, :reorder, :group, :left_joins, :left_outer_joins, :rewhere, :readonly, :create_with,
|
171
|
+
:distinct, :unscope, :calculate, :average, :count_by_sql, :minimum, :lock, :find_by_sql, :count, :cache, :uncached, :connection, :connection_pool,
|
172
|
+
:establish_connection, :connected?, :clear_cache!, :clear_reloadable_connections!, :connection_id, :connection_config, :clear_all_connections!,
|
173
|
+
:remove_connection, :connection_specification_name, :connection_specification_name=, :retrieve_connection, :connection_id=, :clear_active_connections!,
|
174
|
+
:sqlite3_connection, :direct_descendants, :benchmark, :model_name, :with_options, :attr_protected, :attr_accessible
|
175
|
+
]
|
176
|
+
|
177
|
+
def method_missing(name, *args, &block)
|
178
|
+
if args.count == 1 && name.start_with?("find_by_") && !block
|
179
|
+
find_by(_dealias_attribute(name.sub(/^find_by_/, "")) => args[0])
|
180
|
+
elsif [].respond_to?(name)
|
181
|
+
all.send(name, *args, &block)
|
182
|
+
elsif name.end_with?('!')
|
183
|
+
send(name.chop, *args, &block).send(:reload_from_db) rescue nil
|
184
|
+
elsif !SERVER_METHODS.include?(name)
|
185
|
+
raise "#{self.name}.#{name}(#{args}) (called class method missing)"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# client side AR
|
190
|
+
|
191
|
+
# Any method that can be applied to an array will be applied to the result
|
192
|
+
# of all instead.
|
193
|
+
# Any method ending with ! just means apply the method after forcing a reload
|
194
|
+
# from the DB.
|
195
|
+
|
196
|
+
# alias pre_synchromesh_method_missing method_missing
|
197
|
+
#
|
198
|
+
# def method_missing(name, *args, &block)
|
199
|
+
# return all.send(name, *args, &block) if [].respond_to?(name)
|
200
|
+
# if name.end_with?('!')
|
201
|
+
# return send(name.chop, *args, &block).send(:reload_from_db) rescue nil
|
202
|
+
# end
|
203
|
+
# pre_synchromesh_method_missing(name, *args, &block)
|
204
|
+
# end
|
205
|
+
|
206
|
+
def create(*args, &block)
|
207
|
+
new(*args).save(&block)
|
208
|
+
end
|
209
|
+
|
210
|
+
def scope(name, *args)
|
211
|
+
opts = _synchromesh_scope_args_check(args)
|
212
|
+
scope_description = ReactiveRecord::ScopeDescription.new(self, name, opts)
|
213
|
+
singleton_class.send(:define_method, name) do |*vargs|
|
214
|
+
all.build_child_scope(scope_description, *name, *vargs)
|
215
|
+
end
|
216
|
+
# singleton_class.send(:define_method, "#{name}=") do |_collection|
|
217
|
+
# raise 'NO LONGER IMPLEMENTED - DOESNT PLAY WELL WITH SYNCHROMESH'
|
218
|
+
# end
|
219
|
+
end
|
220
|
+
|
221
|
+
def default_scope(*args, &block)
|
222
|
+
opts = _synchromesh_scope_args_check([*block, *args])
|
223
|
+
@_default_scopes ||= []
|
224
|
+
@_default_scopes << opts
|
225
|
+
end
|
226
|
+
|
227
|
+
def all
|
228
|
+
ReactiveRecord::Base.default_scope[self] ||=
|
229
|
+
begin
|
230
|
+
root = ReactiveRecord::Collection
|
231
|
+
.new(self, nil, nil, self, 'all')
|
232
|
+
.extend(ReactiveRecord::UnscopedCollection)
|
233
|
+
(@_default_scopes || [{ client: _all_filter }]).inject(root) do |scope, opts|
|
234
|
+
scope.build_child_scope(ReactiveRecord::ScopeDescription.new(self, :all, opts))
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def _all_filter
|
240
|
+
# provides a filter for the all scopes taking into account STI subclasses
|
241
|
+
# note: within the lambda `self` will be the model instance
|
242
|
+
defining_class_is_base_class = base_class == self
|
243
|
+
defining_model_name = model_name.to_s
|
244
|
+
lambda do
|
245
|
+
# have to delay computation of inheritance column since it might
|
246
|
+
# not be defined when class is first defined
|
247
|
+
ic = self.class.inheritance_column
|
248
|
+
defining_class_is_base_class || !ic || self[ic] == defining_model_name
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# def all=(_collection)
|
253
|
+
# raise "NO LONGER IMPLEMENTED DOESNT PLAY WELL WITH SYNCHROMESH"
|
254
|
+
# end
|
255
|
+
|
256
|
+
def unscoped
|
257
|
+
ReactiveRecord::Base.unscoped[self] ||=
|
258
|
+
ReactiveRecord::Collection
|
259
|
+
.new(self, nil, nil, self, 'unscoped')
|
260
|
+
.extend(ReactiveRecord::UnscopedCollection)
|
261
|
+
end
|
262
|
+
|
263
|
+
def finder_method(name)
|
264
|
+
ReactiveRecord::ScopeDescription.new(self, "_#{name}", {})
|
265
|
+
[name, "#{name}!"].each do |method|
|
266
|
+
singleton_class.send(:define_method, method) do |*vargs|
|
267
|
+
all.apply_scope("_#{method}", *vargs).first
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def abstract_class=(val)
|
273
|
+
@abstract_class = val
|
274
|
+
end
|
275
|
+
|
276
|
+
# def scope(name, body)
|
277
|
+
# singleton_class.send(:define_method, name) do | *args |
|
278
|
+
# args = (args.count == 0) ? name : [name, *args]
|
279
|
+
# ReactiveRecord::Base.class_scopes(self)[args] ||= ReactiveRecord::Collection.new(self, nil, nil, self, args)
|
280
|
+
# end
|
281
|
+
# singleton_class.send(:define_method, "#{name}=") do |collection|
|
282
|
+
# ReactiveRecord::Base.class_scopes(self)[name] = collection
|
283
|
+
# end
|
284
|
+
# end
|
285
|
+
|
286
|
+
# def all
|
287
|
+
# ReactiveRecord::Base.class_scopes(self)[:all] ||= ReactiveRecord::Collection.new(self, nil, nil, self, "all")
|
288
|
+
# end
|
289
|
+
#
|
290
|
+
# def all=(collection)
|
291
|
+
# ReactiveRecord::Base.class_scopes(self)[:all] = collection
|
292
|
+
# end
|
293
|
+
|
294
|
+
[:belongs_to, :has_many, :has_one].each do |macro|
|
295
|
+
define_method(macro) do |*args| # is this a bug in opal? saying name, scope=nil, opts={} does not work!
|
296
|
+
name = args.first
|
297
|
+
opts = (args.count > 1 and args.last.is_a? Hash) ? args.last : {}
|
298
|
+
assoc = Associations::AssociationReflection.new(self, macro, name, opts)
|
299
|
+
if macro == :has_many
|
300
|
+
define_method(name) { @backing_record.get_has_many(assoc, nil) }
|
301
|
+
define_method("#{name}=") { |val| @backing_record.set_has_many(assoc, val) }
|
302
|
+
else
|
303
|
+
define_method(name) { @backing_record.get_belongs_to(assoc, nil) }
|
304
|
+
define_method("#{name}=") { |val| @backing_record.set_belongs_to(assoc, val) }
|
305
|
+
end
|
306
|
+
assoc
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def composed_of(name, opts = {})
|
311
|
+
reflection = Aggregations::AggregationReflection.new(base_class, :composed_of, name, opts)
|
312
|
+
if reflection.klass < ActiveRecord::Base
|
313
|
+
define_method(name) { @backing_record.get_ar_aggregate(reflection, nil) }
|
314
|
+
define_method("#{name}=") { |val| @backing_record.set_ar_aggregate(reflection, val) }
|
315
|
+
else
|
316
|
+
define_method(name) { @backing_record.get_non_ar_aggregate(name, nil) }
|
317
|
+
define_method("#{name}=") { |val| @backing_record.set_non_ar_aggregate(reflection, val) }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def column_names
|
322
|
+
ReactiveRecord::Base.public_columns_hash.keys
|
323
|
+
end
|
324
|
+
|
325
|
+
def columns_hash
|
326
|
+
ReactiveRecord::Base.public_columns_hash[name] || {}
|
327
|
+
end
|
328
|
+
|
329
|
+
def server_methods
|
330
|
+
@server_methods ||= {}
|
331
|
+
end
|
332
|
+
|
333
|
+
def server_method(name, default: nil)
|
334
|
+
server_methods[name] = { default: default }
|
335
|
+
define_method(name) do |*args|
|
336
|
+
vector = args.count.zero? ? name : [[name] + args]
|
337
|
+
@backing_record.get_server_method(vector, nil)
|
338
|
+
end
|
339
|
+
define_method("#{name}!") do |*args|
|
340
|
+
vector = args.count.zero? ? name : [[name] + args]
|
341
|
+
@backing_record.get_server_method(vector, true)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
def define_attribute_methods
|
346
|
+
columns_hash.each do |name, column_hash|
|
347
|
+
next if name == primary_key
|
348
|
+
define_method(name) { @backing_record.get_attr_value(name, nil) }
|
349
|
+
define_method("#{name}!") { @backing_record.get_attr_value(name, true) }
|
350
|
+
define_method("#{name}=") { |val| @backing_record.set_attr_value(name, val) }
|
351
|
+
define_method("#{name}_changed?") { @backing_record.changed?(name) }
|
352
|
+
define_method("#{name}?") { @backing_record.get_attr_value(name, nil).present? }
|
353
|
+
end
|
354
|
+
self.inheritance_column = nil if inheritance_column && !columns_hash.key?(inheritance_column)
|
355
|
+
end
|
356
|
+
|
357
|
+
def _react_param_conversion(param, opt = nil)
|
358
|
+
param = Native(param)
|
359
|
+
param = JSON.from_object(param.to_n) if param.is_a? Native::Object
|
360
|
+
result =
|
361
|
+
if param.is_a? self
|
362
|
+
param
|
363
|
+
elsif param.is_a? Hash
|
364
|
+
if opt == :validate_only
|
365
|
+
klass = ReactiveRecord::Base.infer_type_from_hash(self, param)
|
366
|
+
klass == self || klass < self
|
367
|
+
else
|
368
|
+
# TODO: investigate saving .changes here and then replacing the
|
369
|
+
# TODO: changes after the load is complete. In other words preserve the
|
370
|
+
# TODO: changed values as changes while just updating the synced values.
|
371
|
+
target =
|
372
|
+
if param[primary_key]
|
373
|
+
find(param[primary_key])
|
374
|
+
else
|
375
|
+
new
|
376
|
+
end
|
377
|
+
|
378
|
+
associations = reflect_on_all_associations
|
379
|
+
|
380
|
+
param = param.collect do |key, value|
|
381
|
+
assoc = associations.detect do |association|
|
382
|
+
association.association_foreign_key == key
|
383
|
+
end
|
384
|
+
|
385
|
+
if assoc
|
386
|
+
if value
|
387
|
+
[assoc.attribute, { id: [value] }]
|
388
|
+
else
|
389
|
+
[assoc.attribute, [nil]]
|
390
|
+
end
|
391
|
+
else
|
392
|
+
[key, [value]]
|
393
|
+
end
|
394
|
+
end
|
395
|
+
# TODO: verify wrapping with load_data was added so broadcasting works in 1.0.0.lap28
|
396
|
+
ReactiveRecord::Base.load_data do
|
397
|
+
ReactiveRecord::ServerDataCache.load_from_json(Hash[param], target)
|
398
|
+
end
|
399
|
+
target.cast_to_current_sti_type
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
result
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|