Blog
what did i learn today
News rails-assets ruby ssl gem rails
[rubygems] handling SSL errors on Windows when installing gems

When you encounter SSL errors when installing gems on Windows, the easiest workaround is to change your sources from https://... to http://.... But ... I am an avid user/fan of rails-assets.org and today I suddenly started getting the error on their domain.

So at first I feared that rails-assets had stopped as foreseen (in this ticket), but the site was still reachable, and actually they switched (imho just two days ago) to a new maintainer, which is awesome: the future of rails-assets is safe for now.

But there is no rose without a thorn and now rails-assets enforces TLS (which is actually a good thing), so it is always SSL and gem cannot ignore SSL anymore. Doh! So I was stuck on windows.

I tried to make gem command ignore ssl errors regardless, by creating c:\ProgramData\gemrc with the following content:

---
:ssl_verify_mode: 0

and that partly worked: I was now able to fetch the index, but now I received the SSL error on the first gem retrieved from rails-assets, so I was still not in the clear. I had to make sure the SSL verification actually worked!

Fortunately, after some googling this proved easier then expected! The root cause is that ruby on windows (or openssl) has no default root certificate. So I found a good description how to fix that on windows.

I used the boring/easy/manual approach, in short:

  • download the cacert.pem file from http://curl.haxx.se/ca/cacert.pem. I saved this to my ruby folder (e.g. c:\ruby21).
  • add an environment variable SSL_CERT_FILE, so ruby can pick it up. E.g. in your command prompt type set SSL_CERT_FILE=C:\ruby21\cacert.pem. To make this a permanent setting, add this to your environment variables.
More ...
News routing devise rails
[rails routing] protecting a mounted engine

In a project we built, we are using que for doing our background-jobs, and there is a very simple (but sufficient) and clean web-ui, called que-web, allowing us to monitor the status of the jobs online.

And normally, you just include it in your project by adding the gem, and then adding the following to your config/routes.rb :

require "que/web"
mount Que::Web => "/que"

But, this is completely open and unauthenticated. So we use devise, and it is really easy to limit a route to authenticated users:

require "que/web"
authenticate :user do 
  mount Que::Web => "/que"
end

At least this limits the accessability to logged in users. But we wanted it to be available only to admin-users. So I thought I had to resort to defining my own constraint-class, as follows

class CanSeeQueConstraint
  def matches?(request)
    # determine if current user is allowed to see que
  end
end

and in the routes write it as follows

require 'can_see_que_constraint'
mount Que::Web, at: '/que', constraints: CanSeeQueConstraint.new

The problem was: how do I get to the current user, in a constraint class? So I took a peek at how the authenticate block in devise works, and apparently there is an easier option: the authenticate block takes a lambda, where you can test the currently authenticated user. Woah! Just what we need. So we wrote the following to only allow our adminstrators to see/manage our background jobs:

authenticate :user, lambda {|u| u.roles.include?("admin") } do
  mount Que::Web, at: 'que'
end
More ...
Technology ruby method_missing rails
[rails] store your settings in a model

Most of the times I use a config.yml to store application settings, that I want to be able to change quickly between environments, servers, deployments. But what with settings that need to be changed on the fly, by a user?

I create a small model, with three fields.

rails g model Setting name:string description:string value:string

I use a seed file to define the different settings. Settings are checked in code, but I can not preload them, since a user might change them. So first I added a method as_hash that loads all settings, and I can then directly use a hash, but that gets wordy quickly.

What if ... I could provide a method on the class Setting for each setting in the database? That would be really nice. This seems like a job for ... method-missing-man Special superpower: seeing places where method_missing could be used :)

class Setting < ActiveRecord::Base

  validates_presence_of :name

  def self.as_hash
    settings = {}
    Setting.all.each do |setting|
      settings[setting.name.to_sym] = setting.value
    end
    settings
  end

  # offer all settings as methods on the class
  def self.method_missing(meth, *args, &block) #:nodoc:
    @all_settings ||= Setting.as_hash
    if @all_settings.keys.include?(meth)
      @all_settings[meth]
    else
      super
    end
  end
