Class: ScopeComposer::Scope

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.define_helper(name, proc, *args) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/scope_composer/scope.rb', line 26

def define_helper(name, proc, *args)
  # ensure symbol
  name = name.to_sym
  # define method
  define_method(name) do |*args|
    # otherwise set the value
    instance_exec(*args, &proc)
  end
  # add to scope list
  helpers[name] = proc
end

.define_proc_scope(name, proc, *args) ⇒ Object (protected)



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/scope_composer/scope.rb', line 89

def define_proc_scope(name, proc, *args)
  # ensure symbol
  name = name.to_sym
  # define method
  define_method(name) do |*args|
    # if no value is given, act as a getter and retrieve the value
    return read_scope_attribute(name) if args.compact.blank?
    # otherwise set the value
    instance_exec(*args, &proc)
    # and return self for chaining
    self
  end
  define_method("#{name}=") do |*args|
    self.send( name, *args )
  end
  # add to scope list
  scopes[name] = proc
end

.define_scope(*args) ⇒ Object



22
23
24
# File 'lib/scope_composer/scope.rb', line 22

def define_scope(*args)
  args[1].is_a?(Proc) ? define_proc_scope(*args) : define_simple_scopes(*args)
end

.define_scope_composer(parent_class, scope_type) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/scope_composer/scope.rb', line 6

def define_scope_composer( parent_class, scope_type )
  # define a class method for adding scopes to the composer
  scope_subclass = define_scope_subclass( parent_class, scope_type  )
  # eg. dataset_scope :limit
  parent_class.send(:define_singleton_method, "#{scope_type}_scope") do |*args|
    # act as getter if args are nil
    return scope_subclass if args.first.nil?
    # delegate the scope definition to the sub-class
    scope_subclass.define_scope(*args)
    scope_subclass.define_scope_delegate(parent_class, scope_type, *args)
  end
  parent_class.send(:define_singleton_method, "#{scope_type}_helper") do |*args|
    scope_subclass.define_helper(*args)
  end
end

.define_scope_delegate(parent_class, scope_type, *args) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/scope_composer/scope.rb', line 38

def define_scope_delegate(parent_class, scope_type, *args)
  # options
  options = args.extract_options!
  scope_subclass = self
  # for each scope name
  args.each do |scope_name|
    # skip non text scopes
    next unless scope_name.is_a?(String) || scope_name.is_a?(Symbol)
    # add prefix if required
    method_name = scope_name
    method_name = "#{method_name}_#{scope_type}" if options[:prefix] == true
    # define method
    parent_class.send(:define_singleton_method, method_name) do |*args|
      # delegate the scope to an instance of this scope
      scope_subclass.new.send( scope_name, *args )
    end
  end
end

.define_scope_subclass(parent_class, scope_type) ⇒ Object (protected)



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/scope_composer/scope.rb', line 75

def define_scope_subclass(parent_class, scope_type)
  # the class name
  class_name = "#{scope_type.to_s.camelize}Scope"
  # define the class if it doesn't exist
  unless parent_class.const_defined?(class_name)
    # the new scope class inherits from Scope
    scope_class = Class.new(ScopeComposer::Scope)
    # the class is attached the parent class
    parent_class.const_set class_name, scope_class
  end
  # return the scope class
  "#{parent_class.name}::#{class_name}".constantize
end

.define_simple_scope(name, options) ⇒ Object (protected)



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/scope_composer/scope.rb', line 113

def define_simple_scope(name, options)
  # ensure symbol
  name = name.to_sym
  # define method
  define_method(name) do |*args|
    # without args return the value
    return read_scope_attribute(name) if args.compact.blank?
    # given args, set value
    self.send("#{name}=", args)
    # and return self for chaining
    return self
  end
  define_method("#{name}=") do |*args|
    write_scope_attribute(name, *args)
  end
  # add to scoping list
  scopes[name] = nil
end

.define_simple_scopes(*args) ⇒ Object (protected)



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

def define_simple_scopes(*args)
  options = args.extract_options!
  args.each { |name| define_simple_scope(name, options) }
end

.helper_namesObject



61
62
63
# File 'lib/scope_composer/scope.rb', line 61

def helper_names
  @helper_names ||= helpers.keys
end

.helpersObject



69
70
71
# File 'lib/scope_composer/scope.rb', line 69

def helpers
  @helpers ||= {}
end

.scope_namesObject



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

def scope_names
  @scope_names ||= scopes.keys
end

.scopesObject



65
66
67
# File 'lib/scope_composer/scope.rb', line 65

def scopes
  @scopes ||= {}
end

Instance Method Details

#assign_attributes(*attrs) ⇒ Object



155
156
157
158
159
160
# File 'lib/scope_composer/scope.rb', line 155

def assign_attributes(*attrs)
  attrs = attrs.extract_options!
  attrs.each do |key, value|
    self.send("#{key}=", value) if self.respond_to?("#{key}=")
  end
end

#attributesObject



169
170
171
# File 'lib/scope_composer/scope.rb', line 169

def attributes
  @attributes ||= {}
end

#attributes=(attrs) ⇒ Object



173
174
175
# File 'lib/scope_composer/scope.rb', line 173

def attributes=(attrs)
  @attributes = self.attributes.merge(attrs)
end

#cloneObject



140
141
142
143
144
145
# File 'lib/scope_composer/scope.rb', line 140

def clone
  s = self.class.new
  s.attributes = attributes.clone
  s.scope_attributes = scope_attributes.clone
  s
end

#read_scope_attribute(key) ⇒ Object



147
148
149
# File 'lib/scope_composer/scope.rb', line 147

def read_scope_attribute(key)
  scope_attributes[key]
end

#scope_attributesObject



181
182
183
# File 'lib/scope_composer/scope.rb', line 181

def scope_attributes
  @scope_attributes ||= {}
end

#scope_attributes=(attrs) ⇒ Object



177
178
179
# File 'lib/scope_composer/scope.rb', line 177

def scope_attributes=(attrs)
  @scope_attributes = self.scope_attributes.merge(attrs)
end

#scopedObject



136
137
138
# File 'lib/scope_composer/scope.rb', line 136

def scoped
  self.class.new
end

#where(*args) ⇒ Object



162
163
164
165
166
167
# File 'lib/scope_composer/scope.rb', line 162

def where(*args)
  attrs = args.extract_options!
  attrs.symbolize_keys!
  self.attributes = attrs
  self
end

#write_scope_attribute(key, values) ⇒ Object



151
152
153
# File 'lib/scope_composer/scope.rb', line 151

def write_scope_attribute(key, values)
  scope_attributes[key] = (values.count == 1) ? values.first : values
end