No Pugs

they're evil

I always forget exactly how to do this…

echo check >> /sys/block/mdX/md/sync_action

…where mdX is the raid device name you want to check.

You can monitor the status of the check with cat /proc/mdstat

Published on 06/02/2012 at 03:30AM under .

0 comments

Recently, branch support for Subversion was added to externals.

Subversion does not have a branch feature. Instead, subversion users use the copy feature to copy directories within the repository (branch), a switch command to switch the URL that the working directory points at (checkout), and a merge feature to merge directories (merge).

ext handles branches in Subversion by splitting the URL given by ‘svn info’ into a repository part and a branch part.

If you find yourself doing this:

ext checkout svn+ssh://someserver/somepath/repository/branches/new_feature

Then you almost certainly mean to do this:

ext checkout svn+ssh://someserver/somepath/repository -b branches/new_feature

For ext to use branch-related features with Subversion repositories, the repository must be known. For subprojects this is never a problem, but for the main project, it’s important that there is a repository field under [.] in the .externals file. This can be accomplished by using -b with commands like ‘ext checkout’ and ‘ext init’ or by manually editing the .externals file.

For example, if you are working on svn+ssh://someserver/somepath/repository/current then you want your .externals file to look like this:

[.]
scm = svn
repository = svn+ssh://someserver/somepath/repository

Notice how I left off “/current” from the repository URL. “current” is the branch and not part of the repository from ext’s perspective.

Published on 09/28/2011 at 09:49AM under , .

110 comments

It’s common to need a new branch but the process in git has a few more steps than with most other SCMs.

The branch I will be creating will be called new_branch and I will create it in a remote repository named origin.

git push origin HEAD:new_branch

You can use the old branch’s name instead of HEAD if you’d like. Using HEAD just allows me to not have to know the current branch name.

git fetch origin
git checkout --track -b new_branch origin/new_branch

And there you have it, you’re now on new_branch which is tracking origin/new_branch

Published on 08/04/2011 at 09:06AM under .

0 comments

It looks like if a boolean property is set to false and it has a validates_presence_of validation on it, that the validation will fail. At least in rails 2.3.8 and rails 2.3.5 and I’m assuming all older and possibly newer versions.

It probably has to do with this:

  false.blank?

evaluating as true.

What worked for me was to use validates_inclusion_of instead:

  validates_inclusion_of :is_present_in_sentence, :in => [true, false]

Published on 04/12/2011 at 09:32AM under .

0 comments

If you create a named scope that uses :select, and then call “.size” or “.count” on the resulting proxy served by a call to the scoped method, and if that :select option sets DISTINCT, then it will be ignored because rails ignores the old :select and creates a new one of “COUNT(*) AS count_all”

Here is a made up example:

class Book < ActiveRecord::Base
  named_scope :on_a_favorite_list,
    :select => "DISTINCT ON (books.id) books.*",
    :joins => "INNER JOIN favorites_list_entries 
      ON favorites_list_entries.book_id = books.id"
end

Now let’s pretend that there is only one book on anybody’s favorites_list, but that two people have that book on their list.

Then this:

Book.on_a_favorite_list.map(&:id).size

would return 1, because size would be called on an array that only has 1 integer in it.

but…

Book.on_a_favorite_list.size

Would return 2! Why? Because the proxy object (remember, Book.on_a_favorite_list is NOT an array of books… it’s a proxy object that will fetch the books if needed) realizes it needs to create a COUNT query (it’s not going to actually fetch the books) and it does this by overriding the :select option from “DISTINCT ON (books.id) books.*” with “COUNT(*) as count_all”. So DISTINCT has been lost. Now the duplicate row appears to the select statement and 2 is returned as count_all to rails .size method.

One way around this is to pass the thing being counted, including the DISTINCT keyword, to size…

Book.on_a_favorite_list.size("DISTINCT books.id")

This will return the expected result of 1.

Published on 08/21/2010 at 08:56PM under , .

57 comments

If you are getting this when running rails migrations using a postgresql adapter:

Input string is longer than NAMEDATALEN-1 (63)

Then this tiny plugin can solve this problem. Index names longer than 63 characters work fine with some postgresql adapters and not others. I’m not sure why. This adds a method to ActiveRecord::ConnectionAdapters::PostgreSQLAdapter that keeps the index_names under the limit.

here’s the entire piece of code:

ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
  #There are PostgreSQL drivers/versions of drivers that truncate
  #index names to 63 characters. Since some do not, this override makes
  #sure that the truncate occurs regardless of PostgreSQL driver.
  def index_name(table, columns)
    super(table, columns)[0..62]
  end
end

To install this plugin using ext, you can use:

ext install git://github.com/azimux/ax_fix_long_psql_index_names.git

or, using rake plugin:

./script/plugin install git://github.com/azimux/ax_fix_long_psql_index_names.git

Published on 05/02/2010 at 04:26PM under , .

774 comments

It seems that you cannot create a local variable dynamically in ruby using eval with a binding.

