Class: RenderSync::Scope

Inherits:
Object
  • Object
show all
Defined in:
lib/render_sync/scope.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope_definition, args) ⇒ Scope

Returns a new instance of Scope.



5
6
7
8
# File 'lib/render_sync/scope.rb', line 5

def initialize(scope_definition, args)
  @scope_definition = scope_definition
  @args = args
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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

Delegate all undefined methods to the relation, so that the scope behaves like an ActiveRecord::Relation, e.g. call count on the relation (User.in_group(group).count)



108
109
110
# File 'lib/render_sync/scope.rb', line 108

def method_missing(method, *args, &block)
  relation.send(method, *args, &block)
end

Instance Attribute Details

#argsObject

Returns the value of attribute args.



3
4
5
# File 'lib/render_sync/scope.rb', line 3

def args
  @args
end

#scope_definitionObject

Returns the value of attribute scope_definition.



3
4
5
# File 'lib/render_sync/scope.rb', line 3

def scope_definition
  @scope_definition
end

#validObject

Returns the value of attribute valid.



3
4
5
# File 'lib/render_sync/scope.rb', line 3

def valid
  @valid
end

Class Method Details

.new_from_args(scope_definition, args) ⇒ Object

Return a new sync scope by passing a scope definition (containing a lambda and parameter names) and a set of arguments to be handed over to the lambda



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/render_sync/scope.rb', line 12

def self.new_from_args(scope_definition, args)
  if args.length != scope_definition.parameters.length
    raise ArgumentError, "wrong number of arguments (#{args.length} for #{scope_definition.parameters.length})"
  end

  # Classes currently supported as Arguments for the sync scope lambda
  supported_arg_types = [Fixnum, Integer, ActiveRecord::Base]

  # Check passed args for types. Raise ArgumentError if arg class is not supported
  args.each_with_index do |arg, i|

    unless supported_arg_types.find { |klass| break true if arg.is_a?(klass) }
      param = scope_definition.parameters[i]
      raise ArgumentError, "invalid argument '#{param}' (#{arg.class.name}). Currently only #{supported_arg_types.map(&:name).join(", ")} are supported"
    end
  end
  
  new(scope_definition, args)
end

.new_from_model(scope_definition, model) ⇒ Object

Return a new sync scope by passing a scope definition (containing a lambda and parameter names) and an ActiveRecord model object. The args List will be filled with the model attributes corrensponding to the parameter names defined in the scope_definition



35
36
37
# File 'lib/render_sync/scope.rb', line 35

def self.new_from_model(scope_definition, model)
  new(scope_definition, scope_definition.parameters.map { |p| model.send(p) })
end

Instance Method Details

#args_pathObject

Generates an Array of path elements based on the given lambda args and their name which is saved in scope_definition.parameters



78
79
80
81
82
83
84
85
86
# File 'lib/render_sync/scope.rb', line 78

def args_path
  scope_definition.parameters.each_with_index.map do |parameter, i| 
    if args[i].is_a? ActiveRecord::Base
      [parameter.to_s, args[i].send(args[i].class.primary_key).to_s]
    else
      [parameter.to_s, args[i].to_s] 
    end
  end.flatten
end

#contains?(record) ⇒ Boolean

Check if the given record falls under the narrowing by the stored ActiveRecord Relation. Depending on the arguments set in args this can lead to an exception (e.g. when a nil is passed) Also set the value of valid to avoid another DB query.

Returns:

  • (Boolean)


65
66
67
68
69
70
71
72
73
# File 'lib/render_sync/scope.rb', line 65

def contains?(record)
  begin
    val = relation.exists?(record.id)
    @valid = true # set valid to true, if relation.exists?(model) does not throw any exception
    val
  rescue
    @valid = false
  end
end

#invalid?Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/render_sync/scope.rb', line 57

def invalid?
  !valid?
end

#polymorphic_pathObject

Returns the Pathname for this scope Example:

class User < ActiveRecord::Base
  sync :all
  belongs_to :group
  sync_scope :in_group, ->(group) { where(group_id: group.id) }
end

group = Group.first
User.in_group(group).polymorphic_path.to_s
# => "/in_group/group/1"


100
101
102
# File 'lib/render_sync/scope.rb', line 100

def polymorphic_path
  Pathname.new('/').join(*([scope_definition.name.to_s, args_path].flatten))
end

#relationObject

Return the ActiveRecord Relation by calling the lamda with the given args.



41
42
43
# File 'lib/render_sync/scope.rb', line 41

def relation
  scope_definition.lambda.call(*args)
end

#valid?Boolean

Check if the combination of stored AR relation and args is valid by calling exists? on it. This may raise an exception depending on the args, so we have to rescue the block

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
# File 'lib/render_sync/scope.rb', line 48

def valid?
  @valid ||= begin 
    relation.exists?
    true # set valid to true, if relation.exists?(model) does not throw any exception
  rescue
    false
  end
end