end

For documentation, the test:

context "convenience: define methods for all settings" do
  before do
    Setting.instance_variable_set('@all_settings', nil)
    Setting.create(name: 'my_other_test_setting', value: '123ZZZ')
  end
  it "Setting.my_other_test_setting returns the correct result" do
    Setting.my_other_test_setting.should == '123ZZZ'
  end
  it "an unexisting setting behaves as a normal missing method" do
    expect {
      Setting.this_setting_does_not_exist
    }.to raise_exception(NoMethodError)
  end
end

I love ruby :) :)

More ...
Technology staleobjecterror activerecord rails
automatically handle StaleObjectError in rails 3.x

There are different reasons why a ActiveRecord::StaleObjectError would occur. Sometimes it is caused because rails does not have a stable identity map yet. This means that if the same object would be retrieved via different associations, your rails process would not know they point to the same object, would keep different copies of the same object and that could easily cause a StaleObjectError if you attempt to change both.

Such an occurrence needs to be fixed structurally in your code. But sometimes you can get StaleObjectError because things happen at the same time. There are two ways to handle this:

  • make sure that controller actions which affect the same object, are always executed sequentially. One way to achieve this is to lock the object you want to update in the database. Then all other processes wanting to update the same object will have to wait until the lock is released (and the lock can be acquired). This is a valid approach but costly, intrusive (you need to explicitly add code), and possibly dangerous. It is normally easy to avoid, but you have to be careful for deadlocks and locks that are never released.
  • when a StaleObjectError occurs, just retry the request

Now that second option seems valid, if only it would be easy to handle. Luckily there is a very easy and unobtrusive way to automatically retry all requests when a StaleObjectError occurs. Let's just create a middleware that catches the exception and retries the complete request a few times.

Create a new file lib/middleware/handle_stale_object_error.rb containing the following:

module Middleware 
  class HandleStaleObjectError 
    RETRY_LIMIT = 3 
    
    def initialize(app) 
      @app = app 
    end 

    def call(env) 
      retries = 0 
      begin 
        @app.call(env) 
      rescue ActiveRecord::StaleObjectError 
        raise if retries >= RETRY_LIMIT 
        retries += 1 
        Rails.logger.warn("HandleStaleObjectError::automatically retrying after StaleObjectError (attempt = #{retries})") 
        retry 
      end 
    end 
  end 
end

Then in your config/application.rb you need to add the following lines at the bottom to activate the middleware (this requires a restart of your rails server):

 #
 # Middleware configuration
 #
 require 'middleware/handle_stale_object_error'
 config.middleware.insert_after ActiveRecord::SessionStore, Middleware::HandleStaleObjectError

Warning : this code will retry all occurences of StaleObjectError. For some occurrences this will not help at all, so you have to use your own judgement if this middleware is something you want in your codebase. I like this approach because it is an "optimistic" approach: it only adds extra processing when a StaleObjectError occurs, and when a not-fixable StaleObjectError it still fails as it should.

Hope this helps.

More ...
Technology ruby debugging session rails
logging the activerecord-session-store

I had an issue where I was not sure the ActiveRecord::SessionStore was actually working (in hindsight: it worked). But to make sure, I needed to know what was stored in the session or retrieved.

All logging for the session-store is silenced, using Base.silence.

Obviously I was very interested in that logging, and did not find another to unsilence the logging but to add an initializer with the following code.

So in file config/initializers/unsilence_logging.rb write:

class ActiveRecord::Base 
  def self.silence 
    yield self 
  end 
end

