Rails — Сохранение клиентской модели в базе данных

#html #ruby-on-rails #ruby

Вопрос:

Эй, здесь! Я вроде как новичок в Rails, и я пытался найти некоторые ответы, но пока безуспешно, так что поехали.

Я создал базовое приложение Rails и просто пытаюсь сохранить клиента в своей базе данных с помощью проверки, но, похоже, ничего не получается. Любой может указать мне правильное направление, пожалуйста, или сообщить мне, что я делал неправильно в своем коде.

Я продолжаю получать подобные ошибки:

 NoMethodError in Clients#new
Showing /Users/******/Documents/******/*****/app/views/clients/_form.html.erb where line #1 raised:

undefined method `clients_path' for #<ActionView::Base:0x00000000064a50>
Did you mean?  clients_new_path
 

Даже если я удалюсь @client = Client.new из new метода, я смогу просмотреть страницу, но ничего не будет сохранено.

Я действительно застрял сейчас, так что любая помощь очень признательна! Спасибо!

Мой файл Routes.rb:

 Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
  get 'dashboard/index'
  root to: "home#index"

  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations'
  }

  get '/clients/index'
  get '/clients/new'
  get '/clients/edit'
  get '/clients/delete'

  get '/clients/:id', to: 'clients#show'

  post '/clients/new', to: 'clients#create'
end
 

Мой файл панели мониторинга:

 <% if user_signed_in? %>
    <nav class="subnav">
        <ul>
            <li><%= link_to('My Clients', clients_index_path) %></li>
            <li><%= link_to('Add Client', clients_new_path) %></li>
            <li><%= link_to('Edit registration', edit_user_registration_path) %></li>
            <li><%= link_to('Logout', destroy_user_session_path, :method => :delete) %></li>
        </ul>
    </nav>
<% else %>

  <%= link_to('Register', new_user_registration_path)  %>
  <%= link_to('Login', new_user_session_path)  %>

<% end %>
 

Мой файл ClientsController:

 class ClientsController < ApplicationController
  def index
    @clients = Client.all
  end

  def new
    @client = Client.new
  end

  def show
    @client = Client.find(params[:id])
  end

  def create
    @client = Client.new(client_params)

    if @client.save
      redirect_to @client
    else
      render :new
    end
  end

  def edit
  end

  def delete
  end

  private
    def client_params
      params.require(:client).permit(:name, :provider)
    end
end
 

Моя форма:

 <%= form_with model: @client do |form| %>
  <div>
    <%= form.label :name %><br>
    <%= form.text_field :name %>
    <% client.errors.full_messages_for(:name).each do |message| %>
      <div><%= message %></div>
    <% end %>
  </div>

  <div>
    <%= form.label :provider %><br>
    <%= form.text_field :provider %>
  </div>

  <div>
    <%= form.label :business_type %><br>
    <%= form.select :business_type, ["Partnership", "Sole Trader", "Limited Company"] %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>
 

Наконец-то мой новый файл.html.erb:

 <h1>Clients#new</h1>

<%= render 'form', client: @client %>
 

Ответ №1:

clients_path генерируется resources :clients, only: :index или вам, вероятно, нужно дать вашему маршруту нужное имя. Попробуйте это

 get '/clients/index', as: :clients
 

или, если вы хотите указать пути, отличные от путей по умолчанию , как вы делаете , ваш индекс, вероятно, называется clients_index_path , но вы можете проверить это с rake routes помощью или rails routes , потому что я не уверен.

Тем не менее, я предлагаю вам использовать resources метод в файле маршрутов и использовать пути по умолчанию, как вы пытаетесь это сделать. Что-то вроде

 resources :clients
 

но теперь у вас больше нет такого пути, как /clients/index нет, только /clients для действия с индексом.

Если вы сомневаетесь в маршрутах, попробуйте прочитать руководство по маршрутизации

Комментарии:

1. Спасибо за ваш ответ! Действительно ценю это!

Ответ №2:

Способ Rails объявить маршруты для создания, обновления, чтения и уничтожения (CRUD) ресурса-это просто:

 Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
  get 'dashboard/index'
  root to: "home#index"

  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations'
  }

  resources :clients
end
 

Как вы можете видеть по описаниям выше, каждый метод Rails не добавляет «действие» в путь, за исключением new edit маршрутов и:

 class ClientsController < ApplicationController
  before_action :set_client, only: [:show, :edit, :update, :destroy]

  # GET /clients
  def index
    @clients = Client.all
  end

  # GET /clients/1
  def show
  end
  
  # GET /clients/new
  def new
    @client = Client.new
  end

  # POST /clients
  def create
    @client = Client.new(client_params)

    if @client.save
      redirect_to @client
    else
      render :new
    end
  end

  # GET /clients/edit
  def edit
  end

  # PATCH /clients/1
  def update
    if @client.update(client_params)
      redirect_to @client
    else
      render :edit
    end
  end

  # DELETE /clients/1
  def delete
    @client.destroy
    redirect_to action: :index, 
                notice: 'Client deleted'
  end

  private
    def set_client
      @client = Client.find(params[:id])
    end

    def client_params
      params.require(:client).permit(:name, :provider)
    end
end
 

Таким образом, вы не создаете ресурсы с post '/clients/new' помощью — Вы используете POST /clients . Кроме того, при использовании «простых» методов маршрутизации , таких как match get , post и т.д. Rails автоматически не добавляет помощника по маршрутизации. Если бы вы действительно хотели создать эквивалентные маршруты, вам нужно было бы использовать:

 post '/clients', 
  to: 'clients#create',
  as: :clients
 

Но вам гораздо лучше принять условности и научиться использовать их, чтобы быть продуктивным.

Комментарии:

1. Спасибо за объяснение 🙂 Очень признателен!