Rails and Bootstrap

This hit me when I was rewriting front-end part of Zeropaste. Of course later I found out that there’s gem for it.

But anyway, if you don’t want to add another gem and feel like writing crapload of divs, it’s not that difficult. It breaks Rails standard form error handling though.

First, change the default error field handling to do nothing instead of wrapping it in a div:

config.action_view.field_error_proc = proc { |html| html }

(put in application.rb)

And then create this helper:

def error_class(object, attribute)
  "has-error" if object.errors.include? attribute
end

Finally, here’s how to use it (for attribute key of a model):

<div class="form-group <%= error_class f.object, :key %>">
  <%= f.label :key %>
  <%= f.text_field :key, :class => "form-control" %>
</div>

…and done.

Zeropaste update

I decided to mess around with Zeropaste and added some “features”:

  • Show paste in plaintext (fixed width) and Markdown
  • Allows displaying paste in fixed width instead of full/auto
  • Setting mode and width based on url
  • Automatically updating url based on selected mode and width

0paste.com has been updated accordingly, including Rubinius 2.0.0rc1.

Now you can read glopping Asuna in convenient fixed width markdown (NSFW).

Yet another pastebin: 0paste.com

I decided to get a domain for it because of :reasons:. Anyway, the old ones from p.myconan.net is still accessible (it’ll redirect to new url at 0paste.com). Donations welcome.

Also because the world needs yet another pastebin. This one is running on Rubinius using Puma, by the way. Four threads with awesomest possible caching for showing pastes.

[ 0paste.com | Source ]

Zeropaste – the featureless pastebin

Tonight, when trying to compile Rubinius with Rubinius, I got some errors and wanted to report to relevant party. As usual, the log of what happened is required so I used my usual pastebin – pastie.org to send the logs. But then I noticed that the “Raw” link in it doesn’t provide an actual raw file anymore. What the fuck. It is now a html disguised as txt.

So I decided to whip up a new pastebin (because the world need one more pastebin) which doesn’t have any actual features (like tag highlighting, etc). I also learned the way to create shortest RESTful path possible (read: ‘/’).

There may or may not be more features coming. Developed in Rubinius because I can. Using mysql because of where it’ll be deployed at (see below).

I’ll get around deploying this soon after reinstalling VPS running this blog to Ubuntu or Debian. Running yum in a 128 MB box is suffering.

[ Source Code ]

Ruby 1.9, Rails, and UTF-8

(main purpose of this post is to link this “server error” page of rubygems.org)

The relevant issue in Rails Issue Tracker (3789). AFAICT, there are few ways to “fix” (read: workaround) this:

  • Modify the relevant Rack code to handle this crap
  • Create additional middleware to intercept (how?) the request (tried, either didn’t work or horribly inefficient)
  • Extend rack before it is started

Well, they all sucks. Hopefully someone comes up with actual working solution for this.

Oh, there’re another solutions:

  • Use REE 1.8 (really?)
  • Use JRuby in 1.8 mode
  • Use Rubinius (rbx 2.0 where?) in 1.8 mode

Um, yeah.

Update: I figured out how to “fix” it. Check it out in Moebooru (requires this).

Rails: read_multi and dalli

Be careful when using read_multi with dalli: it may return nil-valued key instead of the correct key.

The issue is tracked here and thanks to this I dropped the read_multi usage in moebooru and used the much simpler (and most likely slower) single fetch (per entry) instead. There’s alternative way to use it – do a read_multi and refetch whatever missing/nil-keyed but apparently I’m too lazy to do it.

Moebooru 3.2

Finally reached the goal: Rails 3.2.6. The isn’t much change between 3.1 and 3.2 which is why I skipped 3.1. As there isn’t much front-end change, it means there isn’t any user-visible changes. Or at least there shouldn’t be.

Plans:

  • Move to jQuery
  • Use paper_trail for versioning (or something else)
  • Add SVG support (and maybe drop SWF support)
  • Actual news ticker
  • And more!

3.2.0 has been branched and currently running on some servers. The next version, 3.2.1 is on default branch and being tested on moe.myconan.net. As (finally) there are database changes, it will not be tested directly on live servers until it is stable enough.

Changes include better support for JRuby, use mini_magick instead of custom plug-in, less monkey-patches (but more bugs), and various clean-ups.

Rails 3.2 in Subdirectory

Steps to be into Rails in subdirectory:

Update config.ru to understand the subdirectory mapping:

run Moebooru::Application

change to

map (ENV['RAILS_RELATIVE_URL_ROOT'] || '/') do
  run Moebooru::Application
end

And then start Rails with correct environment variable (example if you use Unicorn):

RAILS_RELATIVE_URL_ROOT='/img' bin/unicorn

And that’s it. No need to mess with routes.rb as I previously thought after searching and experimenting for few hours. Links etc are properly generated with correct prefix. Or at least based on my quick testing.

