Search code examples
ruby-on-rails-3lazy-loadingbefore-filter

Rails 3.1 - before filter and database error


I'm having some trouble with lazy loading, i'm pretty sure of it ... maybe you could point out to me where I've failed.

def setup_guild
 if params[:guild]
  @guild = Guild.where(:short_name => params[:guild].upcase).first
  if @guild.nil?
    puts "no guild with short name #{params[:guild]} found"
    redirect_to root_path 
  else
    @title = t "layout.guild_title", :guild_name =>  (@guild.name).capitalize
  end
 else
  @guild = nil
 end
end

Which is called in ApplicationController as a before filter. At first I used Guild.find_with_short_name, but I had the same dumb answer as now ... that is :

undefined method `capitalize' for nil:NilClass
app/controllers/application_controller.rb:29:in `setup_guild'

Which is, you'd guess the @title line up there.

The thing is, if I try something similar in the console I get the expected result

ruby-1.9.2-p0 > guild = Guild.where(:short_name => "ICPT").first
  Guild Load (0.5ms)  SELECT "guilds".* FROM "guilds" WHERE "guilds"."short_name" = 'ICPT' LIMIT 1
 => #<Guild id: 2, name: "Inception", detail: "Inception Guild", game_server_id: 2, created_at: "2011-10-30 17:41:19", updated_at: "2011-10-30 17:41:19", short_name: "ICPT"> 
ruby-1.9.2-p0 > guild.name.capitalize
 => "Inception" 

More, if I put something like "puts @guild.inspect" right after the fetch, the capitalization works fine, hence I think it's lazy loading failure.

I'd be happy to have some idea as to how to solve that dumb problem ... I don't really want to have an @guild.inspect for nothing in my code, i find that to be lame solution ...

Thanks !

@PanayotisMatsinopoulos As requested, here is the table Guild :

create_table "guilds", :force => true do |t|
    t.string   "name"
    t.text     "detail"
    t.integer  "game_server_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "short_name"
  end

@PanayotisMatsinopoulos Here you go my friend ;) I still have to i18n it

#encoding: utf-8
class Guild < ActiveRecord::Base
  belongs_to :game_server
  has_one :game, :through => :game_server
  has_many :announcement, :dependent => :destroy
  validates_presence_of :name, :on => :create, :message => "dois avoir un nom"
  validates_presence_of :detail, :on => :create, :message => "dois avoir une description"
  validates_presence_of :game, :on => :create, :message => "dois appartenir a un jeu"
  validates_presence_of :short_name, :on => :create, :message => "dois avoir un acronyme"
  validates_uniqueness_of :short_name, :on => :create, :message => "est deja utilise"
  validates_length_of :short_name, :within => 3..5, :on => :create, :message => "dois faire entre 3 et 5 caracteres"
  validates_exclusion_of :short_name, :in => %w( users admin guilds events loots sessions characters games password), :on => :create, :message => "ne peux pas utilisé se genre d'acronyme"
  validates_uniqueness_of :name, :on => :create, :message => "est deja utilise"

  has_many :guild_mates, :dependent => :destroy
  has_many :guild_ranks, :dependent => :destroy
  has_many :guild_settings, :dependent => :destroy
  has_many :events, :dependent => :destroy
  has_many :characters, :dependent => :destroy

  before_validation :short_name_check ,:on => :create

  after_create :guild_basic_settings

  def guild_basic_settings
    GuildSettingType.all.each do |grst|
      grs = GuildSetting.create do |g|
        g.guild_id = self.id
        g.guild_setting_type_id = grst.id
        g.value = "false"
      end    
    end
    set_setting(["setting_allow_basic_access_for_public","setting_allow_application",
      "setting_allow_event_read_for_public","setting_allow_announcement_read_for_public"],"true")
  end

  def set_setting(setting,value)

    if setting.class == Array
      setting.uniq!
      setting.each do |ar|
        set_setting(ar,value)
      end
    else
      grs = nil
      if setting.class == String
        grs = guild_settings.includes(:guild_setting_type).where(:guild_setting_type => {:name => setting}).first
        return if grs.nil?
      else
        grs = guild_rank_settings.where(:guild_setting_type => setting)
        return if grs.nil?
      end

      grs.value = value
      grs.save
    end
  end

  def short_name_check
    short_name.upcase! if short_name
  end

  def full_name
    "#{name.capitalize} - #{game_server.name}"
  end

  def characters_for_user(user)
    characters.where(:user_id => user.id)
  end

  def method_missing(method,*args)
    check = method.to_s.split("_")
    if(args.count == 0)
      if check[0] == "setting"
         grs = guild_settings.joins(:guild_setting_type).where(:guild_setting => { :guild_setting_types => {:name => method.to_s}}).first
          unless grs.nil?
            return grs.value == "true" ? true : false
          else
            raise "Guild > Method Missing > unknown setting : #{method.to_s}"
          end
      end
    end
  end

end

Edit : I've just seen that i didn't super method missing ... might that be the problem ?


Solution

  • Okay it seems that the problem was my method_missing implementation. It was lacking super call ... Now that it has been restored, everything works fine. no wonder.

    Thanks @PanayotisMatsinopoulos for your help :) (also thanks a good night of sleep ;p )