Почему мое приложение rails не работает, когда я нажимаю на Heroku: «ActionView :: Template :: Error (неопределенный метод« Toilet_available »для nil: NilClass)»? - PullRequest
0 голосов
/ 13 сентября 2018

Я создаю приложение для поиска магазинов в Rails 5, которое использует Open Street Map API и самоцвет для листовок. В среде разработки все работает как положено, но когда я нажимаю на Heroku, я получаю сообщение «Извините, но что-то пошло не так». сообщение. Я создал функцию, в которой вы можете сортировать магазины по наличию туалета или без него, и эти швы должны быть там, где проблема. Журналы Heroku показывают следующее:

2018-09-12T22:02:39.751563+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123] Completed 500 Internal Server Error in 624ms (ActiveRecord: 119.5ms)
2018-09-12T22:02:39.706503+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]   Toilet Load (29.5ms)  SELECT "toilets".* FROM "toilets"
2018-09-12T22:02:39.772904+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]
2018-09-12T22:02:39.773276+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     29:                                             <li><%= link_to "Log In", new_user_session_path %> </li>
2018-09-12T22:02:39.772915+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123] ActionView::Template::Error (undefined method `toilet_available' for nil:NilClass):
2018-09-12T22:02:39.773280+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     30:                                             <li><%= link_to "Add Spaeti", new_user_registration_path %> </li>
2018-09-12T22:02:39.773283+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     31:                                     <% end %>
2018-09-12T22:02:39.773285+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     32:                                     <li><%= link_to "Spaetis with toilets", stores_path(toilet: Toilet.all[0].toilet_available) %></li>
2018-09-12T22:02:39.773288+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     33:                             </ul>
2018-09-12T22:02:39.773290+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     34:                     </div>
2018-09-12T22:02:39.773292+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]     35:             </nav>
2018-09-12T22:02:39.773336+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123]
2018-09-12T22:02:39.773423+00:00 app[web.1]: [30a84d17-6a5a-4b3d-b21f-ee08babfd123] app/views/layouts/application.html.erb:32:in `_app_views_layouts_application_html_erb__2166090761148733231_41993540'

Когда я удаляю эту строку из представления, приложение загружается нормально: <li><%= link_to "Spaetis with toilets", stores_path(toilet: Toilet.all[0].toilet_available) %></li>

Что может быть причиной этой ошибки? Я рвал свои волосы уже несколько дней ...

Модель магазина:

class Store < ApplicationRecord
    belongs_to :user
    belongs_to :toilet

    validates :name, presence: true
    validates :address, presence: true
    validates :address_line2, presence: true
    validates :address_line3, presence: true
    validates :toilet, presence: true
    # validates :latitude, presence: true
    # validates :longitude, presence: true
    validates :beer_cost, format: { with: /\A\d+(?:\.\d{0,2})?\z/ }, numericality: { greater_than: 0, less_than: 10 }
    validates :latitude, :presence => {message: "Not a valid location, please check name address & country fields" }

    def full_address
      [address, address_line2, address_line3].compact.join(', ')
    end
    geocoded_by :full_address
    before_validation :geocode,
      :if => lambda{ |obj| obj.address_changed? }

    def capitalize_name
        name.capitalize
    end

    def capitalize_address
        address.capitalize
    end
end

Модель туалета:

class Toilet < ApplicationRecord
    has_many :stores
end

schema.rb:

ActiveRecord::Schema.define(version: 20180814220216) do

  create_table "stores", force: :cascade do |t|
    t.string "name"
    t.string "address"
    t.float "beer_cost"
    t.text "facilities"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.float "latitude"
    t.float "longitude"
    t.boolean "toilet"
    t.string "address_line2"
    t.integer "user_id"
    t.integer "toilet_id"
    t.string "address_line3"
  end

  create_table "toilets", force: :cascade do |t|
    t.string "toilet_available"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

end

Github репо: https://github.com/catsinspacesuits/Spaeti-App

1 Ответ

0 голосов
/ 13 сентября 2018

Извините, я неправильно истолковал то, что вы пытались сделать.Я думаю, что даже если вы больше не получаете ошибку, вы все еще не получаете ответ, который вы намереваетесь получить.Вы используете очень нестандартный способ иметь логический столбец.На консоли rails сделайте это:

t = Toilet.first
t.toilet_available

и посмотрите на возвращаемое значение.Независимо от «да» или «нет» вы получаете значение.Так что, если это:

Toilet.all[0].toilet_available

должно означать: «получить все туалеты и взять первый, где доступно = да», это НЕ то, что происходит.Столбец БД, определенный как тип String с "да" или "нет", не является логическим значением и не будет действовать как один без определения метода для его интерпретации следующим образом:

def has_toilet
  self.toilet_available == "yes" ? true : false
end

Я думаюс помощью Toilet.all[0].toilet_available вы получаете «Получите все туалеты, возьмите первый результат и верните текст в столбце Toilet_available, независимо от того, является ли этот текст true или false».Но если вы намереваетесь «принести мне первый туалет, доступность которого true», тогда ваш код неверен.

Вот простой тест для использования в вашей БД разработки, где у вас много записей.В консоли Rails сделайте следующее:

puts Toilet.all[0]
puts Toilet.all.first
puts Toilet.where(toilet_available: 'yes').limit(1)
puts Toilet.find_by(toilet_available: 'yes')

Они могут не все возвращать один и тот же результат.Шаблон .all[0] - ИМХО плохой способ получить что-то из БД, поскольку это очень неоднозначно.

Также сделайте это в консоли:

Toilet.all.each do |t|
  puts "toilet_available is #{t.toilet_available} and is #{t.toilet_available ? true : false}
end

Вы должны увидеть что-то вроде:

toilet_available is yes and is true
toilet_available is no and is true

Дело в том, что в Rails есть текстовое значение в текстестолбец приводит к тому, что это "правда".Единственный способ получить значение false - это значение nil.Если toilet_available когда-либо будет иметь только два состояния, тогда логический тип столбца будет более подходящим и того, что другие разработчики будут ожидать.Если значением может быть три состояния, такие как «да», «нет», «неизвестно», то вы можете использовать столбец с конечным автоматом.

...