Mooving to the Mobile Web
With the rise of the myriad of mobile phones, tablets and other devices that are connected to the internet, the potential users for a given website have both increased in number and morphed in their needs in terms of a user experience. As anyone who has attempted to use a website not designed for a mobile phone browser with frantic pinch-zooms to find a tiny page control, right next to four other controls that do something totally different in a menu, can attest this is really not ideal.
And meanwhile from the other perspective, for web developers, the notion of a fragmented user base over everything from a desktop PC with a modern browser to an embedded PC built into my new LCD TV needing to view your pages gracefully can be a scary prospect. The thought of maintaining independent versions of your web infrastructure that fit each of these major use cases would likely scare everyone in your company, especially the finance people cutting all the checks.
So what is a company facing this new reality of the modern web to do? One particular solution can help to alleviate one of the more troublesome issues with new devices browsing the Internet, mobile phone display. While the phones …
browsers mobile
Piggybak Dependency & Demo Updates
Things have been quiet on the Piggybak front lately, but we recently upgraded the demo to Ruby 2.0.0 via rbenv, Rails 3.2.15, and Postgres 9.3. The Piggybak demo runs on Debian 7 with nginx and Unicorn. The upgrade went fairly smoothly, with the exception of jQuery related issues, described below.
As of jQuery 1.7, the live() method is deprecated, replaced with the on() method. As of jQuery 1.10., the live() method no longer exists. The previous version of Rails that was used on the demo, Rails 3.2.12, required the jquery-rails gem version which included an older version of jQuery. Upon upgrading to Rails 3.2.15, the attached jquery-rails gem now includes jQuery 1.10., resulting in the live() method no longer existing. As a result, several of the dependencies needed to be updated to accomodate this change (Rails_admin, the Piggybak Coupon gem, and the Piggybak Gift Cert gem, jQuery Nivo Slider).
What’s next for Piggybak? Our future plans include an upgrade to support Rails 4.0. Additional features described on our last Roadmap Update include advanced taxonomy, reviews & ratings, saved cart, wishlist functionality, and saved address support. Piggybak continues to be a great …
ecommerce piggybak ruby rails
Zero Downtime Deploys with Unicorn
I was recently deploying a new Ruby on Rails application that used NGINX and Unicorn for production. During the deploy, my common practice was to stop the Unicorn processes and then restart them. I would do this by finding the PID (process id) of the running process, stop it using the kill command and then run the unicorn_rails command from my application root directory. This worked well enough that I put together a simple unicorn_init shell script to handle running the commands for me.
After a couple of deploys using this init script, I found that there was a significant inturruption caused to the site. This was due to the approximately 20 seconds it took for the Unicorn workers to launch. This was unaccepatble and I started a search for how to perform a zero downtime deploy for Unicorn.
My search lead me to the Unicorn Signal Handling documentation. Unicorn makes use of POSIX Signals for inter-process communication. You can send a signal to a process using the unfortunately named kill system command. Reading through the different signals and what message they send to the Unicorn master and workers, I found a better approach to restarting my Unicorn processes that would result in …
rails sysadmin
SELinux fix for sudo PAM audit_log_acct_message() failed
I was just reading my co-worker Lele’s blog post about making SELinux dontaudit AVC denial messages visible and realized it was likely the solution to a mystery I ran into a few days ago.
As Lele explains, the SELinux dontaudit flag suppresses certain very common SELinux AVC denials to keep the audit logs from bloating beyond belief and being too hard to use. But sometimes a commonly harmless denial can be the cause of further errors. You can tell this is the case if temporarily disabling SELinux enforcing (setenforce 0) makes the problem go away, but /var/log/audit/audit.log still doesn’t show any AVC denial actions being allowed through.
In my somewhat unusual case there is an Apache CGI shell script that calls sudo to invoke another program as a different user without using setuid or suEXEC. Everything works fine with SELinux enforcing, but there are some strange errors in the logs. In /var/log/secure:
sudo: PAM audit_log_acct_message() failed: Permission deniedAnd in the Apache error_log is the apparently strangely unbuffered output:
[error] sudo
[error] :
[error] unable to send audit message
[error] :
[error] Permission denied
[error]To show the dontaudit AVC denials, I …
redhat security selinux sysadmin
Asynchronous Page Switches with Django
Now that the newly rebuilt endpoint.com website is up and running, you may have noticed it does something fancy: internal links within the site are fetched in the background, and the page is replaced dynamically with a script. That eliminates the ‘flicker’ of normal website navigation, and removes the need for the browser to re-parse CSS and JavaScript, making it feel more responsive.
Recently I did some work on a Django project that uses jQuery for some AJAX calls to send information back to the database. It was a fairly simple $.post() call, but it got me thinking about Django’s template inheritance and how it could be used to render parts of templates and update those client-side without having to render the whole thing. The idea being, if your base template is complex and has a number of built-in queries or calculations, for example if you have a dynamic navigation menu, why put extra load on Postgres, on the web server, or have the browser reload the CSS, JS, images, or other resources, to load in what could be otherwise static data into a content column?
The idea’s a little half-baked, just the result of a little after-hours tinkering over a couple evenings. Certainly hasn’t …
django javascript python
Pagination days are over? Infinite scrolling technique
Love it or hate it, but the infinite scrolling technique became a big part of UX. Google Images use it, Flickr uses it, Beyonce’s official website uses it. Twitter, Tumblr and the Facebook feed have it as well. The technique allows users to seamlessly scroll through content. When the user reaches the end of the page new content will automatically load at the bottom.
In my opinion, it allows for a much more natural and immersive experience while viewing images or articles, much better than pagination or once popular image slideshow galleries. In the real life you don’t click on pagination links to get through your day, right?
To create the infinite scrolling page with images we will use the jQuery Infinite Scroll plugin and Masonry to lay out the images. Here is the demo of what we are going to accomplish. The code is below.
First step is to include the necessary scripts:
<script src="/javascripts/jquery.min.js" type="text/javascript"></script>
<script src="/javascripts/jquery.masonry.min.js" type="text/javascript"></script>
<script src="/javascripts/jquery.infinitescroll.min.js" type="text/javascript …javascript jquery user-interface
Post Login Action in Interchange
A while back, I sent a request to a few coworkers looking for a post login hook in Interchange, meaning that I’d like to execute some code after a user logs in that would not require modifying the core Interchange code. This was prompted by the need to transfer and create database records of uploaded images (uploaded while not logged in) to be tied to a specific user after they log in. Mark found a simple and elegant solution and I’ve described it below.
postlogin_action
The first step to adding a post login hook or method is to add the following to catalog.cfg:
UserDB default postlogin_action transfer_user_imagesThe above code results in a call to the catalog or global sub transfer_user_images after a user logs in.
Defining the Global Sub
Next, the sub needs to be defined. In our code, this looks like:
# custom/GlobalSub/transfer_user_images.sub
GlobalSub transfer_user_images IC::GlobalSubs::transfer_user_images# custom/lib/IC/GlobalSubs.pm
sub transfer_user_images {
#code here
}In the above example a transfer_user_images sub points to a Perl module that contains all of our custom global subroutines. The GlobalSubs Perl module contains the code executed upon login.
Add …
ecommerce interchange perl
Internal Tidbits: Links, Resources, Tools
Here at End Point, we have a broad range and depth of knowledge in many areas of web development, both server side and client side. This shows itself in form of many internal emails. Whenever I get an internal email with some tidbit of information I’d like to read later on, I file it in my Internal folder to read about later. That folder is overflowing now, and I wanted to take some time to clean it out and share the contents in blog form.
- A while back, Jon shared a link to superhero.js, which is an aggregate of the best articles, videos and presentations on creating, testing, and maintaining large JavaScript code bases.
- Jon also shared a link to Coding, Fast and Slow: Developers and the Psychology of Overconfidence. This is an article about estimating projects, which is so inherent in our work.
- Phunk told us about the file finder tool in github: if you go to a repo in github and click “t”, it activates the file finder and you can find files by fragments of the filename. Holy cow – I’m just reading this email now and tried it out for the first time!
- Jon shared a link to Git Best Practices by Seth Robertson.
- Jon (side note: This Jon “character” must send a lot of emails!) told us …
tools