【问题标题】:undefined method `name' for nil:NilClass for custom slugnil 的未定义方法“名称”:自定义 slug 的 NilClass
【发布时间】:2016-01-31 13:30:05
【问题描述】:

我有一个Restaurant 模型,它使用地理编码器在before_validation 回调中收集城市、州和社区。​​p>

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 模型中,我组装了一个自定义 slug,它使用城市名称和它所属的州名称。

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

可以理解,因为没有一个城市或州尚未持久化到数据库中。我想知道如何配置我的回调以使其正常工作?

【问题讨论】:

  • 你试过了吗? "#{name} #{city.try(:name)}" ?当citynil 时,它将确保它不会失败
  • 是的,但问题是我需要城市名称。做你描述的会给我/houston而不是/houston-texas。我需要两者中的后者。
  • 你需要的是州名,而不是城市名

标签: ruby-on-rails associations geocoding slug friendly-id


【解决方案1】:

我能想到的唯一方法是使用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

这方面的文档不多;这基本上意味着您可以在各自的模型中调用相关数据,即city.state(即使state没有保存)。

因此,如果您在每次添加城市时都设置一个(并且它们是关联的),那么您应该可以调用以下(@ 987654322@):

#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

【讨论】:

  • 看来inverse_of 没有成功。仍然出现同样的错误。
【解决方案2】:

在您的城市模型中编写此方法。当您的状态 ID 更改时,这将生成 slug。

def should_generate_new_friendly_id?
    new_record? || state_id_changed?
end

并对下面的方法做这个小改动。

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

【讨论】:

  • 这个会在你创建的时候友好处理,签出第一个条件new_record?。这将使这种情况发生。您在遵循我的解决方案时遇到任何问题吗?让我知道我可以分享。这件事可以通过多种方式完成。
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多