class RenderSync::Scope

Attributes

args[RW]
scope_definition[RW]
valid[RW]

Public Class Methods

new(scope_definition, args) click to toggle source
# File lib/render_sync/scope.rb, line 5
def initialize(scope_definition, args)
  @scope_definition = scope_definition
  @args = args
end
new_from_args(scope_definition, args) click to toggle source

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

# 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) click to toggle source

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

# 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

Public Instance Methods

args_path() click to toggle source

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

# 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) click to toggle source

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.

# 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?() click to toggle source
# File lib/render_sync/scope.rb, line 57
def invalid?
  !valid?
end
method_missing(method, *args, &block) click to toggle source

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)

# File lib/render_sync/scope.rb, line 108
def method_missing(method, *args, &block)
  relation.send(method, *args, &block)
end
polymorphic_path() click to toggle source

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"
# File lib/render_sync/scope.rb, line 100
def polymorphic_path
  Pathname.new('/').join(*([scope_definition.name.to_s, args_path].flatten))
end
relation() click to toggle source

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

# File lib/render_sync/scope.rb, line 41
def relation
  scope_definition.lambda.call(*args)
end
valid?() click to toggle source

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

# 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