Module: ActiveRecord::ClassMethods

Included in:
Base
Defined in:
lib/reactive_record/active_record/class_methods.rb

Constant Summary collapse

SERVER_METHODS =

ignore any of these methods if they get called on the client. This list should be trimmed down to include only methods to be called as “macros” such as :after_create, etc…

[
  :attribute_type_decorations, :defined_enums, :_validators, :timestamped_migrations, :lock_optimistically, :lock_optimistically=,
  :local_stored_attributes=, :lock_optimistically?, :attribute_aliases?, :attribute_method_matchers?, :defined_enums?,
  :has_many_without_reactive_record_add_changed_method, :has_many_with_reactive_record_add_changed_method,
  :belongs_to_without_reactive_record_add_changed_method, :belongs_to_with_reactive_record_add_changed_method,
  :cache_timestamp_format, :composed_of_with_reactive_record_add_changed_method, :schema_format, :schema_format=,
  :error_on_ignored_order_or_limit, :error_on_ignored_order_or_limit=, :timestamped_migrations=, :dump_schema_after_migration,
  :dump_schema_after_migration=, :dump_schemas, :dump_schemas=, :warn_on_records_fetched_greater_than=,
  :belongs_to_required_by_default, :default_connection_handler, :connection_handler=, :default_connection_handler=,
  :skip_time_zone_conversion_for_attributes, :skip_time_zone_conversion_for_attributes=, :time_zone_aware_types,
  :time_zone_aware_types=, :protected_environments, :skip_time_zone_conversion_for_attributes?, :time_zone_aware_types?,
  :partial_writes, :partial_writes=, :composed_of_without_reactive_record_add_changed_method, :logger, :partial_writes?,
  :after_initialize, :record_timestamps, :record_timestamps=, :after_find, :after_touch, :before_save, :around_save,
  :belongs_to_required_by_default=, :default_connection_handler?, :before_create, :around_create, :before_update, :around_update,
  :after_save, :before_destroy, :around_destroy, :after_create, :after_destroy, :after_update, :_validation_callbacks,
  :_validation_callbacks?, :_validation_callbacks=, :_initialize_callbacks, :_initialize_callbacks?, :_initialize_callbacks=,
  :_find_callbacks, :_find_callbacks?, :_find_callbacks=, :_touch_callbacks, :_touch_callbacks?, :_touch_callbacks=, :_save_callbacks,
  :_save_callbacks?, :_save_callbacks=, :_create_callbacks, :_create_callbacks?, :_create_callbacks=, :_update_callbacks,
  :_update_callbacks?, :_update_callbacks=, :_destroy_callbacks, :_destroy_callbacks?, :_destroy_callbacks=, :record_timestamps?,
  :_synchromesh_scope_args_check, :pre_synchromesh_scope, :pre_synchromesh_default_scope, :do_not_synchronize, :do_not_synchronize?,
  :logger=, :maintain_test_schema, :maintain_test_schema=, :scope, :time_zone_aware_attributes, :time_zone_aware_attributes=,
  :default_timezone, :default_timezone=, :_attr_readonly, :warn_on_records_fetched_greater_than, :configurations, :configurations=,
  :_attr_readonly?, :table_name_prefix=, :table_name_suffix=, :schema_migrations_table_name=, :internal_metadata_table_name,
  :internal_metadata_table_name=, :primary_key_prefix_type, :_attr_readonly=, :pluralize_table_names=, :protected_environments=,
  :ignored_columns=, :ignored_columns, :index_nested_attribute_errors, :index_nested_attribute_errors=, :primary_key_prefix_type=,
  :table_name_prefix?, :table_name_suffix?, :schema_migrations_table_name?, :internal_metadata_table_name?, :protected_environments?,
  :pluralize_table_names?, :ignored_columns?, :store_full_sti_class, :store_full_sti_class=, :nested_attributes_options,
  :nested_attributes_options=, :store_full_sti_class?, :default_scopes, :default_scope_override, :default_scopes=, :default_scope_override=,
  :nested_attributes_options?, :cache_timestamp_format=, :cache_timestamp_format?, :reactive_record_association_keys, :_validators=,
  :has_many, :belongs_to, :composed_of, :belongs_to_without_reactive_record_add_is_method, :_rollback_callbacks, :_commit_callbacks,
  :_before_commit_callbacks, :attribute_type_decorations=, :_commit_callbacks=, :_commit_callbacks?, :_before_commit_callbacks?,
  :_before_commit_callbacks=, :_rollback_callbacks=, :_before_commit_without_transaction_enrollment_callbacks?,
  :_before_commit_without_transaction_enrollment_callbacks=, :_commit_without_transaction_enrollment_callbacks,
  :_commit_without_transaction_enrollment_callbacks?, :_commit_without_transaction_enrollment_callbacks=, :_rollback_callbacks?,
  :_rollback_without_transaction_enrollment_callbacks?, :_rollback_without_transaction_enrollment_callbacks=,
  :_rollback_without_transaction_enrollment_callbacks, :_before_commit_without_transaction_enrollment_callbacks, :aggregate_reflections,
  :_reflections=, :aggregate_reflections=, :pluralize_table_names, :public_columns_hash, :attributes_to_define_after_schema_loads,
  :attributes_to_define_after_schema_loads=, :table_name_suffix, :schema_migrations_table_name, :attribute_aliases,
  :attribute_method_matchers, :connection_handler, :attribute_aliases=, :attribute_method_matchers=, :_validate_callbacks,
  :_validate_callbacks?, :_validate_callbacks=, :_validators?, :_reflections?, :aggregate_reflections?, :include_root_in_json,
  :_reflections, :include_root_in_json=, :include_root_in_json?, :local_stored_attributes, :default_scope, :table_name_prefix,
  :attributes_to_define_after_schema_loads?, :attribute_type_decorations?, :defined_enums=, :suppress, :has_secure_token,
  :generate_unique_secure_token, :store, :store_accessor, :_store_accessors_module, :stored_attributes, :reflect_on_aggregation,
  :reflect_on_all_aggregations, :_reflect_on_association, :reflect_on_all_associations, :clear_reflections_cache, :reflections,
  :reflect_on_association, :reflect_on_all_autosave_associations, :no_touching, :transaction, :after_commit, :after_rollback, :before_commit,
  :before_commit_without_transaction_enrollment, :after_create_commit, :after_update_commit, :after_destroy_commit,
  :after_commit_without_transaction_enrollment, :after_rollback_without_transaction_enrollment, :raise_in_transactional_callbacks,
  :raise_in_transactional_callbacks=, :accepts_nested_attributes_for, :has_secure_password, :has_one, :has_and_belongs_to_many,
  :before_validation, :after_validation, :serialize, :primary_key, :dangerous_attribute_method?, :get_primary_key, :quoted_primary_key,
  :define_method_attribute, :reset_primary_key, :primary_key=, :define_method_attribute=, :attribute_names, :initialize_generated_modules,
  :column_for_attribute, :define_attribute_methods, :undefine_attribute_methods, :instance_method_already_implemented?, :method_defined_within?,
  :dangerous_class_method?, :class_method_defined_within?, :attribute_method?, :has_attribute?, :generated_attribute_methods,
  :attribute_method_prefix, :attribute_method_suffix, :attribute_method_affix, :attribute_alias?, :attribute_alias, :define_attribute_method,
  :update_counters, :locking_enabled?, :locking_column, :locking_column=, :reset_locking_column, :decorate_attribute_type,
  :decorate_matching_attribute_types, :attribute, :define_attribute, :reset_counters, :increment_counter, :decrement_counter,
  :validates_absence_of, :validates_length_of, :validates_size_of, :validates_presence_of, :validates_associated, :validates_uniqueness_of,
  :validates_acceptance_of, :validates_confirmation_of, :validates_exclusion_of, :validates_format_of, :validates_inclusion_of,
  :validates_numericality_of, :define_callbacks, :normalize_callback_params, :__update_callbacks, :get_callbacks, :set_callback,
  :set_callbacks, :skip_callback, :reset_callbacks, :deprecated_false_terminator, :define_model_callbacks, :validate, :validators,
  :validates_each, :validates_with, :clear_validators!, :validators_on, :validates, :_validates_default_keys, :_parse_validates_options,
  :validates!, :_to_partial_path, :sanitize, :sanitize_sql, :sanitize_conditions, :quote_value, :sanitize_sql_for_conditions, :sanitize_sql_array,
  :sanitize_sql_for_assignment, :sanitize_sql_hash_for_assignment, :sanitize_sql_for_order, :expand_hash_conditions_for_aggregates, :sanitize_sql_like,
  :replace_named_bind_variables, :replace_bind_variables, :raise_if_bind_arity_mismatch, :replace_bind_variable, :quote_bound_value, :all,
  :default_scoped, :valid_scope_name?, :scope_attributes?, :before_remove_const, :ignore_default_scope?, :unscoped, :build_default_scope,
  :evaluate_default_scope, :ignore_default_scope=, :current_scope, :current_scope=, :scope_attributes, :base_class, :abstract_class?,
  :finder_needs_type_condition?, :sti_name, :descends_from_active_record?, :abstract_class, :compute_type, :abstract_class=, :table_name, :columns,
  :table_exists?, :columns_hash, :column_names, :attribute_types, :prefetch_primary_key?, :sequence_name, :quoted_table_name, :_default_attributes,
  :type_for_attribute, :inheritance_column, :attributes_builder, :inheritance_column=, :reset_table_name, :table_name=, :reset_column_information,
  :full_table_name_prefix, :full_table_name_suffix, :reset_sequence_name, :sequence_name=, :next_sequence_value, :column_defaults, :content_columns,
  :readonly_attributes, :attr_readonly, :create, :create!, :instantiate, :find, :type_caster, :arel_table, :find_by, :find_by!, :initialize_find_by_cache,
  :generated_association_methods, :arel_engine, :arel_attribute, :predicate_builder, :collection_cache_key, :relation_delegate_class,
  :initialize_relation_delegate_cache, :enum, :collecting_queries_for_explain, :exec_explain, :i18n_scope, :lookup_ancestors, :human_attribute_name,
  :references, :uniq, :maximum, :none, :exists?, :second, :limit, :order, :eager_load, :update, :delete_all, :destroy, :ids, :many?, :pluck, :third,
  :delete, :fourth, :fifth, :forty_two, :second_to_last, :third_to_last, :preload, :sum, :take!, :first!, :last!, :second!, :offset, :select, :fourth!,
  :third!, :third_to_last!, :fifth!, :where, :first_or_create, :second_to_last!, :forty_two!, :first, :having, :any?, :one?, :none?, :find_or_create_by,
  :from, :first_or_create!, :first_or_initialize, :except, :find_or_create_by!, :find_or_initialize_by, :includes, :destroy_all, :update_all, :or,
  :find_in_batches, :take, :joins, :find_each, :last, :in_batches, :reorder, :group, :left_joins, :left_outer_joins, :rewhere, :readonly, :create_with,
  :distinct, :unscope, :calculate, :average, :count_by_sql, :minimum, :lock, :find_by_sql, :count, :cache, :uncached, :connection, :connection_pool,
  :establish_connection, :connected?, :clear_cache!, :clear_reloadable_connections!, :connection_id, :connection_config, :clear_all_connections!,
  :remove_connection, :connection_specification_name, :connection_specification_name=, :retrieve_connection, :connection_id=, :clear_active_connections!,
  :sqlite3_connection, :direct_descendants, :benchmark, :model_name, :with_options, :attr_protected, :attr_accessible
]

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