Here’s an example from an IRB session:

irb(main):001:0> def make_a(b)
irb(main):002:1>   eval "a = 'this is a!'", b
irb(main):003:1> end
=> nil
irb(main):004:0> a
NameError: undefined local variable or method `a' for main:Object
        from (irb):4
        from :0
irb(main):005:0> make_a(binding)
=> "this is a!"
irb(main):006:0> a
=> "this is a!"
irb(main):007:0> def test_a
irb(main):008:1>   a = 10
irb(main):009:1>   make_a(binding)
irb(main):010:1>   puts a
irb(main):011:1> end
=> nil
irb(main):012:0> test_a
this is a!
=> nil
irb(main):013:0> def test_a
irb(main):014:1>   make_a(binding)
irb(main):015:1>   puts a
irb(main):016:1> end
=> nil
irb(main):017:0> test_a
NameError: undefined local variable or method `a' for main:Object
        from (irb):15:in `test_a'
        from (irb):17
        from :0
irb(main):018:0>

The last NameError in that IRB session makes no sense to me. I have tried this in Ruby 1.8.6 and in Ruby 1.9.1 and both give the same result.

Can somebody explain what is going on here? Are there any known workarounds for this? I was trying to DRY up some particularly repetitive code, part of which involves initializing a local variable, when I stumbled upon this. I’m having trouble finding blog posts that explain this unexpected behavior, and none of the official documentation that I’ve looked at for Binding and eval seem to point out that you cannot declare local variable in such a manner.

Here’s a stripped down version of the code if you want to put it in your own IRB session and play with it:


 def make_a(b)
   eval "a = 'this is a!'", b
 end
 a
 make_a(binding)
 a
 def test_a
   a = 10
   make_a(binding)
   puts a
 end
 test_a
 def test_a
   make_a(binding)
   puts a
 end
 test_a

Published on 03/10/2010 at 02:29PM under .

4 comments

In Ruby on Rails, it’s common to have a resource have a one-to-one correspondence with a model. Often you will have a create action that looks something like this:

class UsersController < ApplicationController
  # ... other actions, etc

  def create
    User.transaction do
      @user = User.new(params[:user])

      if @user.save
        flash[:notice] = 'User was successfully created.'
        redirect_to(@user)
      else
        render :action => "new"
      end
    end
  end

  # ... other actions
end

Now what if we have another model object that is also managed by this action, perhaps a profile object? Perhaps using the fields_for helper in the view?

Then we might change our code so that it looks something like this:

class UsersController < ApplicationController
  # ... other actions, etc

  def create
    User.transaction do
      @user = User.new(params[:user])
      @profile = Profile.new(params[:profile])

      user.profile = @profile

      if @user.save && @profile.save
        flash[:notice] = 'User was successfully created.'
        redirect_to(@user)
      else
        User.connection.rollback_db_transaction
        render :action => "new"
      end
    end
  end

  # ... other actions
end

And our new.html.erb view will have a form that looks something like this:

<% form_for(@user) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>

  <%# Other fields using the "f" builder %>

  <% fields_for(@profile) do |builder| -%>
    <%= builder.error_messages %>
    <p>
      <%= builder.label :favorite_movie %><br />
      <%= builder.text_field :favorite_movie %>
    </p>

    <%# Other fields using the "builder" builder %>

  <% end %>
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

There should be no problems here right? Wrong. The problem is that in edit.html.erb, we are going to also have a form_for(@user) and fields_for(@profile). So how does new.html.erb and edit.html.erb know to create a form action of create_user_url and update_user_url, respectively? It does this by checking the new_record? method of the passed in model.

Here’s where a problem is created. Lets revisit part of our controller code for the create action:

      if @user.save && @profile.save
        flash[:notice] = 'User was successfully created.'
        redirect_to(@user)
      else
        User.connection.rollback_db_transaction
        render :action => "new"
      end

If @user.save fails, @user.new_record? will still be true. This is what we want since we will be calling render :action => 'new' and we want the form generated there to call create_user_url, not update_user_url.

But what happens when @user.save works and @profile.save fails? @profile.new_record? will still be true, which is good, but @user.new_record? will be false, because it successfully saved! The user row will not exist in the database, because we rolled back our transaction, but only @profile knew to revert to an unsaved active record state. @user has no idea what’s going on.

So then, when new.html.erb renders form_for(@user), it will create a form with the update_user_url instead of create_user_url! This will result in an exception like this:

 ActiveRecord::RecordNotFound in UsersController#update

Couldn't find User with ID=2

To understand how to fix this, we need to understand why it works with only one model. It works because @user.save calls rollback_active_record_state! which records the object’s state, with respect to things like new_recodr?, and takes a block that it executes in a begin/rescue block. If it catches an exception, it reverts to the state it was in before it yielded to the block, and reraises the exception. The exception is usually ActiveRecord::Rollback, which is gobbled up by a transaction that @user.save starts before calling rollback_active_record_state!

We can fix the problem by using this method on both objects, and throwing an exception if any of the models fail to save.

The above if statement becomes something like this:

      #an anonymous Exception class, it's best to create a real class for use
      #in multiple locations
      ec = Class.new(:Exception)

      begin
        @user.rollback_active_record_state! do
          @profile.rollback_active_record_state! do
            if @user.save && @profile.save
              flash[:notice] = 'User was successfully created.'
              redirect_to(@user)
            else
              User.connection.rollback_db_transaction
              raise ec.new
            end
          end
        end
      rescue ec
        render :action => "new"
      end

I have created a plugin that helps replace this type of code. It works with any number of model objects across any number of database connections.

It is at git://github.com/azimux/multimodel_transactions.git

With it installed, the above code becomes:

ax_multimodel_if([@user, @profile],
  :if => proc {
    @user.save && @profile
  },
  :is_true => proc {
    flash[:notice] = 'User was successfully created.'
    redirect_to(@user)
  },
  :is_false => proc {
    render :action => "new"
  }
)

Note to Smalltalk users: if you need an example of ruby’s block passing syntax making certain method calls look a little ugly, there you go :P

There is also another method in the plugin that helps with models being in multiple databases (or the future possibility of such a thing happening.): ax_multimodel_transaction

To apply it to the above call to ax_multimodel_if, it would look somewhat like this:

ax_multimodel_transaction [@profile], :already_in => @user do
  ax_multimodel_if([@user, @profile],
    :if => proc {
      @user.save && @profile
    },
    :is_true => proc {
      flash[:notice] = 'User was successfully created.'
      redirect_to(@user)
    },
    :is_false => proc {
      render :action => "new"
    }
  )
end

h1. Gotchas

1) If @profile has the user_id foreign key, it’s important to do:

@user.profile = @profile

and not:

@profile.user = @user

When neither of the objects have been saved yet. I’m not exactly sure why this is, I just know from experience that if you do it the other way around, @profile will be saved with a nil user_id

2) Like always when doing things sensitive to transactions and rollbacks, you might wish to add a “self.use_transactional_fixtures = false” to the relevant functional test. This is really only necessary if your test runs commands that execute queries that are not expecting to be inside of a rolledback transaction after the call to “post :create” or “post :update” or whatever. It is only very rarely necessary to do, but it’s good to keep in mind when writing more complex functional tests.

Published on 01/27/2010 at 03:01PM under , .

2 comments

It looks like the exception_notification plugin is undergoing a pretty big overhaul to get it working well with rails3. The official git repository for that plugin only has one branch, master. What should you do for your existing rails2 applications that are not ready for migration to rails3?

If you are getting something somewhat like this:

rake aborted!
uninitialized constant ApplicationController::ExceptionNotifiable
.../rails/activesupport/lib/active_support/dependencies.rb:102:in `const_missing'

