How to use unlogged PostgreSQL tables in Rails and ActiveRecord
After calling create_table use a raw SQL statement to convert a table to unlogged:
execute "ALTER TABLE xxx SET UNLOGGED;"
After calling create_table use a raw SQL statement to convert a table to unlogged:
execute "ALTER TABLE xxx SET UNLOGGED;"
Configure a global redirect from www to no-www and http to https in Traefik: https://community.traefik.io/t/global-redirect-www-to-non-www-with-https-redirection/2313/9
Javascript (jQuery):
function autocomplete(options) {
var input = $(options.input);
var resultsElem = $(options.results);
var url = options.url;
var cache = {};
var result = null;
var minQueryLength = options.minQueryLength;
var debounce = null;
var waitingFor = null; // Ajax responses might not arrive in order
var show = function() {
if(result == null) {
return;
}
resultsElem.fadeIn(100);
};
var hide = function() {
resultsElem.fadeOut(100);
};
// Hide when clicking outside autocomplete elements
$('body').click(function(){
hide();
});
// Stop propagation so that event does not reach the body handler
$('.autocomplete').click(function(e){
e.stopPropagation();
});
var renderResults = function(query, results) {
if (query !== waitingFor) {
return;
}
resultsElem.html(results);
if (results != undefined) {
show();
} else {
hide();
}
};
var search = function() {
var query = input.val();
console.log("Searching for '" + query + "'")
waitingFor = query;
if (query in cache) {
console.log('Using cache')
renderResults(query, cache[query]);
} else {
console.log('Not using cache')
if (query.length > minQueryLength) {
$.ajax({url: url, data: {query: query}, type: 'GET'}).then(function(data) {
result = data;
cache[query] = result;
renderResults(query, result);
});
} else {
renderResults(query, null);
}
}
};
var searchWithDebounce = function(e) {
clearTimeout(debounce);
debounce = setTimeout(search, 100);
};
input.on('blur', hide);
input.on('focus', show);
input.on('keyup', searchWithDebounce);
};
autocomplete({
input: '#autoComplete',
results: '#autocomplete-results',
url: '/search',
minQueryLength: 2
});
HTML (Bootstrap 4):
<form action="/search" class="form-inline ml-2 my-2 my-lg-0 ml-auto mr-auto" id="site-search" method="GET">
<input aria-label="Search" autocomplete="off" class="autocomplete form-control mr-sm-2" id="autoComplete" name="query" placeholder="Search" tabindex="1" type="search">
<div class="autocomplete shadow" id="autocomplete-results"></div>
</form>
I prefer using rsync to scp when copying files via jump hosts, for example, to target-host via the intermediate host jump-host:
rsync -v -e 'ssh -A -t [email protected] ssh -A -t target-host' nasty.file :/tmp
rsync syntax is stable across versions and platforms while the syntax of SCP is different across platforms and versions.
man ssh:
-A Enables forwarding of the authentication agent connection. This can also be specified on a per-host basis in a configuration
file.
Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the
agent's UNIX-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material
from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into
the agent.
-t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.
To achieve idempotency with Rails and Turbolinks you have many options including these:
Destroy existing elements that were created on the first page load. This works well with most libraries, including D3.js.
The is also the easiest to implement if you put everything under one root DOM element.
Set a flag. Check if the flag is set before running the script. Note that you will have to use delegated event listeners or attach event listeners again. This is hard to do with, for example, D3.js.
document.addEventListener("turbolinks:load", function() {
$('.linechart').each(function(_ix, el) {
// Option 1: Destroy existing elements that were created on the first page load
el = $(el);
el.empty(); // empty removes all child elements. Normally this would be put in the script itself
linechart(el)
// Option 2: Set a flag to avoid calling the script twice
//if(el.attr('data-initialized') == null) {
// console.log("not initialized")
// linechart(el)
//} else {
// console.log("initialized")
//}
// // Attach event listeners again
// linechart.attachDelegatedEventListeners(el);
//el.attr('data-initialized', true);
});
});
Use D3.js ranges to display ticks every n months, weeks, years, and quarters:
var xAxis = d3.axisBottom()
xAxis.tickValues(d3.timeMonths(firstQtr, lastQtr, 4))
Reference: https://github.com/d3/d3-time#ranges
“Pass all your pack names when using javascript_packs_with_chunks_tag helper otherwise you will get duplicated chunks on the page”
<%= stylesheet_pack_tag 'YOUR_PACK_NAME_HERE' %>
<%# DO %>
<%= javascript_packs_with_chunks_tag 'calendar', 'map' %>
<%# DON'T %>
<%= javascript_packs_with_chunks_tag 'calendar' %>
<%= javascript_packs_with_chunks_tag 'map' %>
https://github.com/rails/webpacker/blob/master/docs/webpack.md#add-splitchunks-webpack-v4
require 'nokogiri'
require 'net/http'
require 'csv'
require 'json'
url = 'http://site/html.table'
uri = URI(url)
response = Net::HTTP.get(uri)
doc = Nokogiri::HTML(response)
table = doc.xpath('//table//tr').map do |row|
row.xpath('td').map do |cell|
cell.text
end
end
puts JSON.pretty_generate(table)
To extract numbers from a string in Bash scripts you can use a bash feature called REMATCH. You don’t need grep, sed, or awk.
Add this to script.sh (remember to run chmod +x script.sh):
#!/usr/bin/env bash
string="COPY 23845\n3409"
if [[ $string =~ ^COPY[[:space:]]([0-9]+) ]]; then
echo "Match: ${BASH_REMATCH[1]}"
else
echo "No match"
fi
This will print 23845, but not 3409. Note that this example uses a capture group.
This is an example of how to use PostgreSQL’s “COPY FROM STDIN”:
psql xxx_development -c "COPY table1(column1, column2) FROM STDIN DELIMITER E'\t' QUOTE E'\x01' ENCODING 'ISO-8859-1' CSV HEADER;" < sub.txt
NOTE: The following example where I put the “COPY FROM STDIN” in a file does not work:
# The COPY FROM STDIN SQL statement is in a file named copy.sql. This does not work:
psql xxx_development | cat copy.sql