141
142
143
144
145
146
147
# File 'lib/reactive_record/active_record/class_methods.rb', line 141

def method_missing(name, *args, &block)
  if args.count == 1 && name =~ /^find_by_/ && !block
    find_by(name.gsub(/^find_by_/, "") => args[0])
  elsif !SERVER_METHODS.include?(name)
    raise "#{self.name}.#{name}(#{args}) (called class method missing)"
  end
end

Instance Method Details

#_react_param_conversion(param, opt = nil) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/reactive_record/active_record/class_methods.rb', line 248

def _react_param_conversion(param, opt = nil)
  param = Native(param)
  param = JSON.from_object(param.to_n) if param.is_a? Native::Object
  result = if param.is_a? self
    param
  elsif param.is_a? Hash
    if opt == :validate_only
      klass = ReactiveRecord::Base.infer_type_from_hash(self, param)
      klass == self or klass < self
    else
      if param[primary_key]
        target = find(param[primary_key])
      else
        target = new
      end
      associations = reflect_on_all_associations
      param = param.collect do |key, value|
        assoc = reflect_on_all_associations.detect do |assoc|
          assoc.association_foreign_key == key
        end
        if assoc
          if value
            [assoc.attribute, {id: [value], type: [nil]}]
          else
            [assoc.attribute, [nil]]
          end
        else
          [key, [value]]
        end
      end

      # We do want to be doing something like this, but this breaks other stuff...
      #
      # ReactiveRecord::Base.load_data do
      #   ReactiveRecord::ServerDataCache.load_from_json(Hash[param], target)
      # end

      ReactiveRecord::ServerDataCache.load_from_json(Hash[param], target)
      target
    end
  else
    nil
  end
  result