This will unsilence the SessionStore logging. Your logging will look like this:

 ^[[1m^[[36mAREL (0.0ms)^[[0m ^[[1mUPDATE "sessions" SET "data" = 'BAh7DEkiFnF1aWN<<snipped to protect the inncocent>>iEi9mcC9kYXNoYm9hcmQ= ', "updated_at" = '2012-05-04 11:17:24.704491' WHERE "sessions"."id" = 33635

This at least allows us to verify that the sessions are stored and retrieved correctly. But how can we see what is stored inside the session? To be able to read or inspect what is actually stored in the session, you can use the following line:

session_data = 'BAh7DEkiFnF1aWN<<snipped to protect the inncocent>>iEi9mcC9kYXNoYm9hcmQ= ' 
Marshal.load(ActiveSupport::Base64.decode64(session_data))

And this will present your session data in a readable format.

This way I learned that a time-drift between our two servers caused a very obscure bug. I hope it can help you too.

More ...
News content_for view testing yield rails rspec
[rspec] view testing: testing the content_for results

I normally do not do a lot of view specs, but at least I want to make sure that my view renders without errors. And sometimes I really need to make sure that some link is shown or hidden depending on e.g. the role of the user or linked objects.

For example,

 describe "posts/show.html.haml" do
   context "without any comments" do
     it "displays no comments" do
       @post = Factory(:post)
       render
       rendered.should contain(I18n.t('posts.show.no_comments'))
     end
   end
 end

So we check the rendered result, whether it contains a specific text.

But what happens if your view is rendering different yield regions? Like a body (the default region) and a sidebar.

Let's use a view like this :

  = show_for @post do |p|
    = p.attribute :title 
    = p.attribute :content
  - if @post.comments
    = render :partial => 'comments' 
  - else 
    = t('posts.show.no_comments')
 
  = content_for :sidebar do
    = link_to 'Edit', edit_post(@post) if is_allowed_to?(:edit)

It renders the attributes using the show_for gem, and then renders inside the sidebar a link if the current user is allowed to edit it.

Now I want to test what is rendered into the sidebar. To my dismay I found that neither content_for or content_for?worked at all inside rspec.

And rendered does not contain the data for the other regions.

So somehow I would want to get to the content for :sidebar.

It appears that the different regions are actually stored inside an instance variable of the view. Once I figured that out, the rest was easy:

  describe "posts/show.html.haml" do
    def rendered_content_for(name)
      view.instance_variable_get(:@_content_for)[name] 
    end 
    
    context "with enough rights" do
      it "displays a link to edit the post" do
        @post = Factory(:post)
        view.stub(:is_allowed_to?) { true }
        render
        rendered_content_for(:sidebar).should contain('Edit') 
      end
    end 
    context "with no rights" do
      it "does not display a link to edit the post" do
        @post = Factory(:post)
        view.stub(:is_allowed_to?) { false }
        render rendered_content_for(:sidebar).should_not contain('Edit')
      end
    end
  end

Hope that this helps somebody. Or did you find a better way?

More ...
News arrrrcamp fast tests rails rspec
Rethinking your design: slim models, fat presenters?

For me, it started with a tweet from Uncle Bob Martin, saying that if all your domain logic is in your model, or if you put your domain logic inside your models by default, then you are doing it wrong. I think the reasoning behind this is that we should design the domain model before relying on our database model (which is actually an implementation of that domain model). Because the best way to store something in the database is not always to best way to treat or represent or handle the data. In my Rails projects, I have to admit that in most cases the database is my domain model. Which in simple cases is correct, but in more complex cases it is not anymore. Secondly what happens is that your database model could shine through in your UI, or if it does not, your views or helpers could get very heavy. One good way to handle this is to use Presenters. Which goes into the direction of that domain logic, independent of the database. A Presenter is a class that groups all data, knows where to find it, or store it, and will match one-on-one on your presentation/view logic. Thirdly, I went to arrrrcamp, and there was Corey Haines doing his talk about Fast Rails Tests. While this title was very promising, Corey warned us that, in his own words, we would be underwhelmed. This was not entirely true, but not entirely false either :) In short what Corey said was: testing in Rails is slow because we need to drag around the framework, so why not cut out the framework where possible. So he showed an example where he extracted code from models and into separate modules, where you test them standalone. Standalone means: without requiring @spec_helper@. I did this for our modules inside @lib@ where possible, and truth be told: those specs now really fly! Awesome. But the large parts of our test-suite is our models, controllers, views, helpers where this is not possible nor wanted. I want to be able to run our complete test-suite faster, and this was not a solution for that. We scraped a few seconds of our complete time. Extracting code from our models into standalone modules will not make our total test-suite go faster either. Still it is something well worth investigating further. I don't believe in splitting up classes into modules just for the sake of making my tests faster. There has to be some logical reason (pertaining to the domain model --that is). But maybe presenters could be the way out here:

  • they group domain logic
  • while they are responsible for retrieving the correct objects from the database, these actions are just delegated to the responsible models So that sounds promising to me and a road I will investigate.
More ...
News ruby migrate to rails3 rspec2 rails3 rails
Porting an existing rails 2 site to rails 3

I have created a few rails 3 sites, but i have never before ported an existing rails2 application to rails3. I will describe the problems i encountered. First off there were some very good resources (step-by-step descriptions) to guide me through it:

ActiveSupport::Callbacks

Before we wrote: [ruby] module Workflow class Base define_callbacks :before_something, :after_something def some_method run_callbacks :before_something puts "some method" run_callbacks :after_something end end class SpecificWorkflow < Base before_something :do_something def do_something puts "something" end end [/ruby] Now, this has changed. Into the following: [ruby] module Workflow class Base define_callbacks :something def some_method run_callbacks :something do puts "some method" end end end class SpecificWorkflow < Base set_callback :something, :before, :do_something def do_something puts "something" end end [/ruby] Which is pretty nice. It has the disadvantage we can only use :before and :after callbacks anymore, but that was easily solved.

ActionController::ParamsParser

We hooked into the Rack middleware before the ActionController::ParamsParser to make sure we return Bad Request when the parsing fails. This middleware has been renamed to ActionDispatch::ParamsParser. Easy fix :)

safe_helper removed?

We prepared our Rails 2 project a long time ago, and used the rails_xss plugin. We used the safe_helper all over our helper-methods, but apparently this is not supported in Rails 3. Bummer. So, before [ruby] def some_helper "<strong>something</strong>" end safe_helper :some_helper [/ruby] After: [ruby] def some_helper "<strong>something</strong>".html_safe end [/ruby] A bit annoying to do, a bit unfortunate, because we thought we were preparing ourselves for a smoother upgrade. Not entirely so.

The routes!

Only after those steps did my rails get far enough to discover my routes. I did not change anything about the routes, just placed inside the correct block. I deleted my index.html and put back my original application.html.haml and the first view was working.

The missing to_key

The to_key was missing inside the user_session model. I described that solution already in this blogpost. So i just needed to fix that.

Replacing ActionController::RecordIdentifier.singular_class_name

We used ActionController::RecordIdentifier.singular_class_name, in rails3 this is replaced by ActionController::RecordIdentifier.dom_class.

Missing translations

A feature we used a lot was I18n.t('.filter') and this would look for operators.filter.filter because the line was inside a partial _shared/_filter.html.haml and called from the operators/index.html.haml. Now this does not work anymore, and now instead I18n looks for _shared.filter.filter. I did not find an easy way to solve this, just moved some translations. Luckily we did not override the translations of a partial based on the context where it was rendered yet. Does anybody has any tips on that?

Upgrading javascript helpers

In rails3 unobtrusive is the way to go. So, a remote_form_for like [ruby] - form_remote_tag :url => update_url do [/ruby] becomes [ruby] - form_tag :url => update_url, :remote => true do [/ruby] Which seems easy enough. It does get more complicated when the :update tag is used. For example: [ruby] - remote_form_for post, :update => {:success => "result_#{id}"} do |form| [/ruby] becomes [ruby] - remote_form_for post, :remote => true, :html => {:class => 'remote-post-form', :'data-update' => "#result_#{id}"} do |form| [/ruby] The :update is no longer supported as before, and we have to perform some glueing ourselves. So i replaced the :update by data-update. And then inside javascript (e.g. application.js) we can do the following: [javascript] jQuery(function($) { $(".remote-post-form") .bind("ajax:success", function(data, status, xhr) { var update_selector = $(this).attr('data-update'); $(update_selector).html(status); }); }); [/javascript] If you need more elaborate example, check this question on stackoverflow.

master_helper_module

This has been replaced by _helpers.

active_layout

The active_layout method, of a controller, no longer exists inside rails3. To replace it you need to use two methods:

  • action_has_layout? returns true if a layout exists.
  • To get the layout-name, i have no better solution then calling the private method _layout. This can be done, as known, by doing controller.send(:_layout).

Upgrade rspec

I had to upgrade Rspec 1 to v2. First off in the Gemfile i added the correct version. I removed the rspec.rake file. I ran [ruby] rails g rspec:install [/ruby] But still all rake spec commands were missing. The fix was simple. In the Gemfile make sure the rspec-rails is also usable from development mode: [ruby] group :development, :test do gem 'rspec-rails' end [/ruby] Now on to fixing the tests!

Fixing the tests

In the upgrade from rspec1 to rspec2 a lot of things have changed. What i encountered:

  • replace all Spec:: by RSpec::
  • controller_name 'users' no longer exists, write a surrounding describe UsersController do instead (that is also clearer imho)
  • ...

Extending Rspec::Rails::ExampleGroup::ControllerExampleGroup

Before, in rspec1, ControllerExampleGroup was a class and you could add code to it. So for instance, we had a file like this in our support folder: [ruby] module RSpec module Rails module Example class ControllerExampleGroup let(:the_account ) { Factory(:account) } let(:the_user ) { Factory(:user)} end end end end [/ruby] A bit larger, but you get the picture: this allowed us to define a set of shared let definitions. In rspec-2 this is no longer possible this way, because ControllerExampleGroup is now a module. I handled that like this: [ruby] module Lets def self.included(base) base.let(:the_account ) { Factory(:account) } base.let(:the_user ) { Factory(:user)} end end [/ruby] and inside my spec_helper this file is automatically required (since it is stored in the support folder) and i just add [ruby] config.include(Lets) [/ruby]

Rspec: replace config.extend

I also noticed that using config.extend(ModuleName) dit not work anymore. Instead i had to write (on the same place, inside the configure block) : [ruby] Rspec.configure do |config| .. include ModuleName .. end [/ruby] and that worked for me.

More?

Do you have more hints to share? What bumps did you find and how did you overcome them?

More ...
Uncategorized view testing rspec2 rails3 rails rspec
rails3 and rspec2 view testing

Testing the view in Rspec is just great. It allows you to test the view in total isolation. It just does the render. Make sure you set up some data that is needed, and then check if all areas are available for instance. Now for Rspec2 a lot of things have changed:

  • have_tag is no longer supported: use have_selector from webrat instead
  • response is deprecated, use rendered instead
  • the assignment has changed, write assign(:events, [stub_model(Event)]) instead of using the old assigns[:events]=[...] notation Let me show you a full example, because that always makes things clearer: [ruby wraplines="false"] require 'spec_helper' DUMMY_NUMBER="dummy number" DUMMY_MESSAGE="dummy message" describe "envelopes/index.html.haml" do before (:each) do envelope = mock_model(Envelope) envelope.should_receive(:destination).and_return(DUMMY_NUMBER) envelope.should_receive(:message).and_return(DUMMY_MESSAGE) assign(:envelopes, [envelope]) render end it ("has a h1") { rendered.should have_selector('h1')} it ("shows the correct title") { rendered.should contain(t('envelopes.list.title')) } it ("have a table-grid") { rendered.should have_selector('.grid') } it ("shows the destination") { rendered.should contain(DUMMY_NUMBER) } it ("shows the message") { rendered.should contain(DUMMY_MESSAGE) } end [/ruby]
More ...
Uncategorized submodules git plugins rails
Using git-submodule to handle plugins

Using git-submodule can make it very easy for you to work with plugins in your rails projects. I will try to show you this, in an easy step-by-step manner. To start, make a plugin-project, call it your_plugin, in its own folder, and push the code to git. Your standard commands apply, as for any project:

  • git status : what is changed?
  • git add . : add the newly added files to your git-repository
  • git commit -am "a meaningful message" : commit your changes in your local repository
  • git push origin master : push your local changes to the remote master (origin/master) How can you add the plugin as a submodule to your rails project? Navigate to the root of your rails project, and execute the following commands: [bash] git submodule add git://your_repository vendor/plugins/your_plugin_name git submodule init git submodule update git status # will show the difference: only the submodule is added git commit -a -m "added plugin your-plugin-name" [/bash] How do you retrieve the lastest version of a submodule/plugin. A submodule in git is coupled to the git-repository at a specific time, so it does not automatically evolve with the remote versions of your pluging. You have to manually make a few operations, to make sure you are using the latest version. In my opinion this is an advantage, as you can keep using a known working version until you really want to upgrade. To update your submodule, go to the root of your plugin/submodule (normally RAILS_ROOT/vendor/plugins/your-plugin-name), and execute the following commands: [bash] git remote update # since your submodule is actually a git repository on its own, you can do this git merge origin/master # retrieve the remote master version cd ...... # back to RAILS_ROOT git status # your submodule is updated to the latest version [/bash] Now to edit and change the plugin/submodule, it is the easiest to work inside the plugin folder itself. To do so, you have to proceed as follows. Inside the root of your plugin (e.g. @\vendor\plugins\your-plugin@) [bash] git checkout -b your_local_branch ... do some changes git commit -a -m "something changed" git checkout master git pull git checkout your_local_branch git rebase master ... solve posslble merge-conflicts ... git checkout master git merge your_local_branch git push [/bash] then cd to RAILS_ROOT [bash] git status # => your plugin will have changed git commit -a -m "improved plugin" [/bash] I used the following sources for inspiration:
  • using git-submodules to track plugins
  • git submodules in n easy steps
  • agile git and the story branch pattern
More ...
Uncategorized rails3 activerecord rails
rewriting find_by_sql for rails 3

I am starting in Rails 3. I have a simple situation where i would select a parent based on a condition of one of its children. Normally i would write something like: [ruby] Distributor.find_by_sql("select d.*, c.rate from distributors d, coverages c where c.country_code_id = 25 and c.distributor_id=d.id order by rate asc") [/ruby] Although this works, it is not the best solution to take. For one, it is vulnerable to sql-injection and secondly it shows a lot of the underlying database structure, and on top of that the sql-implementation could change between databases. In Rails 3 i can now write [ruby] Distributor.includes(:coverages).where("coverages.country_code_id=? and distributors.id =coverages.distributor_id", 25).order(:rate) [/ruby] This is so readable! Awesome :)

More ...
Uncategorized mongrel_service service thin windows rails
mongrel_service alternative: using thin and srvany

So i am developing and deploying Ruby on Rails applications on Windows. Recently i started experimenting with the newer versions of ruby (mingw32platform). One of the side-effects is that the mongrel-service, which i always used to deploy my rails-applications no longer works on mingw32. And aside of that, i have read on various instances [ref] that thin should be better (more efficient) than mongrel. But i still want to install it as a service. First off, you need to download and install the Windows Resource Kit. This contains the executables to make a service of any executable or script. Then create the service running (in the console): [bash] C:\Program Files\Windows Resource Kits\Tools> instsrv "[my_service_name]" "c:\program files\Windows Resource Kits\Tools\srvany.exe" The service was successfuly added! Make sure that you go into the Control Panel and use the Services applet to change the Account Name and Password that this newly installed service will use for its Security Context. [/bash] This will add an empty entry in the registry, which actually still does nothing. To get it working, we have to start regedit, and navigate to the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services[my_service_name] Create a new key (folder) named Parameters. This will contain the settings of our actual application that will be run as a service. Add the following String Values: [bash] [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services[my_service_name]\Parameters] Application=c:\ruby\bin\ruby.exe AppDirectory=[my_ruby_app_folder] AppParameters=c:\ruby\bin\thin start -p 4000 -e production [/bash] Assuming that c:\ruby\bin is your ruby folder, and you want your thin to listen to port 4000. Once that is done, start the service, and your rails application should be up and running :)

... but Windows Server 2008

Unfortunately, to do this on Windows 2008 you need to perform some extra steps. As you can't install the resource kit on Windows Server 2008R2 for some peculiar reason, and at the time of this posting, i have not found a Windows Server 2008 Resource Kit Tools, so i took the following steps:

  1. copy the "srvany.exe " from the "Windows Server 2003 Resource Kit Tools " to a suitable location on your Win2008 server (e.g. C:\Windows\System32\ )
  2. use "sc " to create a new service that launches "srvany " (e.g. sc create MyService binPath= C:\Windows\System32\srvany.exe DisplayName= "My Custom Service" )
  3. using RegEdit create a "Parameters " key for your service as before and fill it with the 3 string values A bit more work, but not too much.

mongrel-service?

And just today I discovered an update of mongrel_service was announced, so you can still work using mongrel_service instead of using thin and manually creating the service. What you need to do:

  • install mongrel service: gem install mongrel_service --prerelease
  • create the service as before: mongrel_rails service::install -N myapp -c c:\my\path\to\myapp -p 4000 -e production That is much easier of course.
More ...
Uncategorized ruby refactoring rails
refactoring ruby code

Most of my ruby/rails development is against a legacy Oracle database. One of the things we needed to fix, was a user-table with not enough fields. Because the user table was shared with another application, we were not able to alter the table. So we added another table, user_params, containing possibly extra parameters for each user. Now it would be nice if each of those possible parameters would behave like a real attribute. So, first implementation: [ruby] class User < ActiveRecord::Base set_primary_key "user_name" set_table_name "stca_user" set_sequence_name "autogenerated" # do not use a sequence at insert! validates_presence_of :user_name validates_presence_of :password # define some virtual attributes for attributes defined in the UserParam table def group_name UserParam.get_param_value(self.user_name, 'UserGroup') end def group_name=(value) UserParam.set_param_value(self.user_name, 'UserGroup', value) end def title UserParam.get_param_value(self.user_name, 'UserTitle') end def title=(value) UserParam.set_param_value(self.user_name, 'UserTitle', value) end def language UserParam.get_param_value(self.user_name, 'UserLanguage') end def language=(value) UserParam.set_param_value(self.user_name, 'UserLanguage', value) end def full_name UserParam.get_param_value(self.user_name, 'UserFullName') end def full_name=(value) UserParam.set_param_value(self.user_name, 'UserFullName', value) end def email UserParam.get_param_value(self.user_name, 'UserEmail') end def email=(value) UserParam.set_param_value(self.user_name, 'UserEmail', value) end # ... snipped away more code end [/ruby] Obviously, this code is not DRY. At lot of repetition, like the stuff i hate about C# or java properties. This could be done better, let's just generate the methods: [ruby] class User < ActiveRecord::Base set_primary_key "user_name" set_table_name "stca_user" set_sequence_name "autogenerated" # do not use a sequence at insert! validates_presence_of :user_name validates_presence_of :password # define some virtual attributes for attributes defined in the UserParam table instance_eval do [['group_name', 'UserGroup'], ['title', 'UserTitle'], ['language','UserLanguage'], ['full_name', 'UserFullName'], ['email', 'UserEmail']].each do |arr| define_method arr[0].to_sym do UserParam.send('get_param_value', self.user_name, arr[1]) end define_method "#{arr[0]}=" do |value| UserParam.send("set_param_value", self.user_name, arr[1], value) end end end end [/ruby] This looks nice. One disadvantage might be that this is not very readable. At first glance it is no longer clear which attributes are available. But with models that is always the case. A few things can still be improved. Every get and set is a query against the database. We might want to improve upon that, and cache results. Also saving the virtual fields is now done when they are being set, but at that time the parent "User" might still not be saved. So this still calls for a better solution. But this does show why i like ruby so much. It makes me feel powerful :)

More ...
Uncategorized oracle_enhanced_adapter oracle rails
rails and avoiding oracle sequences at insert

When using Rails on top of an Oracle database, you use the oracle enhanced activerecord adapter. This adapter (or Rails) has one weird side-effect: there is no way to avoid using a sequence when inserting a new record. But, in this comment, Raimonds Simanovskis hints at the solution. In an initializer you write: [ruby] # a small patch as proposed by the author of OracleEnhancedAdapter: http://blog.rayapps.com/2008/05/13/activerecord-oracle-enhanced-adapter/#comment-240 # if a ActiveRecord model has a sequence with name "autogenerated", the id will not be filled in from any sequence ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do alias_method :orig_next_sequence_value, :next_sequence_value def next_sequence_value(sequence_name) if sequence_name == 'autogenerated' # we assume id must have gotten a good value before insert! id else orig_next_sequence_value(sequence_name) end end end [/ruby] ... and in your model you add: [ruby] set_sequence_name 'autogenerated' [/ruby]

More ...
Uncategorized ruby exceptions actionmailer rails
exception notifier configuration troubles

I installed and configured exception notifier to be notified of any unexpected errors in our production environment. At first i tried this out in development, used gmail as my smtp server and all was working fine. My action mailer configuration looked as follows, in environment.rb: [ruby] # configure mailing config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :enable_starttls_auto => true, :address => "smtp.gmail.com", :port => "587", :domain => "localhost", :authentication => :plain, :user_name => "<snipped>", :password => "<snipped>" } ExceptionNotifier.exception_recipients = %w(bla@my_clients_domain.com) ExceptionNotifier.sender_address = %("<snipped>@gmail.com") ExceptionNotifier.email_prefix = "[My Application ERROR] " [/ruby] Using this configuration worked, and i received the e-mails. Alas, as usual, on my client's production server the port to reach gmail was blocked, and when i asked to open it, they instead proposed to use their own smtp-server. So i changed the configuration as follows: [ruby] config.action_mailer.smtp_settings = { :address => "192.168.0.10", :port => "25", :domain => "production-domain.be", :authentication => nil } ExceptionNotifier.exception_recipients = %w(bla@my_clients_domain.com) ExceptionNotifier.sender_address = %("info@production-domain.com") ExceptionNotifier.email_prefix = "[My Application ERROR] " [/ruby] The first thing i did wrong was the domain-name. At first i wrote "@production-domain.be" in my action-mailer configuration, so my HELO request was blocked. Secondly, apparently, because i wrote ExceptionNotifier.sender_address = %("info@production-domain.com") the sender address was not recognised and the mail was rejected by our own SMTP-server. This took me a while to figure out. Luckily our sys-admin noticed the difference. The fix: [ruby] ExceptionNotifier.sender_address = %(info@production-domain.com) [/ruby] And now i know for sure that if i get no mails, my application really is working :)

More ...