You can fix it by using commit e8b603e523c14f145da7b3a1729f5cc06eba2dd1 of that plugin.

Something like this should do the trick:

cd vendor/plugins/exception_notification
git checkout -b rails2 e8b603e523c14f145da7b3a1729f5cc06eba2dd1

That particular commit is from November 13, 2008. It is the last commit not having anything to do with rails3, and it is a very stable commit and unlikely to need modification for existing projects.

if you are using externals to manage your subprojects, you can quickly fix it like this (from the main project directory):

ext freeze exception_notification e8b603e523c14f145da7b3a1729f5cc06eba2dd1

Published on 01/26/2010 at 06:26PM under , , .

79 comments

Upgrading via a git merge might not be the best way of upgrading typo. The safest way is probably to follow the instructions in the UPGRADE file. However, I have a few modifications I've made to Typo that I'd like to preserve.

So I went ahead and merged 5_3_0 with my 5.1.3 branch and ran a db:migrate

I couldn't log in anymore. It turns out a "status" column is added to the users table in a migration, and in the same migration, each existing user's status is set to "active"

The problem is that after a db:migrate, the status column was still NULL. What happens is that it works if you run 1 migration at a time. But if you run the migration that adds and sets the status column to "active" in the same rake invocation that has already accessed the User class, it will already have the old columns loaded into it and will not think the "status" column even exists.

To fix it, you need to issue a User.reset_column_information after adding the column.

This column is not the only problem column, the "text_filter_id" and "editor" column also failed to update.

Below is a quick patch I made from my typo repository. I only went back to the migrations I was missing between 5.1.3 and 5.3 and made sure any model classes that were used had "reset_column_information" called before using. If you are going to attempt upgrading your typo blog via a git merge/pull, this patch might be useful.

0001-Changed-some-recent-migrations-to-call.patch

A note about an oddity I ran into when running these migrations in a production environment: You'll need to set config.cache_classes in config/environments/production.rb to false while running the migrations, otherwise it might try to preload information about classes whose tables don't yet exist. I'm not exactly sure why this happens, I've never had this problem in the past.

Published on 12/02/2009 at 10:08PM under , .

2 comments

Powered by Typo – Thème Frédéric de Villamil | Photo Glenn