end

#abstract_class=(val) ⇒ Object



149
150
151
# File 'lib/reactive_record/active_record/class_methods.rb', line 149

def abstract_class=(val)
  @abstract_class = val
end

#abstract_class?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/reactive_record/active_record/class_methods.rb', line 19

def abstract_class?
  defined?(@abstract_class) && @abstract_class == true
end

#allObject



163
164
165
# File 'lib/reactive_record/active_record/class_methods.rb', line 163

def all
  ReactiveRecord::Base.class_scopes(self)[:all] ||= ReactiveRecord::Collection.new(self, nil, nil, self, "all")
end

#all=(collection) ⇒ Object



167
168
169
# File 'lib/reactive_record/active_record/class_methods.rb', line 167

def all=(collection)
  ReactiveRecord::Base.class_scopes(self)[:all] = collection
end

#base_classObject



5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/reactive_record/active_record/class_methods.rb', line 5

def base_class

  unless self < Base
    raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
  end

  if superclass == Base || superclass.abstract_class?
    self
  else
    superclass.base_class
  end

end

#column_namesObject



212
213
214
# File 'lib/reactive_record/active_record/class_methods.rb', line 212

def column_names
  ReactiveRecord::Base.public_columns_hash.keys
end

#columns_hashObject



216
217
218
# File 'lib/reactive_record/active_record/class_methods.rb', line 216

