#ruby-on-rails-3 #lazy-loading #before-filter
#ruby-on-rails-3 #отложенная загрузка #перед фильтром
Вопрос:
У меня возникли некоторые проблемы с отложенной загрузкой, я в этом уверен… может быть, вы могли бы указать мне, где я потерпел неудачу.
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
Который вызывается в ApplicationController как фильтр перед.
Сначала я использовал Guild.find_with_short_name , но у меня был такой же тупой ответ, как и сейчас… это :
undefined method `capitalize' for nil:NilClass
app/controllers/application_controller.rb:29:in `setup_guild'
То есть, вы бы догадались, что там есть строка @title.
Дело в том, что если я попробую что-то подобное в консоли, я получу ожидаемый результат
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"
Более того, если я добавлю что-то вроде «puts @guild.inspect» сразу после выборки, заглавные буквы работают нормально, поэтому я думаю, что это сбой отложенной загрузки.
Я был бы рад получить представление о том, как решить эту глупую проблему… Я действительно не хочу, чтобы в моем коде не было @guild.inspect, я считаю, что это неубедительное решение…
Спасибо!
@PanayotisMatsinopoulos В соответствии с просьбой, вот таблица гильдии :
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 Вот и ты, мой друг 😉 Я все еще должен i18n это
#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
Редактировать: я только что увидел, что я не пропустил супер-метод… может ли это быть проблемой?
Комментарии:
1. Почему у вас есть
:guild_name => (@guild.name).capitalize
, а нет:guild_name => @guild.name.capitalize
? (Возможно, это не проблема, но я просто спрашиваю)2. Ну, это было так, как вы спрашивали раньше, я просто пробовал альтернативы … ^^
3. Я могу только догадываться, что ваш запрос возвращает запись с
name
нулевым значением. Я не могу найти другого очевидного объяснения. Поставьтеinspect
перед, чтобы узнать, верно это или нет.4. >> Более того, если я добавлю что-то вроде «puts @guild.inspect» сразу после выборки, заглавные буквы работают нормально, поэтому я думаю, что это сбой отложенной загрузки.
5. Можете ли вы опубликовать свою
Guild
модель?
Ответ №1:
Хорошо, похоже, проблема заключалась в моей реализации method_missing. В нем отсутствовал суперзвонок… Теперь, когда он был восстановлен, все работает нормально. неудивительно.
Спасибо @PanayotisMatsinopoulos за вашу помощь 🙂 (также спасибо за хороший ночной сон ; p)
Ответ №2:
вы также должны проверить, равно ли name nil:
if @guild.nil? || @guild.name.nil?
Комментарии:
1. Думаю, я мог бы … тем не менее, я нахожу это маловероятным (я проверяю наличие имени при создании… тем не менее, это может помочь …)
2. Пытался, он обнаружил проблему, но не решил ее для записей, поле имени которых заполнено, но не загружено
Ответ №3:
Верно. method_missing
должен быть вызван super
в конце. Но я не уверен, что ваша проблема существует. Это может быть. Возможно, это не так.
С другой стороны, позвольте мне рассказать кое-что, что, по моему мнению, имеет больше шансов стать вашей проблемой. Это тот факт, что вы выполняете свою проверку presence
name
только :on => :create
для of . Это означает, что обновление объекта Guild
, который не содержит name
, пройдет проверку и будет сохранен в базе данных без проблем. Тогда вы setup_guild
обязательно выдадите ошибку:
undefined method `capitalize' for nil:NilClass
app/controllers/application_controller.rb:29:in `setup_guild'
т. е. Ошибка, с которой началось это обсуждение.
Следовательно, мое предложение состоит в том, чтобы удалить ваше :on => :create
условие при проверке name
. (кстати … я предлагаю вам удалить его из всех ваших проверок, если вы не знаете, что делаете)
Но тогда я не могу доказать, что это была ваша проблема в первую очередь. Я просто привожу здесь свой совет, а не мой положительный ответ в качестве решения вашей проблемы.
Комментарии:
1. Привет @PanayotisMatsinopoulos, проблема заключалась в method_missing. Что касается проблемы проверки, которую вы выделяете, на самом деле эти атрибуты не предназначены для обновления, поэтому это не должно быть проблемой. Но, как можно было бы сказать, случается всякое 😉 поэтому я последую вашему совету и на всякий случай удалю инструкцию :on . В любом случае спасибо за вашу помощь!
2. @Kluthen57 Хорошо, спасибо за отзыв. Если вы все еще считаете, что мой ответ был полезным, я был бы признателен за голосование, даже если он не выбран в качестве ответа на ваш вопрос. Голосование означает «Этот ответ полезен». В любом случае спасибо.
3. не могу проголосовать за вас, извините, у меня недостаточно репутации для этого: x