Categories
English Regular Expressions

Convert old-style Ruby hashes to new-style.

Search:

:([^s:@]+)s*=>s*

Replace:

1: 
Categories
English Uncategorized

Marshal.dump and load with ActiveRecord

If you aren’t familiar with Marshal.dump and Marshal.load, you probably should be. It’s used to serialize Ruby objects into binary data – mostly caching.

Now, if you’re trying to implement a Russian-doll caching system with objects, you probably have run into the issue of eager-loading associations using #includes not being cached.

my_data = Rails.cache.fetch('an_object') do
  MyData.where(condition: 1).includes(:user).first
end

my_data.user
# On cache miss:
# => SELECT "my_datas".* FROM "my_datas" WHERE "condition" = 1 ORDER BY "id" ASC LIMIT 1
# => SELECT "users".* FROM "users" WHERE "id" = 1
# On cache hit:
# => SELECT "users".* FROM "users" WHERE "id" = 1

So, I wrote a quick module to make Marshal.dump and Marshal.load dump and load the association data, as well.

https://gist.github.com/keichan34/6448987

NB: This hack works with Rails 4, but I haven’t tried it on any other versions. YMMV.

Categories
English Uncategorized

Rails Security 101

I’ve come across too many Rails apps with the secret_token in version control. Don’t do that.

Categories
English Meta

Moved!

Just writing to let you know that I’ve switched servers for this blog! I’ve been meaning to get this on to a faster server that I have control over for awhile, and I finally got around to doing it.

For those of you who are curious, this site is being served by WordPress Multisite, on a Sakura 2G VPS.

And because everyone likes talking about stacks:

Stack.

Kidding.

That’s it! There is some moderate caching in most layers (WordPress Object Cache, APC, NGINX, etc), but nothing too drastic. It’s much faster now than it was on the previous server – we’ll see how this one holds up.

Thoughts during the Migration Process

MariaDB

I can’t say this enough – really, really, really smooth. Just stop mysql, remove, install MariaDB, then start it up again. All my data was migrated automatically.

NGINX + PHP + WordPress

There were a ton of guides for this kind of setup, but the two that most helped me were the WordPress Codex and rtCamp’s excellent WordPress + Nginx tutorials. Reading through both is highly recommended.

Categories
English WordPress

Making a (proper) WordPress Theme

One of the things that I’ve built regularly are custom WordPress themes for clients. Let me clarify — a custom theme for each client. One theme per client.

So, I decided to try my hand at making a “proper” WordPress theme — a theme for regular users. And I submitted it to the WordPress themes gallery. Successfully!

wp386 - my first public WordPress theme!
wp386 – my first public WordPress theme!

There were, however, quite a few catches along the way.

  • Code format / styling.
  • Completeness.
  • Compatibility / interoperability.
  • Edge cases.

TL;DR? Use _s.

Code format / styling.

If you are even a lightly experienced programmer, you understand the importance of a uniform code style. This applies here, too. WordPress has a few coding conventions that you should adhere to.

If you use _s, you’re pretty much set on this – just follow the conventions that have been established.

Completeness.

Support for comments, post titles, categories, tags, et cetera. You need it all.

Compatibility / interoperability.

This is a big one.

Please don’t design your theme to have any special features.

Since the purpose of Themes is to define the presentation of user content, Themes must not be used to define the generation of user content, or to define Theme-independent site options or functionality.

(read more)

Ideally, a user should not have the appearance of lost data when switching themes. Switch themes throughout development semi-regularly, just to make sure your users are happy both when they try your theme and when they try other themes.

Edge cases.

This is a little harder – there are quite a few edge cases (long titles, non-breaking text, you know the general culprits).

I strongly recommend using the WordPress Theme Unit Test suite of tools, including a WXR file full of edge cases, against your theme during development.

So?

Quite a few of these catches can be easily overcome by simply building your theme with a steady foundation. I highly recommend _s, a theme that Automattic (the makers of WordPress.com) built. Not only does it get you started with the basic features (think comments, theme hooks, base CSS classes), it will provide a basic template for more advanced features, such as Jetpack compatibility, the live theme editor, among others.

Have fun!

Categories
Code Snippets English

Facebook: Pop-in.

What do you do when you have a Facebook app tab (inside an iframe, mind you) that’s externally linkable? Pop-in.

Screen Shot 2013-08-07 at 9.43.48 AM

Let’s break this down.