def columns_hash
  ReactiveRecord::Base.public_columns_hash[name] || {}
end

#composed_of(name, opts = {}) ⇒ Object



204
205
206
207
208
209
210
# File 'lib/reactive_record/active_record/class_methods.rb', line 204

def composed_of(name, opts = {})
  Aggregations::AggregationReflection.new(base_class, :composed_of, name, opts)
  define_method(name) { @backing_record.reactive_get!(name, nil) }
  define_method("#{name}=") do |val|
    @backing_record.reactive_set!(name, backing_record.convert(name, val))
  end
end

#define_attribute_methodsObject



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/reactive_record/active_record/class_methods.rb', line 236

def define_attribute_methods
  columns_hash.keys.each do |name|
    next if name == :id
    define_method(name) { @backing_record.reactive_get!(name, nil) }
    define_method("#{name}!") { @backing_record.reactive_get!(name, true) }
    define_method("#{name}=") do |val|
      @backing_record.reactive_set!(name, backing_record.convert(name, val))
    end
    define_method("#{name}_changed?") { @backing_record.changed?(name) }
  end
end

#enum(*args) ⇒ Object



52
53
54
# File 'lib/reactive_record/active_record/class_methods.rb', line 52

def enum(*args)
  # when we implement schema validation we should also implement value checking
end

#find(id) ⇒ Object



44
45
46
# File 'lib/reactive_record/active_record/class_methods.rb', line 44

def find(id)
  base_class.instance_eval {ReactiveRecord::Base.find(self, primary_key, id)}
end

#find_by(opts = {}) ⇒ Object



48
49
50
# File 'lib/reactive_record/active_record/class_methods.rb', line 48

def find_by(opts = {})
  base_class.instance_eval {ReactiveRecord::Base.find(self, opts.first.first, opts.first.last)}
end

#inheritance_columnObject



31
32
33
# File 'lib/reactive_record/active_record/class_methods.rb', line 31

def inheritance_column
  base_class.instance_eval {@inheritance_column_value || "type"}
end

#inheritance_column=(name) ⇒ Object



35
36
37
# File 'lib/reactive_record/active_record/class_methods.rb', line 35

def inheritance_column=(name)
  base_class.instance_eval {@inheritance_column_value = name}
end

#model_nameObject



39
40
41
42
# File 'lib/reactive_record/active_record/class_methods.rb', line 39

def model_name
  # in reality should return ActiveModel::Name object, blah blah
  name
end

#primary_keyObject



23
24
25
# File 'lib/reactive_record/active_record/class_methods.rb', line 23

def primary_key
  base_class.instance_eval { @primary_key_value || :id }
end

#primary_key=(val) ⇒ Object



27
28
29
# File 'lib/reactive_record/active_record/class_methods.rb', line 27

def primary_key=(val)
 base_class.instance_eval {  @primary_key_value = val }
end

#scope(name, body) ⇒ Object



153
154
155
156
157
158
159
160
161
# File 'lib/reactive_record/active_record/class_methods.rb', line 153

def scope(name, body)
  singleton_class.send(:define_method, name) do | *args |
    args = (args.count == 0) ? name : [name, *args]
    ReactiveRecord::Base.class_scopes(self)[args] ||= ReactiveRecord::Collection.new(self, nil, nil, self, args)
  end
  singleton_class.send(:define_method, "#{name}=") do |collection|
    ReactiveRecord::Base.class_scopes(self)[name] = collection
  end
end

#server_method(name, default: nil) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
# File 'lib/reactive_record/active_record/class_methods.rb', line 224

def server_method(name, default: nil)
  server_methods[name] = { default: default }
  define_method(name) do |*args|
    vector = args.count.zero? ? name : [[name]+args]
    @backing_record.reactive_get!(vector, nil)
  end
  define_method("#{name}!") do |*args|
    vector = args.count.zero? ? name : [[name]+args]
    @backing_record.reactive_get!(vector, true)
  end
end

#server_methodsObject



220
221
222
# File 'lib/reactive_record/active_record/class_methods.rb', line 220

def server_methods
  @server_methods ||= {}
end