Miscellaneous
Utilities & Helpers
Origen provides some general-purpose utlity classes and modules that can help you to better develop your applications, plugins, and other features. The following is a list of the utilities currently implemented by Origen:
Unfortunately this guide has not been written yet, but it is an area that is on our road map.
Please comment below to let us know that you were looking for it, this will help us to prioritize which sections to write next.
If you need help on this item in the meantime, please ask a question in the Origen forum.
You may notice some features within Origen, such as registers
, bits
, or anything
that uses componentable
to instantiate, are able to take either an options hash
or an
options block
and merge the two, allowing users to work with whichever is preferred. Under the
hood of these features, is the Collector
, which allows for a block to be transformed
into a hash
and can then be used as options for the given feature.
The collector is available at Origen::Utility::Collector
, but a shortcut method to create a new instance is
available as Origen::Utility.collector
. The collector isn’t really meant to be used throughout, rather
it is an intermediary step to join hashes and blocks. An example of using the collector is:
block = Proc.new do |collector|
collector.arg1 'argument 1'
collector.arg2 'argument 2'
end
collector = Origen::Utility.collector
block.call(collector)
collector.to_h
#=> {arg1: 'argument 1', arg2: 'argument 2'}
The result of using the collector is that each argument given as a method is transformed into a hash key/value pair.
No Value Given
If a method is given without a value, it will be defined and set to nil
, as shown below:
block = Proc.new do |collector|
collector.arg1
end
collector = Origen::Utility.collector
block.call(collector)
collector.to_h
#=> {arg1: nil}
As previously stated, one use of the collector is to transform an option block
into an option hash
and/or merge an existingoption hash
and the resulting option hash
. This allows for options
to be given either as a hash or as a block or both, depending on the nature of the options and the preference of the user. In
these cases, it is common to just instantiate the collector, convert it to a hash, then throw it away. This can
be done in a single line as:
collector = Origen::Utility.collector(&block).to_h
The collector allows for automatic hash merging
. The intent is to easily allow for an options hash
and an options block
to merge into a single combined hash
. This can be achieved by passing in
two options during collector initialization: hash
and merge_method
.
# Combining a hash and block with no clashes
options = {argA: 'arg A', argB: 'arg B'}
block = Proc.new do |collector|
collector.arg1 'arg 1'
collector.arg2 'arg 2'
end
Origen::Utility.collector(hash: options, &block).to_h
#=> {argA: 'arg A', argB: 'arg B', arg1: 'arg 1', arg2: 'arg 2'}
# Combining a hash and block with some keys clashing (default merging)
options = {arg1: 'has arg 1', arg2: 'hash arg 2'}
block = Proc.new do |collector|
collector.arg2 'block arg 2'
collector.arg3 'block arg 3'
end
Origen::Utility.collector(hash: options, &block).to_h
#=> {arg1: 'has arg 1', arg2: 'hash arg 2', arg3: 'block arg 3'}
# Combining a hash and block with explicit merge method :keep_hash (default)
options = {arg1: 'has arg 1', arg2: 'hash arg 2'}
block = Proc.new do |collector|
collector.arg2 'block arg 2'
collector.arg3 'block arg 3'
end
Origen::Utility.collector(hash: options, merge_method: :keep_hash, &block).to_h
#=> {arg1: 'has arg 1', arg2: 'hash arg 2', arg3: 'block arg 3'}
As shown, of the options that were given to both the hash and the block, the options in the hash were kept. This is the
default behavior, or can be explicitly defined by providing merge_method: :keep_hash
to avoid confusion.
Two other merge method exists: :keep_block
and :fail
. :keep_block
is just the
opposite of :keep_hash
and :fail
will raise an error if the same option is provided by
both the hash and the block. Trying to set the merge_method
to anything else will raise an error.
options = {arg1: 'has arg 1', arg2: 'hash arg 2'}
block = Proc.new do |collector|
collector.arg2 'block arg 2'
collector.arg3 'block arg 3'
end
Origen::Utility.collector(hash: options, merge_method: :keep_block, &block).to_h
#=> {arg1: 'has arg 1', arg2: 'block arg 2', arg3: 'block arg 3'}
options = {arg1: 'has arg 1', arg2: 'hash arg 2'}
block = Proc.new do |collector|
collector.arg3 'block arg 3'
end
Origen::Utility.collector(hash: options, merge_method: :fail, &block).to_h
#=> {arg1: 'has arg 1', arg2: 'hash arg 2', arg3: 'block arg 3'}
options = {arg1: 'has arg 1', arg2: 'hash arg 2'}
block = Proc.new do |collector|
collector.arg2 'block arg 2'
collector.arg3 'block arg 3'
end
Origen::Utility.collector(hash: options, merge_method: :fail, &block).to_h
#=> Origen::OrigenError
#=> 'Origen::Utility::Collector detected both the hash and block attempting to set :arg2 (merge_method set to :fail)'
As shown above, trying to merge the same key in the hash and block when merge_method: :fail
will cause an exception. There are a few other conditions that will cause the collector to fail.
Since the collector tries to transform an options block
into a hash, some of the syntactic rules of
hashes are enforced on blocks.
Multiple Sets
The collector will fail if the same method is set after multiple times. For example:
block = Proc.new do |collector|
collector.arg1 'hi'
collector.arg1 = 'hello'
end
Origen::Utility.collector(&block)
#=> ArgumentError
Even though this is technically allowed in Ruby, its the equalivent of a hash formatted
{arg1: 1, arg1: 2}
, which just overwrites values. There is no reason for this usage and it just
causes confusion (especially in large hashes or blocks), so the collector disallows this.
Multiple Values In A Single Set
Each method can only set one value. As such, providing any number of arguments greater than one will fail, as will attempting to use both an argument and a block.
For example:
block = Proc.new do |collector|
collector.arg1 'arg1', 'arg2', 'arg3'
end
Origen::Utility.collector(&block)
#=> ArgumentError
block = Proc.new do |collector|
collector.arg1('arg1') do
'nothing'
end
end
Origen::Utility.collector(&block)
#=> ArgumentError
This would be the hash equalivent of {arg1: 'arg1', 'arg2', 'arg3'}
which is a syntax error. Also,
setting a value to just a block is accepted, just not a block and another value simultaneously.
For the collector, method_missing
actually returns self
, instead of the value set. This
means that blocks that only use the collector.arg value
notation will always return the collector. The
advertised means of using an anonymous collector is:
Origen::Utility.collector(options, &block)
However, the following may work, depending on the block:
block.call(Origen::Utility.collector)
For the above case, in order to get a collector instance, the block must return the collector. If
just using collector.arg val
syntax, this will work, but collector.arg = val
syntax will not.
This is due to Ruby’s rules that collector.arg = val
will return val
. Likewise, adding
other stuff at the end of the block will also change its return value:
block = Proc.new do |collector|
collector.arg1 'arg1'
end
block.call(Origen::utility.collector)
#=> Collector Instance
block = Proc.new do |collector|
collector.arg1 = 'arg1'
end
block.call(Origen::utility.collector)
#=> 'arg1'
block = Proc.new do |collector|
collector.arg1 'arg1'
'random stuff'
end
block.call(Origen::utility.collector)
#=> 'random stuff'
However, if the block returns the collector itself, as below:
block = Proc.new do |collector|
collector.arg1 'arg1'
'random stuff'
collector
end
block.call(Origen::utility.collector)
#=> Collector Instance
then this will work as expected. But, this relies on the block being written in a way that is impossible to detect from the collector itself.
The correct way to work around this is to use the advertised means of initializing an anonymous collector. This will give you the desired result regardless of the block’s return value.
block = Proc.new do |collector|
collector.arg1 'arg1'
end
Origen::utility.collector(&block)
#=> Collector Instance
block = Proc.new do |collector|
collector.arg1 = 'arg1'
end
Origen::utility.collector(&block)
#=> Collector Instance
block = Proc.new do |collector|
collector.arg1 'arg1'
'random stuff'
end
Origen::utility.collector(&block)
#=> Collector Instance
Unfortunately this guide has not been written yet, but it is an area that is on our road map.
Please comment below to let us know that you were looking for it, this will help us to prioritize which sections to write next.
If you need help on this item in the meantime, please ask a question in the Origen forum.
Unfortunately this guide has not been written yet, but it is an area that is on our road map.
Please comment below to let us know that you were looking for it, this will help us to prioritize which sections to write next.
If you need help on this item in the meantime, please ask a question in the Origen forum.
Unfortunately this guide has not been written yet, but it is an area that is on our road map.
Please comment below to let us know that you were looking for it, this will help us to prioritize which sections to write next.
If you need help on this item in the meantime, please ask a question in the Origen forum.
Unfortunately this guide has not been written yet, but it is an area that is on our road map.
Please comment below to let us know that you were looking for it, this will help us to prioritize which sections to write next.
If you need help on this item in the meantime, please ask a question in the Origen forum.
Usage of the mailer in applications or plugins is described at sending emails and maillists.
As a quick recap of the above, you can send an email using Origen’s mailer:
Origen.mailer.send_email(subject: "Hello", to: ['user@domain.com', 'other_user@domain.com'], body: message)
The subject
, to
, and from
options are the most used but you can get a test email
sent to the current user (yourself) by omitting all the options:
Origen.mailer.send_email
#=> to: current user's email
#=> from: current user's email
#=> subject: 'Hello'
#=> body: 'Hello from Origen!'
However, that assumes a working mailer setup. In order to use the mailer, either the user, in the options, or the site administator will need to setup the mailer correctly. It is recommended that the mailer be setup in the Site Config, allowing all users to use the same configuration. However, each option can be overridden when using the mailer directly.
For the mailer’s options in the site config, please see the default site config.
Origen’s mailer is just a wrapper around Ruby’s net/smtp library.
When using a SMTP server, you’ll need to supply
the server
, port
, and domain
values. These can come from the site config
as keys:
email_domain: company.com
email_server: smtp.company.net
email_port: 25
Or can be passed in as options:
Origen.mailer.send_email(
domain: 'company.com',
server: 'smtp.company.net',
port: 25,
)
For non-authenticating SMTP servers, that is usually sufficient. For servers which require that the requester supply some credentials, you can also supply an authentication customization either in the site config:
email_authentication: login
Or as an option:
Origen.mailer.send_email(authentication: :login)
The username and password will default to the current user’s credentials, Origen.current_user.email
and
Origen.current_user.password
respectively, and, in general, this should be adequate.
However, these can be overwritten if, for example, a service account is used instead of the active user’s account:
email_auth_user: service_user_email
email_auth_password: service_user_password
Origen.mailer.send_email(
authentication: :login,
auth_user: 'service_user_email',
auth_password: 'service_user_password',
)
You can reference Origen’s wrapper around SMTP on Github.
Unfortunately this guide has not been written yet, but it is an area that is on our road map.
Please comment below to let us know that you were looking for it, this will help us to prioritize which sections to write next.
If you need help on this item in the meantime, please ask a question in the Origen forum.