tag:blogger.com,1999:blog-79750272310826373312024-03-17T01:08:51.301-07:00Craic Computing Tech TipsA collection of computer systems and programming tips that you may find useful.
<br> <br>
Brought to you by <a href="http://www.craic.com">Craic Computing LLC</a>, a bioinformatics consulting company.Robert Joneshttp://www.blogger.com/profile/13582954721486542844noreply@blogger.comBlogger250125tag:blogger.com,1999:blog-7975027231082637331.post-77694832990111805702019-04-25T13:38:00.000-07:002019-04-25T13:38:55.760-07:00Ruby serializable_hash removes ruby/object from YAML outputI use <a href="https://en.wikipedia.org/wiki/YAML">YAML</a> as a convenient way to serialize data in a number of projects, most of which are written in Ruby and Rails<br />
<br />
You generate the YAML representation with the <span style="font-family: Courier New, Courier, monospace;">.to_yaml</span> method - really simple.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">p = Paper.find(359)</span><br />
<span style="font-family: Courier New, Courier, monospace;">puts p.to_yaml</span><br />
<br />
But if the input is a ruby or rails object the output is prefixed with !ruby/object and that causes problems when you try and load that document in another script that does not know about this object<br />
<br />
For example - here is an example of a Paper object from a Rails application.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">--- !ruby/object:Paper</span><br />
<span style="font-family: Courier New, Courier, monospace;">attributes:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> id: 359</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pmid: 7945531</span><br />
<span style="font-family: Courier New, Courier, monospace;"> title: 'Pharmacokinetics of a new human monoclonal antibody against cytomegalovirus.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Third communication: correspondence of the idiotype activity and virus neutralization</span><br />
<span style="font-family: Courier New, Courier, monospace;"> activity of the new monoclonal antibody, regavirumab in rat serum and its pharmacokinetics'</span><br />
<span style="font-family: Courier New, Courier, monospace;">[...]</span><br />
<br />
If I try and read this file in a separate script I get this error because that script has no concept of a Paper object.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">y = YAML.load_file('test.yml')</span><br />
<span style="font-family: Courier New, Courier, monospace;">ArgumentError: undefined class/module Paper</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>from /Users/jones/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/psych-2.0.5/lib/psych/class_loader.rb:53:in `path2class'</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>from /Users/jones/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/psych-2.0.5/lib/psych/class_loader.rb:53:in `resolve'</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>from /Users/jones/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/psych-2.0.5/lib/psych/class_loader.rb:45:in `find'</span><br />
<span style="font-family: Courier New, Courier, monospace;">[...]</span><br />
<br />
The way to strip off the <span style="font-family: Courier New, Courier, monospace;">ruby/object </span>'header' is to use <span style="font-family: Courier New, Courier, monospace;">serializable_hash</span> before <span style="font-family: Courier New, Courier, monospace;">to_yaml</span>.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">---</span><br />
<span style="font-family: Courier New, Courier, monospace;">abstract: TI-23 consists of lyophilized regavirumab (monoclonal antibody C23, MCA</span><br />
<span style="font-family: "Courier New", Courier, monospace;">[...]</span><br />
<span style="font-family: "Courier New", Courier, monospace;">id: 359</span><br />
<span style="font-family: Courier New, Courier, monospace;">pmid: 7945531</span><br />
<span style="font-family: Courier New, Courier, monospace;">publication_date: 1994-07-01</span><br />
<span style="font-family: Courier New, Courier, monospace;">title: 'Pharmacokinetics of a new human monoclonal antibody against cytomegalovirus.</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Third communication: correspondence of the idiotype activity and virus neutralization</span><br />
<span style="font-family: Courier New, Courier, monospace;"> activity of the new monoclonal antibody, regavirumab in rat serum and its pharmacokinetics'</span><br />
<br />
It looks like the keys in the yaml block are output in alphabetical order.<br />
<br />
It's a simple fix but I had to hunt around to find it.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com9tag:blogger.com,1999:blog-7975027231082637331.post-29533162262141568072019-03-14T14:58:00.000-07:002019-03-14T14:58:25.376-07:00Using Google BERT to Classify Biomedical PapersI have been using Google's BERT language representation model to help classify a certain type of biomedical paper based on abstracts in the <a href="https://www.ncbi.nlm.nih.gov/pubmed/">PubMed</a> database.<br />
<br />
The scripts that I use for data preparation and a detailed walk through of the process are written up in a new <a href="https://github.com/craic/bert_paper_classification">GitHub repository</a> that I have created.<br />
<br />
My work was based on a <a href="https://blog.insightdatascience.com/using-bert-for-state-of-the-art-pre-training-for-natural-language-processing-1d87142c29e7">blog post by Javed Qadrud-Din</a> that I found extremely helpful.<br />
<br />
With my dataset I am getting around 91% accuracy - which is much better than my earlier experiments with LSTM, CNN, etc approaches.<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com2tag:blogger.com,1999:blog-7975027231082637331.post-10967934682435948402018-11-13T13:25:00.003-08:002018-11-13T13:25:44.500-08:00Sharing a folder on a Synology NAS with MacOS and Ubuntu linux using CIFS / SMBI have a Synology DS418 Network Attached Storage (NAS) system.<br />
<br />
I wanted to create a Shared Folder on the NAS that I could access from Mac OS (Mojave 10.14) and a Linux box running Ubuntu 16.04.<br />
<br />
MacOS uses SMB to share folders and so I decided to use that on the Linux box.<br />
<br />
There are 3 parts to this process:<br />
<br />
#1 Set up the folder on the NAS.<br />
<br />
In Synology File Station, create the folder (<span style="color: red;">SMBtest</span> is the name used here). Under the Permissions Tab I gave my user (jones) full control by selecting 'Administration' and 'Change Permissions' and 'Take Ownership'<br />
<br />
I think that is all that is needed on the NAS.<br />
<br />
#2 on the Mac<br />
<br />
Under the Finder -> <span style="color: red;">'Go' -> 'Connect to Server'</span><br />
In my case the address to use was '<span style="color: red;">smb://craic-nas-1</span>'<br />
Connect as Registered User on the NAS and then select the volume '<span style="color: red;">SMBtest</span>'<br />
<br />
I then had access to that volume in the Finder or at <span style="color: red;">/Volumes/SMBtest</span> on the command line<br />
<br />
#3 on the Linux box<br />
<br />
Ubuntu Linux uses the CIFS "common internet file system" protocol to communicate with SMB servers.<br />
<br />
I had to install the CIFS software<br />
<br />
<span style="color: red;">sudo apt-get install cifs-utils</span><br />
<br />
and I created a credentials file with my NAS username and password.<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">emacs ~/.smbcredentials</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;"><br /></span>
<span style="color: red; font-family: Courier New, Courier, monospace;">username=jones</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">password=<mypassword></span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;"><br /></span>
<span style="color: red; font-family: Courier New, Courier, monospace;">chmod 600 ~/.smbcredentials</span><br />
<br />
I created a mount point on the Linux box and made myself the owner<br />
<br />
mkdir /mnt/<br />
mkdir /mnt/jones<br />
sudo chown jones.jones /mnt/jones<br />
<br />
To mount that shared folder<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">sudo mount -t cifs -o credentials=~/.smbcredentials,uid=1000,gid=1000,iocharset=utf8 //craic-nas-1/SMBtest /mnt/jones/SMBtest</span><br />
<br />
My UID on the linux box is 1000 - the uid and gid options means that the mounted directory is owned by me on the linux box - otherwise there are all sorts of permission issues.<br />
<br />
The <span style="color: red;">iocharset=utf8</span> is important. Without it, if I edited a file on Linux then there would be strange characters when I looked at it on the Mac side.<br />
<br />
With that mount command I can create, edit and run scripts on either MacOS or Linux<br />
<br />
To unmount the share<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">sudo umount /mnt/jones/SMBtest</span><br />
<br />
To mount the share automatically I added this to /etc/fstab<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">//craic-nas-1/SMBtest /mnt/jones/SMBtest cifs credentials=/home/jones/.smbcredentials,uid=1000,iocharset=utf8 0 0</span><br />
<br />
To test that works<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">sudo mount -a</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com4tag:blogger.com,1999:blog-7975027231082637331.post-68154669794887239002018-01-03T10:37:00.000-08:002018-01-03T10:37:35.741-08:00Audio Cover on Gigabyte Aorus Z370 Gaming 7 Motherboard Blocks PCIEX16 SlotI've just finished building a machine learning Linux machine based on the <a href="http://www.gigabyte.us/Motherboard/Z370-AORUS-Gaming-7-rev-10#kf">Gigabyte Aorus Z370 Gaming 7 Motherboard</a> and a <a href="http://www.gigabyte.us/Graphics-Card/GV-N108TAORUS-X-11GD#kf">Gigabyte Aorus Geforce GTX 1080 Ti</a> graphics card.<br />
<br />
Most high end motherboards these days are aimed at gamers and so they include all sorts of RGB Led lights and assorted bling so that the users can install them in cases with a clear side. I don't care about all that.<br />
<br />
The problem with this motherboard and card combination is that, as part of the bling, they have covered part of the board with a piece of plastic, marked as 'AMP-UP AUDIO', which has no actual function... and one end of that lies in front of the PCIEX16 slot where the graphics card needs to sit (see the arrow).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5AFGkClYB9mBOflru7u-hDnl2mtZuFeeRt_DbCrIIn7y-wjKv9SRuLGm70AbNteDT4ZmT1rnhJwwQ-DKQkX3O4n-M8n6tZ_apAZqzKpjlBCPl20_KL2wMTpsySK1eDKaebXnCssBylBU/s1600/card_cover.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="800" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5AFGkClYB9mBOflru7u-hDnl2mtZuFeeRt_DbCrIIn7y-wjKv9SRuLGm70AbNteDT4ZmT1rnhJwwQ-DKQkX3O4n-M8n6tZ_apAZqzKpjlBCPl20_KL2wMTpsySK1eDKaebXnCssBylBU/s320/card_cover.png" width="239" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Here is the tab on the graphics card that is blocked. I don't know if other cards have this tab.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisCu1eMHyE0Al2TViUa58XcmRy94v7WtX2e9QBfJtOfHAS4StCQ5RQgFF0Q99t8mII7nzA7xMFciD7AVYW-L6bmGFcZRdx-NfbtEd9OJxYiJdzCJVDXpGK4w8Wz8QQQSBLg85LQy4D8hY/s1600/tab_on_card.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="800" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisCu1eMHyE0Al2TViUa58XcmRy94v7WtX2e9QBfJtOfHAS4StCQ5RQgFF0Q99t8mII7nzA7xMFciD7AVYW-L6bmGFcZRdx-NfbtEd9OJxYiJdzCJVDXpGK4w8Wz8QQQSBLg85LQy4D8hY/s320/tab_on_card.png" width="239" /></a></div>
<br />
<br />
So with the plastic in place, you can't seat the card... and both components are from the same manufacturer... <i>sigh</i><br />
<br />
Fortunately, because the cover has no function whatsoever, you can just remove it and solve the problem. Flip over the motherboard and remove these two small screws. Throw the nasty piece of plastic in the recycling. Job done...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQiD8qvKF9pTQ_r17Xs3sNwsQky9P4DCIh52q_Wn3mTeHu3HEjpKgD4d53oXpUmZRR0ZCQXte5mJIosQvAN4C_cmZlpRVx1SIkbl5AIzpndIKMdfVNLa0x_X8YrAkrtESM6Mu4QTM7nkE/s1600/screw_holes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="800" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQiD8qvKF9pTQ_r17Xs3sNwsQky9P4DCIh52q_Wn3mTeHu3HEjpKgD4d53oXpUmZRR0ZCQXte5mJIosQvAN4C_cmZlpRVx1SIkbl5AIzpndIKMdfVNLa0x_X8YrAkrtESM6Mu4QTM7nkE/s320/screw_holes.png" width="239" /></a></div>
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com2tag:blogger.com,1999:blog-7975027231082637331.post-30506260983954397342016-09-29T16:33:00.001-07:002016-09-29T16:33:38.748-07:00pi_power - power management for portable Raspberry Pi projectsI have been working on a portable Raspberry Pi project for a while - still not there yet but I've completed one important piece.<br />
<br />
It's portable so it obviously has a battery. The Pi takes quite a bit of power so it needed to be rechargeable and include a charger. Adafruit make a great device called the <a href="https://www.adafruit.com/products/2465">PowerBoost 1000C</a> which takes care of the core charging and power supply functions. But I really wanted my project to work like my phone does:<br />
<br />
<li>To power it up from a cold state, press a button for a few seconds</li>
<li>To power it off, press the same button for a few seconds</li>
<li>Indicate how much power remains in the battery</li>
<li>Provide an alert when that is running really low</li>
<li>Shut down safely without any data corruption if the battery does run out</li>
<li>To recharge the battery, just plug in a cable from a USB charger</li>
<div>
<br /></div>
<div>
I couldn't find anything that provided all the functionality I wanted - so I built my own</div>
<br /><a href="https://github.com/craic/pi_power">pi_power</a> consists of fairly straightforward circuitry that links the PowerBoost to the Pi in conjunction with two python scripts that run in the background and monitor the battery voltage.<div>
<br /></div>
<div>
If you are building a portable RasPi project then you might want to take a look</div>
<div>
<br /></div>
<div>
<a href="https://github.com/craic/pi_power">https://github.com/craic/pi_power</a></div>
<div>
<br /></div>
Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com1tag:blogger.com,1999:blog-7975027231082637331.post-31317672915013534822016-06-08T14:13:00.001-07:002016-06-08T14:13:59.935-07:00Image capture software for cheap USB microscopesLook on Amazon and you will find a variety of cheap USB microscopes. These are basically a USB video camera with a macro lens. They are good for inspecting fine details of things like electronic components, plants, insects, stamps, etc. but they are not powerful enough for looking at, say, cells in biological samples.<br />
<br />
I just bought one to help me capture images of various plant pathologies.<br />
<br />
They are marketed as having a range of magnification from, for example, 20 to 300X and the cameras have resolutions anywhere from 0.3 to 5 M pixels. Be aware that the specified magnification range may include the magnification inherent in displaying the image on a large monitor !<br />
<br />
Dino-Lite make a range of professional USB microscopes of various sorts but these can cost hundreds of dollars. For basic experimentation there are a load of other vendors and products with prices in the $50 - $100 range.<br />
<br />
If you look on Amazon it will be obvious that the same basic models are being sold be several different vendors.<br />
<br />
Here is the one that I bought for $60 which is branded <a href="http://www.amazon.com/DBPOWER-20-300X-Microscope-Magnifier-Software/dp/B00RVGHABS">DBPOWER</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9mYAdcZCLCao1yotyn4ERA40we3mahnq2A9RQQaBJru4vZ9joJfER6SLJgLL4DvZaBmFpWwlkTlCgFOBsZDWEB7Vwpt3Gm4_DfTuoLRlBSKxWFdfrQDWcqp9zg_L-QpB19uemJyNBSs8/s1600/microscope.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9mYAdcZCLCao1yotyn4ERA40we3mahnq2A9RQQaBJru4vZ9joJfER6SLJgLL4DvZaBmFpWwlkTlCgFOBsZDWEB7Vwpt3Gm4_DfTuoLRlBSKxWFdfrQDWcqp9zg_L-QpB19uemJyNBSs8/s320/microscope.png" width="303" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
The same microscope with the same stand is also branded as :</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="http://www.amazon.com/Crenova%C2%AE-UM012C-Digital-Microscope-Magnifier/dp/B012G28SLC">Crenova® UM012C USB Digital Microscope</a> $69</div>
<br />
<a href="http://www.amazon.com/Celestron-Handheld-Digital-Microscope-Pro/dp/B00CMJ1I08">Celestron 5 MP Handheld Digital Microscope Pro</a> $83<br />
<br />
And with a different stand, or without a stand, by a wide variety of other vendors<br />
<br />
I went with the $60 DBPOWER variant with a 5 MP camera. It comes with the stand in two pieces and a CD containing software called MicroCapturePro for PC and Mac.<br />
<br />
You need software to interact with it - it does not just show up as a camera in the MacOS ImageCapture or Preview tools.<br />
<br />
I don't have a CD drive on the machine I want to use this with and transferring the software from one that does is a bit of a pain. So I looked online for the software.<br />
<br />
You can get <a href="http://www.celestron.com/c3/support3/index.php?_m=downloads&_a=viewdownload&downloaditemid=851&nav=0,7&group=iframe">MicroCapturePro</a> from Celestron but after digging around a bit I would recommend a different solution.<br />
<br />
Plugable have a <a href="http://plugable.com/products/usb2-micro-250x">similar microscope</a> and they provide a piece of software called <a href="https://s3.amazonaws.com/plugable/bin/Digital_Viewer_3.1.07.dmg">Digital Viewer</a> - get that and install it on your Mac (they have a Windows version too). When I started it up it displayed the view from my webcam but click the Settings icon in the top left and select the microscope.<br />
<br />
The focussing mechanism on these microscopes is a bit rough but you'll get used to it. I can see that I may want to build myself a better stand and illumination rig.<br />
<br />
Under Settings you can select the image resolution and do a bit of image adjustment. You can take individual images, videos or a set of timed images.<br />
<br />
It looks like it will do exactly what I need it to do - for $60 that's not bad.<br />
<br />
Here is an example image:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFuXXaW9zGz6U4GI-57J5LnqT8_7k884ccO7Vg6_myddMzwZLwa1RuIAJ4Vb4lxZD2MXRn3NHtWrKIINA5zn2ZMzcdK_ZS5_vsiHIFxfKiN6dgzOKb-hqWDB4apKJ1nj35dZZrrAWknmM/s1600/S20160608_001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFuXXaW9zGz6U4GI-57J5LnqT8_7k884ccO7Vg6_myddMzwZLwa1RuIAJ4Vb4lxZD2MXRn3NHtWrKIINA5zn2ZMzcdK_ZS5_vsiHIFxfKiN6dgzOKb-hqWDB4apKJ1nj35dZZrrAWknmM/s320/S20160608_001.jpg" width="320" /></a></div>
<br />
<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com7tag:blogger.com,1999:blog-7975027231082637331.post-53847285825136056922016-01-28T15:52:00.001-08:002016-01-28T15:52:39.794-08:00Raspberry Pi - strange icon in top right of screenI have been working with a mobile Raspberry Pi project powered by a LiPo battery and a Powerboost 1000c charger from Adafruit to handle battery charging.<br />
<br />
Several times I have seen a small square icon in the top right of the attached small HDMI screen that has a rainbow of colors. I had absolutely no idea where this came from or what it represented.<br />
<br />
But now I do... <a href="https://www.raspberrypi.org/forums/viewtopic.php?t=82373">https://www.raspberrypi.org/forums/viewtopic.php?t=82373</a><br />
<br />
The B+ (and presumably later models) has an <span style="color: red;">under-voltage</span> trigger that shows itself as this 'rainbow' square in the top right of the display when the supply voltage drops below <span style="color: red;">4.65V</span>.<br />
<br />
In addition, an <span style="color: red;">over-temperature</span> trigger displays a solid red square in the same location if the temperature goes above <span style="color: red;">85deg C</span>.<br />
<br />
You can disable the warnings in config.txt - see the link for details<br />
<br />
I'm glad that the system has these triggers but I don't think the display of a red/rainbow square is a good way to inform the user.<br />
<br />
<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com6tag:blogger.com,1999:blog-7975027231082637331.post-8022132588637391612015-11-28T08:36:00.000-08:002015-11-28T08:36:35.922-08:00How I fixed a loose MagSafe connector in a MacBook AirThe MagSafe power connector kept falling out of my wife's MacBook Air. I figured it might be due to just wear and tear on the edge of the plug but when I looked at it I could not see any problem.<br />
<br />
Last week I took another look at the plug and socket while I was wearning my magnifying reading glasses - and there was the problem !<br />
<br />
The MagSafe socket is magnetic and so any metal dust that gets rubbed off from the plug will stick to the magentic surface. As a result you can see dark dust adhering to that. But in addition, there was a small metal shaving that was stuck there as well - large enough to interfere with the plug being properly seated. It was small but 'chunky' enough to cause the problem. No idea where it came from - not from the plug. I removed that with a pairs of tweezers and cleaned up the adhered dush with the end of a slightly damp Q-tip.<br />
<br />
Problem solved !<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-10218349778890954672014-10-27T14:07:00.001-07:002014-10-27T14:09:06.791-07:00USPTO Patent data sets are now distributed by Reed Tech, not GoogleFor the past few years Google has been making US Patent Office datasets available for free on the sites:<br />
<br />
<a href="http://www.google.com/googlebooks/uspto-patents-grants-biblio.html">http://www.google.com/googlebooks/uspto-patents-grants-biblio.html</a><br />
<a href="http://www.google.com/googlebooks/uspto-patents-applications-biblio.html">http://www.google.com/googlebooks/uspto-patents-applications-biblio.html</a><br />
and others.<br />
<br />
But the sites have not been updated since around Oct 7th 2014 and no information about the delay was posted... I rely on these updates so that was a big problem.<br />
<br />
After some poking around I stumbled on the fact that <a href="http://patents.reedtech.com/index.php">Reed Tech</a>, a division of Lexis Nexis, is now distributing these datasets at no charge.<br />
<br />
Fortunately the format of the zip files remains identical, at least for the ones I work with.<br />
<br />
You can find the Patent Grant Bibliographic Text at <a href="http://patents.reedtech.com/pgrbbib.php">http://patents.reedtech.com/pgrbbib.php</a> and the Application Bibliographic Text at <a href="http://patents.reedtech.com/parbbib.php">http://patents.reedtech.com/parbbib.php</a><br />
<br />
At the time of writing these pages are up to date.<br />
<br />
This is good news, but it would have been even better if Google had announced the transition a month or so in advance.<br />
<br />
<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com2tag:blogger.com,1999:blog-7975027231082637331.post-22634229853888340842014-09-22T16:07:00.000-07:002014-09-22T16:07:08.255-07:00Trends in Human Antibody Development - ChartsI operate the <a href="http://tabs.craic.com/">TABS Therapeutic Antibody Database</a> which help biotechnology companies working in the field of antibody development. TABS represents the most comprehensive resource in this field.<br />
<br />
With all that data available, I have compiled summary statistics that show the growth of this area of biotech over the years. I have made charts of those trands and have made those freely available on the TABS database site. You can find all the charts <a href="http://tabs.craic.com/static_pages?permalink=antibody_data_presentation_charts">HERE</a>.<br />
<br />
Here is an example showing the number of active projects per year<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://tabs.craic.com/assets/active_antibody_projects_by_year_w_2014_small.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://tabs.craic.com/assets/active_antibody_projects_by_year_w_2014_small.png" height="218" width="320" /></a></div>
<br />
<br />
<br />
You can get a f<a href="http://tabs.craic.com/users/sign_up">ree 30 day trial account at TABS</a>.<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-41040444983967175202014-09-22T10:00:00.001-07:002014-09-22T10:00:14.662-07:00TV Eye - a way to view YouTube videos without all the clutterWhen you view a video on <a href="http://youtube.com/">youtube.com</a> you get not only the video, but a bunch of suggested related videos and often times a lot of comments and other text. All this clutter gets in the way of what you want to do - simply watching the video.<br />
<br />
So I wrote <a href="http://tv-eye.craic.com/">TV Eye</a>, a simple service that embeds your desired video in a simple, plain web page, with none of the usual clutter.<br />
<br />
To use, go to youtube.com and find the video that you want to watch. Copy the URL for the video and paste it into the form on <a href="http://tv-eye.craic.com/">TV Eye</a>.<br />
<br />
The service is really simple and the code is distributed freely under the temrs of the MIT license. You can get the code at <a href="https://github.com/">Github</a> at <a href="https://github.com/craic/tv_eye">https://github.com/craic/tv_eye</a>.<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com2tag:blogger.com,1999:blog-7975027231082637331.post-75130395148391182382014-09-19T14:02:00.001-07:002014-09-19T14:03:08.388-07:00Installing Ruby in Docker Images<a href="https://www.docker.com/">Docker</a> is a great way to package applications with all their dependent libraries etc and then deploy them easily on various hosts. It builds on tools like <a href="https://www.vagrantup.com/">Vagrant</a>.<br />
<br />
I am interested in using it to package Ruby applications built with <a href="http://www.sinatrarb.com/">Sinatra</a> or <a href="http://rubyonrails.org/">Rails</a>.<br />
<br />
The preferred way to build a Docker Image is to write a Dockerfile that contains instructions that load an operating system, installs system packages, copies user code, etc.<br />
<br />
I am building my Images on top of <a href="http://www.ubuntu.com/">Ubuntu</a> 14.04, the current Ubuntu Linux release. A problem with most of the Linux distributions is that the packages that install Ruby are often one or two releases behind. In this case the packaged Ruby is 1.9.3 and the current release if 2.1.2. In many cases this would not be a problem but if you want the latest version then you have do a bit more work and, specifically, compile Ruby from source.<br />
<br />
Once you have the Dockerfile working then this all happens very smoothly but it took me a while to get all the pieces working together. So I wrote up two versions of a minimal Sinatra application along with the Dockerfiles needed to get them to work.<br />
<br />
The code is on Github at <a href="https://github.com/craic/docker_sinatra_examples">https://github.com/craic/docker_sinatra_examples</a><br />
<br />
The Docker Images are on DockerHub at<br />
<a href="https://registry.hub.docker.com/u/craic/docker_sinatra_example_1/">https://registry.hub.docker.com/u/craic/docker_sinatra_example_1/</a><br />
and<br />
<a href="https://registry.hub.docker.com/u/craic/docker_sinatra_example_2/">https://registry.hub.docker.com/u/craic/docker_sinatra_example_2/</a><br />
<br />
The first example installs the packaged Ruby (1.9.3)<br />
The second compiles and installs Ruby 2.1.2 from source.<br />
<br />
I hope these examples help you get up to speed with Docker quickly.<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-68136669367738304122014-09-19T13:05:00.002-07:002014-09-19T13:07:15.449-07:00Clean up unused Docker Containers and Images<a href="https://www.docker.com/">Docker</a> is a great way to package applications with all their dependent libraries etc and then deploy them easily on various hosts. It builds on tools like <a href="https://www.vagrantup.com/">Vagrant</a>.<br />
<br />
In Docker you create <span style="color: red;">Images</span> that contain your code, the OS, libraries, etc and <span style="color: red;">Containers</span> which are the instances of the Image which you actually run.<br />
<br />
Docker does not do a good job cleaning up old Images and Containers and when you are doing a lot of developing this can become a problem. Various people have proposed ways to handle the issue. The best of the web posts that I have seen is http://blog.stefanxo.com/2014/02/clean-up-after-docker/<br />
<br />
Here is a slight restating of those solutions which work for me on MacOSX.<br />
<br />
To clean up non-running containers<br />
<br />
<b><span style="font-family: Courier New, Courier, monospace;"><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;">$ docker ps </span><span class="pun" style="color: #666600; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">-</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;">a </span><span class="pun" style="color: #666600; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">--</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;">no-trunc </span><span class="pun" style="color: #666600; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">|</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"> grep </span><span class="str" style="color: #008800; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">'Exit'</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"> </span><span class="pun" style="color: #666600; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">|</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"> awk </span><span class="str" style="color: #008800; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">'{print $1}'</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"> </span><span class="pun" style="color: #666600; font-size: 16px; line-height: 22.399999618530273px; white-space: pre-wrap;">|</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"> xargs</span><span class="pln" style="font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"> docker rm</span></span></b><br />
<span class="pln" style="font-family: Consolas, monospace, serif; font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"><br /></span>
<span class="pln" style="font-family: Consolas, monospace, serif; font-size: 16px; line-height: 22.399999618530273px; padding-left: 0px; padding-right: 0px; white-space: pre-wrap;"></span><br />
This removes any containers where the Status contains the string Exit. I have seen containers with no status which perhaps have crashed or hung. You just have to remove these manually.<br />
<br />
Once you have removed unused Containers you can then remove unused Images. If you try this the other way round you will get errors that the Images are still in use.<br />
<br />
Unused Images look like this in the output of 'docker ps' - they are the ones with <none> as the repository and tag<br />
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">craic/sinatra_example v1 f9d2702eb2f7 2 days ago 481.3 MB</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><none> <none> 196afed3dded 2 days ago 378.5 MB</span></div>
<div class="p1">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><none> <none> 56f86f0a985e 2 days ago 378.5 MB</span></div>
<br />
<div class="p1">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><none> <none> 011f588e88db 2 days ago 586.8 MB</span></div>
<div class="p1">
<br /></div>
<div class="p1">
To remove them use this command</div>
<br />
<span style="font-family: Courier New, Courier, monospace;"><b>$ docker images -f dangling=true -q | xargs docker rmi</b></span><br />
<br />
If you are using <span style="color: red;">Dockerfiles</span> to build your Images (recommended) then you can always rebuild an image should anything get removed accidentally.<br />
<br />
<br />
<div>
<br /></div>
Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com2tag:blogger.com,1999:blog-7975027231082637331.post-17551614841182881302014-03-10T09:23:00.000-07:002014-03-10T09:23:12.425-07:00Private Wi-Fi Networks, Raspberry Pi and Mac OS X MavericksI ran into two problems connecting to my Wi-Fi network recently - both turned out to be the result of the network being private and not broadcasting its SSID (Service Set Identifier) - the 'name' of the network.<br />
<br />
My network runs on an Apple Time Capsule using WPA2 encryption. It has worked fine with other machines - MacBook, Win PC, Chromebook, iPhones...<br />
<br />
<br />
#1 Getting W-Fi running on a Raspberry Pi<br />
<br />
I was not able to get Wi-Fi running on a Raspberry Pi linux machine, despite trying a range of configurations that I found on the web.<br />
<br />
When I changed the network to make its SSID public then it connected just fine with the basic configuration.<br />
<br />
#2 Setting up a new MacBook Pro<br />
<br />
When you start up a brand new Mac it walks you through several setup steps, including connecting to a network. The new MacBook Pro only has Wi-Fi so connecting to the network is essential. But in my case it did not see the private network and so I was unable to get through the regular setup.<br />
<br />
The work around was to skip those steps until I got to the regular desktop. Then going into Preferences and Network and configuring the network manually I was able to get in.<br />
<br />
I think that if the SSID were broadcast then I would not have had any problems.<br />
<br />
<br />
The reason to keep an SSID private is to make it more difficult for someone to break into your network. If they don't know the network exists then they won't try and break in. In reality, however, it not that simple. A serious hacker will still be able to detect packets on all networks in the area including the 'hidden' ones and then attempt to break in. So a private network is a good idea but it does not offer great protection.<br />
<br />
<br />
<br />
Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com1tag:blogger.com,1999:blog-7975027231082637331.post-71777602648618929242014-02-10T09:16:00.000-08:002014-02-10T09:16:08.140-08:00Using Ping to find machines on your networkThe UNIX command <span style="color: red;">ping</span> is used to test if specific machines are active on a network<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ ping 10.0.1.9</span><br />
<span style="font-family: Courier New, Courier, monospace;">PING 10.0.1.9 (10.0.1.9): 56 data bytes</span><br />
<span style="font-family: Courier New, Courier, monospace;">64 bytes from 10.0.1.9: icmp_seq=0 ttl=255 time=0.619 ms</span><br />
<span style="font-family: Courier New, Courier, monospace;">[...]</span><br />
<br />
I have been using ping for years but last week I found out that you can ping the broadcast address of a network (<span style="color: red;">x.x.x.255</span>) and see all the machines on that network that are configured to respond to ping:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ ping 10.0.1.255</span><br />
<span style="font-family: Courier New, Courier, monospace;">PING 10.0.1.255 (10.0.1.255): 56 data bytes</span><br />
<span style="font-family: Courier New, Courier, monospace;">64 bytes from 10.0.1.10: icmp_seq=0 ttl=64 time=0.071 ms</span><br />
<span style="font-family: Courier New, Courier, monospace;">64 bytes from 10.0.1.9: icmp_seq=0 ttl=255 time=0.534 ms</span><br />
<span style="font-family: Courier New, Courier, monospace;">64 bytes from 10.0.1.1: icmp_seq=0 ttl=255 time=0.544 ms</span><br />
<span style="font-family: Courier New, Courier, monospace;">[...]</span><br />
<br />
Really useful if you need the IP address for a machine that used DHCP to assign its address<br />
<br />
A complementary command is <span style="color: red;">arp -a </span><br />
<br />
This displays information of all the network interfaces for a machine and reports the interface, the IP address and the <span style="color: red;">MAC</span> address of each entry in the address resolution tables.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ arp -a</span><br />
<span style="font-family: Courier New, Courier, monospace;">? (10.0.1.1) at b8:8d:12:5a:ad:77 on en0 ifscope [ethernet]</span><br />
<span style="font-family: Courier New, Courier, monospace;">? (10.0.1.2) at b8:8d:12:5a:ad:77 on en0 ifscope [ethernet]</span><br />
<span style="font-family: Courier New, Courier, monospace;">? (10.0.1.6) at 70:56:81:ad:b6:d1 on en0 ifscope [ethernet]</span><br />
<span style="font-family: Courier New, Courier, monospace;">? (10.0.1.7) at b8:8d:12:5a:ad:77 on en0 ifscope [ethernet]</span><br />
<span style="font-family: Courier New, Courier, monospace;">? (10.0.1.9) at 70:56:81:c5:fb:2d on en0 ifscope [ethernet]</span><br />
<span style="font-family: Courier New, Courier, monospace;">[...]</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Times, Times New Roman, serif;">Note that these addresses are not necessarily active. You can see link reachability information using <span style="color: red;">arp -al</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com1tag:blogger.com,1999:blog-7975027231082637331.post-47905824406665989982013-12-24T10:42:00.001-08:002013-12-24T10:42:57.331-08:00Web Site for Lakou Lapè - working to end violence in Haiti<a href="http://lakoulape.org/">Lakou Lapè</a> is a non-profit organization based in Port-au-Prince, Haiti, that is working to end violence and conflict in some of the impoverished communities in that country.<br />
<br />
<a href="http://lakoulape.org/">Lakou Lapè</a> was created to extend the achievements of the past few years in the Port-au-Prince neighborhood of St.Martin. Starting in 2004, members of that community, the charity <a href="https://www.concern.net/">Concern Worldwide</a>, and the Irish group <a href="http://www.glencree.ie/">Glencree Center for Peace and Reconcilliation</a>, came together to limit and reduce the level of gang violence within that community.<br />
<br />
By using the approaches of reconcilliation, dialogue and respect that helped bring peace to Northern Ireland, the community was able to work together and greatly reduce the violence that was holding the entire community back.<br />
<br />
Lakou Lapè is applying the same approach to other communities in Haiti. Through training, dialogue and engagement with the people that live in these communities, their goal is to reduce conflict and enable people to improve their lives.<br />
<br />
I have been working with the group over the past year as it has started its work and I am proud to have helped build their web site http://lakoulape.org/ which describes their plans and their acheivements in French, Haitian Keyol and English.<br />
<br />
It has been a pleasure to work with old friends from Ireland and new friends in Haiti and I wish Lakou Lapè the best of luck in 2014.<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-67442037388829186212013-11-14T15:24:00.002-08:002013-11-14T15:25:26.654-08:00Web Apprentice - Tutorials on Web TechnologiesThe range of web technologies that are available to web designers and developers is just incredible right now - from maps and graphs to translation and speech recognition.<br />
<br />
Many of these are easy to incorporate into your sites but getting started can be confusing. There are examples and tutorials that are obsolete or needlessly complex - I've written some of them myself !<br />
<br />
I want to help people get up and running with simple examples that they can use in their work today.<br />
<br />
So I have created <span style="color: red;">Web Apprentice</span> (<a href="http://apprentice.craic.com/">http://apprentice.craic.com</a>) - a site that contains clear, straightforward tutorials on web technologies across the spectrum.<br />
<br />
Tutorials range from simple embedding of Twitter feeds or Maps through to Typography, Translation and Geolocation.<br />
<br />
Each tutorial has a self-contained live demo and all the code is available and free to use. Tutorials walk you through all the steps and explains what is going on in the code.<br />
<br />
There are three levels of tutorial:<br />
<br />
Basic - embedding widgets into your pages - no need to know JavaScript<br />
Intermediate - involve some JavaScript<br />
Advanced - complex JavaScript and Server side programming - may involve new technologies that are not in all browsers.<br />
<br />
The goal is to add new tutorials every couple of weeks at least and over time build the site into a destination for learning and applying web technologies.<br />
<br />
Please check it out at <a href="http://apprentice.craic.com/">http://apprentice.craic.com</a> and let me know what you think.<br />
<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-2002440322073864582013-11-11T15:17:00.002-08:002013-11-11T15:17:44.512-08:00Setting up a new Application on HerokuYou can set up a new web application on <a href="https://www.heroku.com/">Heroku</a> in several ways. Here is my preferred way:<br />
<br />
1: Build and test your application locally<br />
<br />
2: Set it up as a git repository and commit all changes<br />
<br />
3: Go to your account on the Heroku web site and cerate your new app there with your preferred name.<br />
<br />
4: In your local git repo run:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ heroku git:remote -a <your-app-name></span><br />
<br />
The response should be 'Git remote heroku added'<br />
<br />
5: Upload your code with:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">$ git push heroku master</span><br />
<br />
6: Finish up your Heroku configuration on the we b site<br />
<br />
7: Import any existing database as directed by <a href="https://devcenter.heroku.com/articles/heroku-postgres-import-export">this article</a>.<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-13897938604570818392013-11-05T12:24:00.002-08:002013-11-05T12:45:20.496-08:00HABTM relationships in Rails 4Rails 4 has changed the way <span style="color: red;">has_and_belongs_to_many</span> (HABTM) relationships are handled as well as introducing <span style="color: red;">strong parameters</span> in the controller as a replacement to having <span style="color: red;">:attr_accessible</span> in your model.<br />
<br />
Here is how you set up HABTM with a joining table.<br />
<br />
My models are <span style="color: red;">Tutorial</span> and <span style="color: red;">Category</span> - a tutorial can have more than one category and vice versa.<br />
<br />
Both models already existed and I wanted to create the relationship between them.<br />
<br />
1: Create a migration for the joining table<br />
<br />
The default table name should be the plural of the two models, in alphabetical order, separated by an underscore. (You can give it any name you want - you just need to include that later in the model)<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">class CreateCategoriesTutorials < ActiveRecord::Migration</span><br />
<span style="font-family: Courier New, Courier, monospace;"> def change</span><br />
<span style="font-family: Courier New, Courier, monospace;"> create_table :categories_tutorials do |t|</span><br />
<span style="font-family: Courier New, Courier, monospace;"> t.belongs_to :tutorial</span><br />
<span style="font-family: Courier New, Courier, monospace;"> t.</span><span style="font-family: 'Courier New', Courier, monospace;">belongs_to</span><span style="font-family: Courier New, Courier, monospace;"> :category</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> end</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end</span><br />
<span style="font-family: Courier New, Courier, monospace;">end</span><br />
<br />
2: Add the relationships to the models<br />
<br />
Previously you would have done this (in the Tutorial model):<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">has_many :categories_tutorials, :dependent => :destroy</span><br />
<span style="font-family: Courier New, Courier, monospace;">has_many :categories, :through => :categories_tutorials, :uniq => true</span><br />
<br />
That is now simplified to this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">has_and_belongs_to_many :categories</span><br />
<br />
If you have a custom table name then specifiy it like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">has_and_belongs_to_many :categories, join_table: :my_category_tutorial_table</span><br />
<div>
<br /></div>
<div>
The Category model has:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">has_and_belongs_to_many :tutorials</span></div>
</div>
<div>
<br /></div>
<div>
The CategoryTutorial model has:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">belongs_to :category</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">belongs_to :tutorial</span></div>
</div>
<div>
<br /></div>
<div>
In my example I want to specify Categories when I create a Tutorial. </div>
<div>
<br /></div>
<div>
In order for this to work I need to allow the tutorials_controller to accept the category_ids parameter which is passed from the tutorial form.</div>
<div>
<br /></div>
<div>
At the bottom of the controller Rails has created this:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">def tutorial_params</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> params.require(:tutorial).permit(:title, :description, :status)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">end</span></div>
</div>
<div>
<br /></div>
<div>
I need to add category_ids and have it set up as an array </div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">def tutorial_params</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> params.require(:tutorial).permit(:title, :description, :status, <span style="color: red;">:category_ids => []</span>)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">end</span></div>
</div>
<br />
That last step is critical - if you miss this then the associated rows are not created in the database.<br />
<br />
For more information on HABTM take a look at:<br />
<br />
<a href="http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association">http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association</a><br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com1tag:blogger.com,1999:blog-7975027231082637331.post-18139665850570507912013-09-20T09:18:00.003-07:002013-09-30T13:36:49.580-07:00Stop e-mail spam from creating events in Google CalendarAn ever growing number of email spam messages will attempt to create events in your Google calendar. This doubles your spam experience - in your email and in your calendar - great...<br />
<div>
<br /></div>
<div>
The messages exploit the default settings in Google Calendar and fortunately this is easy to fix.</div>
<div>
<br /></div>
<div>
Open up your Google Calendar, click on the Setting icon in the top right of the panel (the Gear wheel icon) and then select 'Settings' from the menu that appears.</div>
<div>
<br /></div>
<div>
That gives you a long page of settings - look for this one, most of the way down:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWY4zQZYY8h_NhqSNTWbzD2ofNw5I7aVXi1mFzfpuEFeq7KPVmjMhglTXbEx0FFP0zJGzARyN_KQhcLUJufs21YaydGpOmwAgwcl2ysId-GafyrYlNACXkSNc71pdxR_EqE-pb_W1nZyw/s1600/spam.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="59" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWY4zQZYY8h_NhqSNTWbzD2ofNw5I7aVXi1mFzfpuEFeq7KPVmjMhglTXbEx0FFP0zJGzARyN_KQhcLUJufs21YaydGpOmwAgwcl2ysId-GafyrYlNACXkSNc71pdxR_EqE-pb_W1nZyw/s640/spam.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Change the current setting to 'No, only show invitations to which I have responded' and Save your settings.</div>
<div>
<br /></div>
<div>
That should do it !</div>
<div>
<br /></div>
<div>
Why Google doesn't have this as the default I have no idea...</div>
<div>
<br /></div>
Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-53299526746678847652013-09-05T13:13:00.000-07:002013-09-05T13:13:13.796-07:00Adding extensions to Postgresql database with Rails on HerokuThis is a follow up to my previous post <a href="http://craiccomputing.blogspot.com/2013/08/adding-extensions-to-postgresql.html">Adding extensions to Postgresql database with Rails</a><br />
<br />
If your database is running on Heroku you need to access it slightly differently.<br />
<br />
Using the 'rails db' command does not work:<br />
<pre>$ heroku run rails db
Running `rails db` attached to terminal... up, run.6499
Couldn't find database client: psql. Check your $PATH and try again.</pre>
<br />
Instead access psql like this and then add the extension. \dx lists the current installed extensions<br />
<pre>$ <span style="color: red;">heroku pg:psql</span>
psql (9.2.1, server 9.1.9)
[...]
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
dftmhe7vpg4dhs=> <span style="color: red;">create extension unaccent;</span>
CREATE EXTENSION
dftmhe7vpg4dhs=> <span style="color: red;">\dx</span>
List of installed extensions
Name | Version | Schema | Description
----------+---------+------------+---------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
unaccent | 1.0 | public | text search dictionary that removes accents</pre>
<br />
<br />
Note that this works just fine with a pg:basic database plan. There is no need to upgrade just to use postgres text search.<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-71821463261802410062013-08-21T13:38:00.002-07:002013-08-21T13:38:42.068-07:00Adding extensions to Postgresql database with RailsThe default Postgresql installation on Mac OS X using homebrew includes a single extension - plpgsql (PL/pgSQL procedural language) but there are a number of them available in the lib directory (/usr/local/Cellar/postgresql/9.2.1/lib on my machine)<br />
<br />
To install an extension into the database, the easiest way I found was to open a database console using the '<span style="color: red;">rails db</span>' command and then create it directly. I have seen mention of doing this in a Rails migration but this did not work for me.<br />
<br />
Note that an extension is installed in a specific database, rather than being added to all databases.<br />
<br />
The command to list the installed extensions is '<span style="color: red;">\dx</span>'<br />
<br />
<pre>$ rails db
psql (9.2.1)
Type "help" for help.
tabs_development=# \dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
tabs_development=# create extension unaccent;
CREATE EXTENSION
tabs_development=# \dx
List of installed extensions
Name | Version | Schema | Description
----------+---------+------------+---------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
unaccent | 1.0 | public | text search dictionary that removes accents
(2 rows)
</pre>
Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-27947476923407854082013-08-16T15:27:00.000-07:002013-08-16T15:27:19.371-07:00Testing for the presence of a loaded Gem in a Rails applicationI'm migrating the search function in an application from <a href="https://github.com/ernie/meta_search">meta_search</a> to <a href="https://github.com/ernie/ransack">ransack</a> (both from <a href="https://github.com/ernie">Ernie Miller</a>)<br />
<br />
The syntax has changed quite a bit between the two gems and I use the search functionality in more than 30 controllers / index pages. So I want a simple way to update each instance while still being able to switch back to meta_search if I need to.<br />
<br />
So I need to test which of the two gems has been loaded in the running application.<br />
<br />
The best way that I have found is this:<br />
<br />
<pre>if Gem.loaded_specs['ransack']
'... do this...'
else
'... do that ...'
end</pre>
<br />
You can see the full list of loaded gems with Gem.loaded_specs.keys<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-68216490451555480972013-08-07T12:02:00.002-07:002013-08-07T12:02:30.519-07:00Default Sort Order in Ransack Rails GemErnie Miller's <a href="https://github.com/ernie/ransack">Ransack</a> gem is a great way to handle searching and sorting of data in a Rails 3 application. It is the successor to his meta_search gem. There is a <a href="http://railscasts.com/episodes/370-ransack">railscast episode on ransack</a>.<br />
<br />
But while Ransack offers benefits over meta_search, it is lacking in documentation which is a shame.<br />
<br />
The problem I ran into was how to set a default sort order for records in the controller, before one had been set in the view.<br />
<br />
Here is how you specify this:
<br />
<pre> @search = Post.search(params[:q])
@search.sorts = 'name asc' if @search.sorts.empty?
@posts = @search.result.paginate(:page => params[:page],
:per_page => 20)</pre>
<br />
<br />
The other problem that I am still dealing with is that Ransack does not appear to let you use scopes from your model in the search form. meta_search did allow this. That turns out to be a big issue in a current project to port an older application into Rails 3.
Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com0tag:blogger.com,1999:blog-7975027231082637331.post-62440887087296713382013-07-02T10:12:00.001-07:002013-07-02T10:12:43.449-07:00Recording from a Microphone in the browser using the Web Audio APII have posted a code example that shows how to record audio from a microphone in a web browser using the <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">Web Audio API</a>.<br />
<br />
Take a look a the demo and the code <a href="http://html5-examples.craic.com/microphone_input_with_spectrogram.html">HERE</a><br />
<br />
It turns out that the API does not support recording directly so you have to add consecutive samples of audio data to your own recording buffer. You need to grow the size of the buffer whenever you add a new sample. Once you have your recording you can use it as the source of a BufferSourceNode and play it back.<br />
<br />
<br />Robert Joneshttp://www.blogger.com/profile/07503053614730814672noreply@blogger.com2