Restful a has_many

Witam serdecznie!
Mój problem polega na tym, że nie działa mi akcja show, w relacji has_many
No route matches {:action=>“show”, :controller=>“produkts”, :firma_id=>“3”} missing required keys: [:id]

  • Modele:
class Firma < ActiveRecord::Base
   has_many :produkts
end
class Produkt < ActiveRecord::Base
  belongs_to :firma
end
  • Kontroler produkts

class ProduktsController < ApplicationController

  layout 'admin'
  before_action :set_produkt, only: [:show, :edit, :update, :destroy]
  before_action :set_firma
  before_action :waluta, only: [:new, :edit, :update]
  def index
    @produkt = @firmas.produkts.najnowszy
  end
  def show
  end
  def new
    @produkt = Produkt.new({:firma_id => @firmas.id, :nazwa => "Podaj nazwę produktu"})
    @firma = Firma.order('created_at ASC')
  end
  def edit
  end
  def create
    @produkt = Produkt.new(produkt_params)
    respond_to do |format|
      if @produkt.save
        format.html { redirect_to @produkt, notice: 'Produkt was successfully created.' }
        format.json { render :show, status: :created, location: @produkt }
      else
        @firma = Firma.order('created_at ASC')
        format.html { render :new }
        format.json { render json: @produkt.errors, status: :unprocessable_entity }
      end
    end
  end
  def update
    respond_to do |format|
      if @produkt.update(produkt_params)
        format.html { redirect_to @produkt, notice: 'Produkt was successfully updated.' }
        format.json { render :show, status: :ok, location: @produkt }
      else
        format.html { render :edit }
        format.json { render json: @produkt.errors, status: :unprocessable_entity }
      end
    end
  end
  def destroy
    @produkt.destroy
    respond_to do |format|
      format.html { redirect_to produkts_url, notice: 'Produkt was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
private
def waluta
  @waluta = %w[PLN EUR USD CHF RUB]
end
def set_firma
  if params[:firma_id]
    @firmas = Firma.find(params[:firma_id])
  end
end
def set_produkt
  @produkt = Produkt.find(params[:id])
end
def produkt_params
  params.require(:produkt).permit(:firma_id, :category_id, :subcategory_id, :nazwa, :opis, :widoczny, :zdjecie1, :zdjecie2, :zdjecie3, :cena, :waluta, :link)
end
  • Widok index produkts, gdzie w wywołaniu akcji show występuje błąd:

<%= notice %>

<h1>Produkts</h1>
<table>
  <thead>
    <tr>
      <th>Firma</th>
      <th>Nazwa</th>
      <th>Opis</th>
      <th>Widoczny</th>
      <th>Zdjecie1</th>
      <th>Cena</th>
      <th>Waluta</th>
      <th>Link</th>
      <th colspan="3"></th>
    </tr>
  </thead>
  <tbody>
    <% @produkt.each do |produkty| %>
      <tr>
        <td><%= produkty.id %></td>
        <td><%= produkty.firma_id %></td>
        <td><%= produkty.nazwa %></td>  
        <td><%= produkty.opis %></td>
        <td><%= produkty.widoczny %></td>
        <td><%= produkty.zdjecie1 %></td>
        <td><%= produkty.cena %></td>
        <td><%= produkty.waluta %></td>
        <td><%= produkty.link %></td>
        <td><%= link_to 'show', firma_produkt_path %></td>
      </tr>
    <% end %>
  </tbody>
</table>
<br>
<%= link_to 'New Produkt', new_firma_produkt_path %>

No route matches {:action=>“show”, :controller=>“produkts”, :firma_id=>“3”} missing required keys: [:id]

Mniej więcej rozumiem o co chodzi w restful, ale tu pogubiłem się, nie wiem dlaczego nie pobiera :id produktu skoro w samym index’ie ten id istnieje,

  • trasy chyba są ok:
Rails.application.routes.draw do
  root "firmas#index"
  resources :firmas do
     resources :produkts
  end
end

Za wszelką pomoc z góry dziękuję

Opakuj kod w backticki ( ` ) a podem zadaj pytanie jeszcze raz, bo nie da się tego czytać.

chyba lepiej teraz wygląda, dzięki za uwagę

  1. Nie używaj polskich nazw
  2. powinno być <%= link_to ‘show’, firma_produkt_path(produkty) %>

Masz rację z tymi nazwami to zaszłość w projekcie, ale już robiłem tak jak piszesz i też nie działa, tylko teraz wysypuje się jeszcze bardziej,

jest możliwe, że to przez nazewnictwo polskie nie działa?

Jest to możliwe, a co oznacza wysypuje się bardziej?

O tak, sie dzie teraz:

No route matches {:action=>"show", :controller=>"produkts", :firma_id=>#<Produkt id: 16, firma_id: 3, category_id: nil, subcategory_id: nil, nazwa: "Podaj nazwę produktu", opis: "", widoczny: true, zdjecie1_file_name: nil, zdjecie1_content_type: nil, zdjecie1_file_size: nil, zdjecie1_updated_at: nil, zdjecie2_file_name: nil, zdjecie2_content_type: nil, zdjecie2_file_size: nil, zdjecie2_updated_at: nil, zdjecie3_file_name: nil, zdjecie3_content_type: nil, zdjecie3_file_size: nil, zdjecie3_updated_at: nil, cena: "", waluta: "PLN", link: "", created_at: "2016-02-04 20:56:47", updated_at: "2016-02-04 20:56:47">, :id=>nil} missing required keys: [:id]

Pokaż out z rake routes

firma_produkts GET /firmas/:firma_id/produkts(.:format) produkts#index
POST /firmas/:firma_id/produkts(.:format) produkts#create
new_firma_produkt GET /firmas/:firma_id/produkts/new(.:format) produkts#new
edit_firma_produkt GET /firmas/:firma_id/produkts/:id/edit(.:format) produkts#edit
firma_produkt GET /firmas/:firma_id/produkts/:id(.:format) produkts#show
PATCH /firmas/:firma_id/produkts/:id(.:format) produkts#update
PUT /firmas/:firma_id/produkts/:id(.:format) produkts#update
DELETE /firmas/:firma_id/produkts/:id(.:format) produkts#destroy

jest firma_produkt dla produkts#show

Rozumiem, że product belongs_to company?
Jeżeli tak to akcja show (set_product) powinna wyglądać tak:

@company = Company.find(params[:company_id])

szukamy modelu nadrzędnego (company_id podane jest w parametrach)

@product = @company.products.find(params[:id])

szukamy w danym modelu firmy o id z parametrów.

Ok już widzę dokładnie:
wyszukujesz firmę (model nadrzędny), ale nic z tego nie robisz
Produkt.find(params[:id]) - wyszukuje produkt o danym id, ale nie masz podanego w parametrach firma_id ( co jest sprzeczne z modelem - produkt belongs_to firma ).
musi być

@firmas.produkts.find(params[:id]) 

wtedy już podajesz w zmiennej firmas firma_id (tutaj znowu kłania się konwencja nazewnictwa - firma jest jedna więc nie firmas tylko firma), można też zrobić to ewentualnie innaczej - przez podanie hasha z parametrami wszystkimi do zapytania - ale ten pierwszy sposób jest bardziej Rails Way.

Nie polecam też na początek takiego rozbijania akcji - lepiej powtórzyć sobie kilka razy w każdej akcji tą samą linijkę - a dopiero później wrzucić to do odpowiedniej metody. Będzie to o wiele bardziej przejrzyste i zrozumiałe dla Ciebie (i łatwiejsze do troubleshootingu). Później z czasem się nauczysz tworzyć odpowiednie metody( w podstawowych controllerach typu CMS jest to bardzo schematyczne)

w indexie powinieneś mieć zmienną @produkty (bo jest ich wiele) i zrobić
@produkty.each do |produkt| - wtedy kod jest bardziej przejrzysty.

Konwencja nazewnictwa:
index - wszystkie - liczba mnoga
show i inne akcje - liczba pojedyncza

Rozumiem, wielkie dzięki, zaraz wdrażam to w życie,
Trochę namieszałem, ale wcześniej nie tykałem restful i nie miałem problemu,
Mam jeszcze jedno pytanie,
chciałbym poprawić nazewnictwo w projekcie, jest na to jakiś sposób czy po prostu usuwam model controller i widoki, jesli tak to czy na to jest jakiś szybki sposób? (komenda w wierszu poleceń)?, czy po prostu usuwam.
Bardzo dziękuję i pozdrawiam

Musisz najpierw zmienić nazwy tabeli migracją - google me!
Potem zmieniasz nazwy modeli (i ich zawartości)
Potem zmieniasz controllery
Na końcu widoki

Mam nadzieje ze niczego nie zapomnialem

migracją - google me!
przepraszam za głupie pytania, ale czy mógłbyś naświetlić mi ten sposób,

robisz rails g migration w konsoli - stworzy Ci pustą migrację.
tam robisz rename_table
potem rake db:migrate w konsoli

Google nie boli :confused:

Czasem boli :slight_smile:
dzięki bardzo, teraz dam radę, napiszę jak zadziała