Class: SWS::Slot

Inherits:
Object
  • Object
show all
Defined in:
lib/sws/slot.rb

Overview

Represents a settable parameter of a component. It can have a value bound to itself, thus allowing the developer to make the component customizable.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(component, name) ⇒ Slot

Creates new Slot object Parameters: component - the component this slot belongs to name - slot name



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/sws/slot.rb', line 38

def initialize ( component, name )
	
	@component = component
	@name = name
	@synchronize = component.synchronize_slot?( name ) ? "@#{name}" : nil
	@settable = false
	#@required_type = nil
	@required = nil
	@default = nil
	
end

Instance Attribute Details

#bound_stringObject (readonly)

Literal string that was bound to the slot



31
32
33
# File 'lib/sws/slot.rb', line 31

def bound_string
  @bound_string
end

#componentObject

Component the receiver is contained within



12
13
14
# File 'lib/sws/slot.rb', line 12

def component
  @component
end

#defaultObject

Holds default value for the slot if none bound



24
25
26
# File 'lib/sws/slot.rb', line 24

def default
  @default
end

#nameObject

Name of the binding



15
16
17
# File 'lib/sws/slot.rb', line 15

def name
  @name
end

#requiredObject

Determines whether binding a value to the receiver is obligatory



21
22
23
# File 'lib/sws/slot.rb', line 21

def required
  @required
end

#settableObject

Determines whether the value can be set by the slot (in order to update the bound value in the definition component)



28
29
30
# File 'lib/sws/slot.rb', line 28

def settable
  @settable
end

Instance Method Details

#bind(binding) ⇒ Object

Binds a string to the receiver. As SWS uses YAML now, the parameter can be a regular object, not only a string



53
54
55
# File 'lib/sws/slot.rb', line 53

def bind ( binding )
	@bound_string = binding #binding is a string that is used in value=, so we keep it
end

#bound_objectObject

Returns an object that was bound to the slot. Can be a variable or a method (in that case its return value is used)



60
61
62
# File 'lib/sws/slot.rb', line 60

def bound_object ()
	return object_to_binding( @bound_string )
end

#object_to_binding(object) ⇒ Object

Converts an object retrieved by YAML from .sws file to a value to be bound to a slot



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/sws/slot.rb', line 150

def object_to_binding ( object )

	unless ( object.is_a?( ::String ) )
		return object
	end
	
	if ( object =~ /^'.*'$/ ) #literal string - strip '
		return object[1 .. -2]
	else	#unquoted string - a method
		if ( object =~ /^[A-Z]/ )	# starts with uppercase - class/module method
			module_name, method_string = object.split( /\./, 2 )
			method_object = SWS.get_module( module_name )
		else
			if ( object =~ /^\^/ ) # parent binding
				return @component.definition_component.slots[ object[1 .. -1] ].bound_object()
			else
				method_object = @component.definition_component()
				method_string = object
			end
		end
		# if the method does not exist the exception is raised, so we don't need to check
		while ( md = /^([^.]+)\.(.+)$/.match( method_string ) )
			method_object = method_object.method( md[1] ).call()
			method_string = md [2]
		end
		value = method_object.method( method_string )
		return value
	end
	
end

#to_sObject

Returns string representation of the receiver



183
184
185
# File 'lib/sws/slot.rb', line 183

def to_s () 
	return "Slot - name: #{@name}, component: #{@component}, binding: #{@bound_string}, required: #{@required}, default: #{@default}, settable: #{settable}"
end

#to_tag_attributeObject

Returns default representation of the slot as a tag attribute (that is eg. ‘href=“#href=""href"">slots.value’ for slot named ”href“) if the slot is bound, empty string otherwise



191
192
193
# File 'lib/sws/slot.rb', line 191

def to_tag_attribute ()
	return (@bound_string || @default) ? "#{name}=\"#{value()}\"" : ""
end

#valueObject

Calculates the value that was bound to the receiver (“evaluates” @bound_string) and returns it



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/sws/slot.rb', line 88

def value () 
	
	#component parent is not null, because top-level components (pages)
	#do not have slots		
	if ( bound_object() == nil )
		if ( @required == true )
			raise "Slot #{@name} is a required slot for component #{@component.name}"
		else
			value = @default
		end
	elsif ( bound_object().instance_of?( Method ) )
		value = bound_object().call() 
	else
		value = bound_object()
	end
	#if ( @required_type != nil && value.type.to_s != @required_type )
	#	raise "Slot #{@name} requires value type #{@required_type}, but got #{value.type}"
	#end
	if ( @synchronize )
		component.instance_variable_set( @synchronize, value )
	end
	return value
	
end

#value=(value) ⇒ Object

Updates the value of the object bound



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/sws/slot.rb', line 115

def value= ( value )
	
	string = @bound_string
	if ( @settable == true )
		if ( string =~ /^[A-Z]/ )	# starts with uppercase - class/module method
			module_name, method_string = string.split( /\./, 2 )
			method_object = SWS.get_module( module_name )
		else
			if ( string =~ /^\^/ ) # parent binding
				@component.definition_component.slots[ string[1 .. -1] ].value = value
				return nil
			else
				method_object = @component.definition_component()
				method_string = string
			end
		end
		# if the method not exists the exception will be thrown, so we don't need to check
		while ( md = /^([^.]+)\.(.+)$/.match( method_string ) )
			method_object = method_object.method( md[1] ).call()
			method_string = md [2]
		end
		method = method_object.method( "#{method_string}=" )
		method.call( value )
		if ( @synchronize )
			component.instance_variable_set( @synchronize, value )
		end
	else
		raise "Trying to set #{bound_object()} to #{value} by not settable slot #{self}!"
	end
	
end