May or may not work with earlier version(s) as I haven’t bothered to test it anywhere else.

Moebooru/Rails 3, and more

After working on it for several weeks, finally it got to the point where it’s relatively usable. No more Bundler-on-Rails2 evilry and the fact that 3.0 branch is still supported.

The best part is the one above. Yes, Moebooru now runs on Rubinius/Puma. The only foreseeable problem is it uses Process.pid on file uploads which, when several people uploading (or working with) files at same time, the temporary filename will collide.

Though due to me aiming more for workable implementation instead of correct implementation, there are quite a lot legacy stuff still in there:

  • repeated_auto_complete doesn’t work in Rails 3 without vendoring or updating the gem itself  (and I did both since Bundler’s git functionality seems broken in Rubinius).
  • prototype_legacy_helper must be used since I haven’t had time to upgrade the *_remote functions (and still thinking how to do it).
  • verification gem since I haven’t upgraded the route and its functionality, which previously built-in in Rails 2.3 has now removed.
  • Unsightly lib/core_ext. Just look at evilry I have added to make it behave like 2.3-stable.

On the brighter side, now I can start cleaning up the code. Or upgrade all the way to Rails 3.2 ( ¬‿¬)

Optimize all the queries!

While digging more into the code called “Moebooru” which was forked from “Danbooru”, I noticed this:

def self.included(m)
  m.extend(ClassMethods)
  m.after_create :increment_count
  m.after_destroy :decrement_count
end

def increment_count
  connection.execute("update table_data set row_count = row_count + 1 where name = 'users'")
end

def decrement_count
  connection.execute("update table_data set row_count = row_count - 1 where name = 'users'")
end

Counting takes ages, right. Except it is not. I’ve done this, yes, but on a table with 10+ millions of data (this one has ~400k in mainline danbooru), with multiple data inserted (this one got, uh, one every other week?) and queried every second (see below), and with the required count method not a simple select count(1) on some_table (which is what the example above used for).

The best part? It’s only used once, when user registers:

def set_role
  if User.fast_count == 0
    self.level = CONFIG["user_levels"]["Admin"]
  elsif CONFIG["enable_account_email_activation"]
    self.level = CONFIG["user_levels"]["Unactivated"]
  else
    self.level = CONFIG["starting_level"]
  end

  self.last_logged_in_at = Time.now
end

moebooru again

Last week I posted about my random project which involves modernizing moebooru without doing complete rewrite (see this for yet another complete rewrite attempt).

Let’s revisit the plan:

  • Upgrade to Ruby 1.9: done, need testing.
  • Update all plugins: mostly done, can use some trimming.
  • Update anything deprecated: nope
  • Migrate to Bundler: done, not sure how to test.
  • Use RMagick instead of custom ruby-gd plugin: nope
  • Use RMagick instead of calling jhead binary: nope
  • And more!: I hope you didn’t expect me to do more while there are incomplete items above.

Sure looks good. Need more testing though. There’s also one part which I totally had no idea why should be changed when upgrading to 1.9. Just grep for FIXME to see which it is and hopefully fix it up for me (or explain what it does).

As usual, having completed the work for today, live demo is up and open for everyone to break (…if there’s anyone, that is).

[ Live Demo | Repository ]

An Attempt to Update moebooru Engine

If you didn’t know, the current moebooru running on oreno.imouto is using ancient version of many things. It also uses a custom lighty module (mod_zipfile) which doesn’t seem to be available anywhere.

I’ve updated it with latest Rails 2.x and made it compatible with nginx. Mostly. You can see it running here.

The plans:

  • Upgrade to Ruby 1.9.
  • Update all plugins.
  • Update anything deprecated.
  • Migrate to Bundler.
  • Use RMagick instead of custom ruby-gd plugin.
  • Use RMagick instead of calling jhead binary.
  • And more!

We’ll see if I can actually finish this one. Grab the source here. Yeah, I’m using Mercurial for a Rails project.

danbooru for windows

😆

This morning I randomly decided to try installing danbooru on Windows (7-x64). And indeed it works. Mostly.

Using mongrel and nginx since unicorn is not available on Windows.

Few things to note:

* system_timer is missing since I can’t seem to install it. Probably need to try ruby19 or ruby18-1.8.6-p27 (currently using ruby18-1.8.6-p383)
* manual initial database initialization since the script I made is specifically for *nix systems
* compiling danbooru_image_resizer is… *fun*
* for whatever reason I can’t install mongrel_service
* apparently there’s something missing. Or broken. Or both – there’s message “The system cannot find the path specified.” every time I start mongrel and do migrate

…anyone interested trying this on production server? 😛

_Last update 2011-07-18 21:01: formatting, also added rewrite rule for nginx to cope with uploaded media path change_