2015-10-31 2 views
0

У меня есть модель Restaurant, в которой используется геокодер, чтобы собирать город, штат и окрестности по обратному сообщению before_validation.undefined method `name 'для nil: NilClass для пользовательского slug

class Restaurant < ActiveRecord::Base 
    # attrs: :name, :address, :city_id, :neighborhood_id 

    ... 

    before_validation :geocode 

    geocoded_by :address do |obj,results| 
    if geo = results.first 
     obj.city = City.where(name: geo.city).first_or_create 
     obj.city.update_attributes(state: State.where(name: geo.state).first_or_create) 

     obj.neighborhood = Neighborhood.where(name: geo.neighborhood).first_or_create 
     obj.neighborhood.update_attributes(city: City.where(name: geo.city).first_or_create) 

     obj.longitude = geo.longitude 
     obj.latitude = geo.latitude 
    end 
    end 
end 

В моей City модели я соединил пользовательский слизняк, который использует название города и название государства, что оно принадлежит.

class City < ActiveRecord::Base 
    # attrs :name, state_id 

    belongs_to :state 

    friendly_id :state_slug, use: :slugged 

    def state_slug 
    "#{name} #{state.name}" 
    end 
end 

Всякий раз, когда я создать новый ресторан я ошибка:

undefined method `name' for nil:NilClass 

def state_slug 
    "#{name} #{state.name}" 
end 

Вполне понятно, потому что это не город или государство, которое до сих пор не сохраняется в базе данных. Мне интересно, как мне настроить мой обратный вызов, чтобы заставить это работать?

+0

ли Вы пытаетесь? '" # {name} # {city.try (: name)} "'? Он будет уверен, что это не сработает, если 'city'' nil' –

+0

Да, но проблема в том, что мне нужно имя города. Выполнение того, что вы описали, даст мне '/ houston' вместо'/houston-texas'. Мне нужен последний из двух. –

+0

Вам нужно имя штата, а не город –

ответ

0

Напишите этот метод в своей городской модели. Это приведет к сбою при изменении вашего идентификатора состояния.

def should_generate_new_friendly_id? 
    new_record? || state_id_changed? 
end 

И сделайте это небольшое изменение следующим методом.

def state_slug 
    "#{name} #{state.name}" if state.present? 
    end 
+0

Мне нужно это на 'create'. Не 'update'. –

+0

Это будет позаботиться о дружелюбности, когда вы создадите, выберете первое условие new_record ?. Это сделает это. Вы столкнулись с какой-либо проблемой во время моего решения? Дайте мне знать, что я могу поделиться. Это можно сделать разными способами. – Rubyrider

0

Единственный способ, которым я могу думать о том, чтобы использовать inverse_of:

#app/models/state.rb 
class State < ActiveRecord::Base 
    has_many :cities, inverse_of: :state 
end 

#app/models/city.rb 
class City < ActiveRecord::Base 
    belongs_to :state, inverse_of: :cities 
end 

Существует не так много документации по этому поводу; это в основном означает, что вы можете вызвать связанные данные в своих соответствующих моделях, IE city.state (даже если state не сохраняется).

Таким образом, если вы устанавливаете в состояние каждый раз, когда вы добавляете город (и они ассоциированы), вы должны быть в состоянии назвать следующие (validation):

#app/models/city.rb 
class City < ActiveRecord::Base 
    belongs_to :state, inverse_of: :cities 
    validates :state, presence: true 

    friendly_id :state_slug, use: :slugged 

    private 

    def state_slug 
    "#{name} #{state.name}" 
    end 
end 
+0

Кажется, 'inverse_of' не сделал трюка. По-прежнему остается та же ошибка. –

Смежные вопросы