if (self === top) {

This conditional will be true when the browser is not inside an iframe.

window.location.href = 'https://www.facebook.com/test/app_1234';

If we are not inside an iframe, then redirect to the following URL.

Categories
English Uncategorized

S3 Uploader

There have been more than a few times where someone needs to send a big file to me. So, I made a quick and dirty tool to allow anyone to upload files directly to a S3 bucket.

No more shuffling links around, worrying about them expiring, and wondering whether the data stored is safe or not.

Screen Shot 2013-08-06 at 5.17.27 PM

Fork away!

Source code

Categories
AWS English

Amazon IAM Policies: Granting one user access to a S3 bucket

It may be easy to use the same master Access Key and Secret Access Key for all your apps using Amazon AWS, but it’s definitely not secure and recommended against.

That said, I had a little trouble writing the IAM policy granting a single user access to a single S3 bucket. I finally had time to sit down and figure it out today, and turns out – it’s pretty easy. Up to this point, I’m assuming that you’ve already created your user, but if you haven’t – the IAM management console is located here: https://console.aws.amazon.com/iam/home?#users.

Once you’ve opened the “Permissions” tab of the user, click “Attach User Policy”.

Screen Shot 2013-07-12 at 9.03.58 AM
You’ll get a dialog with a bunch of choices – use the “Custom Policy” option, then click the “Select” button.

Here, you’ll enter the name of the policy (something descriptive) and the contents of the policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::bucket-name-here",
        "arn:aws:s3:::bucket-name-here/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "arn:aws:s3:::*"
    }
  ]
}

Of course, you need to replace “bucket-name-here” with the name of the bucket that you want to grant access to.

If you’re using a console or GUI tool (Transmit recommended 🙂 ), you’ll need the "Action": "s3:ListAllMyBuckets" section that’s included in the sample, but if you’re accessing your bucket programmatically, it’s not required.

Source: AWS Security Blog / “Writing IAM Policies: How to grant access to an Amazon S3 bucket”

Categories
English WordPress

Ruby/WordPress

Too long? tl;dr.

Situation: You’re migrating a big site to WordPress. You don’t want to make 1,000+ posts manually, do you?

Meet Ruby/WordPress. I’ve made a quick little Ruby gem that interfaces with your WordPress database, so you can manipulate it within Ruby. This opens up a whole world of possibilites – the most exciting being Nokogiri, of course.

Here’s a quick code sample that will create 100 new posts!

require 'wordpress'

# Configuration
wp = WordPress.new { host: '127.0.0.1',
                     port: 3306,
                     username: 'test',
                     password: 'test',
                     encoding: 'utf8',
                     database: 'wordpress',
                     wordpress_prefix: 'wp_' }

(1..100).each do |i|
  post = wp.new_post { post_name: "post-#{i}",
                       post_status: 'publish',
                       post_title: "Post #{i}" }
  post.post_content = "This is the content for post #{i}"
  post.save!
end

Note that the configuration must point to a valid WordPress database (and make sure you don’t use one with valuable data… I don’t take responsibility for any lost data. You should be backing up anyways.)

It’s at version 0.0.2, a very early beta at this point, but it can do basic tasks such as creating posts (as shown before) and post querying (albeit, very basic at this stage in development):

wp.query( post__in: [ 1, 5, 8] ).each do |post|
  puts "Post: #{ post.post_title }n"
end
wp.query( post_type: 'custom_post_type', post_parent: 10 ).each do |post|
  puts "Post: #{ post.post_title }n"
end

The ultimate goal of WordPress#query is to be fully compatible with the WP_Query API.

Another feature is post meta manipulation. After you get your post object (WordPress::Post), getting or setting post meta is very easy:

post.post_meta['hello'] = 'world'
puts post.post_meta['hello'] + "n"

Initial support for taxonomies is also included:

puts post.get_the_terms('category').join(', ') + "n"
post.set_post_terms ['love', 'WordPress'], 'category'

Note: WordPress::Post#set_post_terms will overwrite all terms of the given taxonomy, unless you supply the “append” flag:

post.set_post_terms ['love', 'WordPress'], 'category', true

As you can probably tell, this is not a very ideal API, and I am planning on changing it soon.

Contribution

Contributions are very welcome!! If you have an idea, or something that you would like to contribute, but don’t feel like you have something concrete enough for a pull request yet, please don’t hesitate to open an issue or contact me directly.

How to Install

Ruby/WordPress can be installed via RubyGems:

$ gem install ruby-wordpress

or, if you use Bundler:

gem 'ruby-wordpress', :require => 'wordpress'

Links:

Categories
English

LocationMatch and ProxyPass

Want to mix LocationMatch and ProxyPass? Not so fast.

<LocationMatch ^/(regex/here/.*)$>
  ProxyPassMatch http://backend/$1 
</LocationMatch>

Don’t forget to use ProxyPassReverse if you need it (it shouldn’t be inside the LocationMatch directive, though).

References: