неопределенный метод 'имя_модели' для nil: NilClass - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь получить адрес пользователя и сохранить его в базе данных, но я получаю undefined method 'model_name' for nil:NilClass. На этой же странице может обновляться имя, которое получается при регистрации. Я хочу, чтобы имя сохранялось в таблице пользователей, а адрес сохранялся в таблице адресов в базе данных при нажатии кнопки сохранения изменений. Я не знаю, где я иду не так. Пожалуйста, помогите решить эту проблему!

Посмотреть код

<%= form_for(@user, url: { action: 'update_profile' }, html: { class: 'm-form m-form--fit m-form--label-align-right' } ) do |f| %>
  <% if @user.errors.any? %>
    <h4><%= pluralize(@user.errors.count, "error") %>
      prohibited this profile from being saved:</h4>
    <ul>
      <% @user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  <% end %>
  <div class="form-group m-form__group row">
    <label for="name" class="col-2 col-form-label">
      Name
    </label>
    <div class="col-7">
      <%= f.text_field :name, class: 'form-control m-input', placeholder: 'Full Name' %>
    </div>
  </div>
  <div class="m-form__seperator m-form__seperator--dashed m-form__seperator--space-2x"></div>
  <%= f.fields_for @user.address do |a| %>

  <div class="form-group m-form__group row">
    <label for="example-text-input" class="col-2 col-form-label">
      Address
    </label>
    <div class="col-7">
      <%= a.text_field :area, class: 'form-control m-input', placeholder: 'Address' %>
    </div>
  </div>
  <div class="form-group m-form__group row">
    <label for="example-text-input" class="col-2 col-form-label">
      City
    </label>
    <div class="col-7">
      <%= a.text_field :city, class: 'form-control m-input', placeholder: 'City' %>
    </div>
  </div>
  <div class="form-group m-form__group row">
    <label for="example-text-input" class="col-2 col-form-label">
      State
    </label>
    <div class="col-7">
      <%= a.text_field :state, class: 'form-control m-input', placeholder: 'State' %>
    </div>
  </div>
<% end %>
<%= f.submit 'Save Changes', class: 'btn btn-accent m-btn m-btn--air m-btn--custom' %>
&nbsp;&nbsp;
<%= link_to 'Back', root_path, class: 'btn btn-secondary m-btn m-btn--air m-btn--custom' %>

Код контроллера

class ProfileController < ApplicationController
  before_action :set_user, only: %i[index update_profile]

  def index; end

  def update_profile
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to profile_index_path, notice: 'Profile was successfully updated.' }
      else
        format.html { render :index }
      end
    end
  end

private

  def set_user
    @user = User.find(current_user.id)
  end

  def user_params
    params.require(:user).permit(:name)
  end

  def address_params
    params.require(:user).permit(address: %i[area state country])
  end
end

Код модели

Address.rb

class Address < ApplicationRecord
  belongs_to :user
end

User.rb

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_one :address, dependent: :destroy

  validates :name, presence: true
  def admin?
    false
  end
end

Терминал журнала

Started GET "/profile" for 127.0.0.1 at 2018-05-02 14:31:21 +0530
Processing by ProfileController#index as HTML
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 11 ORDER BY `users`.`id` ASC LIMIT 1
  User Load (0.2ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 11 LIMIT 1
  Rendering profile/index.html.erb within layouts/application
  Rendered profile/_profile_card.html.erb (0.2ms)
  Address Load (0.2ms)  SELECT  `addresses`.* FROM `addresses` WHERE `addresses`.`user_id` = 11 LIMIT 1
  Rendered profile/_profile_detail.html.erb (3.4ms)
  Rendered profile/index.html.erb within layouts/application (4.7ms)
Completed 401 Unauthorized in 8ms (ActiveRecord: 0.7ms)


[Rollbar] Reporting exception: undefined method `model_name' for nil:NilClass
[Rollbar] Scheduling item
[Rollbar] Sending item
[Rollbar] Success
[Rollbar] Details: https://rollbar.com/instance/uuid?uuid=60dbe4e1-e5ef-4414-a9a5-e8a866c47740 (only available if report was successful)
[Rollbar] Exception uuid saved in env: 60dbe4e1-e5ef-4414-a9a5-e8a866c47740

NoMethodError - undefined method `model_name' for nil:NilClass:
  app/views/profile/_profile_detail.html.erb:45:in `block in _app_views_profile__profile_detail_html_erb___3163788399910446599_70315531332300'
  app/views/profile/_profile_detail.html.erb:26:in `_app_views_profile__profile_detail_html_erb___3163788399910446599_70315531332300'
  app/views/profile/index.html.erb:7:in `_app_views_profile_index_html_erb__1161982046354726382_70315531116820'

Started POST "/__better_errors/0227f950024c358e/variables" for 127.0.0.1 at 2018-05-02 14:31:22 +0530

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

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

class UsersController < ApplicationController
  def set_user
    @user = User.find(current_user.id)
    @user.address || @user.build_address
  end
end

или в представлении выше:

  <% @user.address || @user.build_address %>
  <%= f.fields_for :address do |a| %>
0 голосов
/ 02 мая 2018

Имя вашего контроллера должно совпадать с именем вашей модели во множественном числе:

# model user.rb
class User < ApplicationRecord
end

# controller users_controller.rb
class UsersController < ApplicationController
end

Edit:
Вы можете добавить вложенную ассоциацию в свою модель пользователя

class User < ApplicationRecord
  has_one :address, dependent: :destroy
  accepts_nested_attributes_for :address
end

затем измените свой fields_for как:

<%= f.fields_for :address, @user.address do |a| %>

и переименуйте ваш контроллер и параметры вашего разрешения:

#controller name: users_controller.rb
class UsersController < ApplicationController
  before_action :set_user, only: %i[index update_profile]

  def index; end

  def update_profile
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to profile_index_path, notice: 'Profile was successfully updated.' }
      else
        format.html { render :index }
      end
    end
  end

private

  def set_user
    @user = User.find(current_user.id)
    @user.address.build
  end

  def user_params
    params.require(:user).permit(:name, address_attributes: %i[area state country])
  end
end

примечание: не забудьте проверить свои маршруты

...