W nawiązaniu do wątku o poprawności pisania kodu w RoR

Mam następujący dylemat.

Utworzyłem dwa modele danych

parent (z opcą has_many :childs) i 
child (z opcją beolngs_to :parent)

Używając:

rails g scaffold Child .....

RoR domyślnie generuje m.in formularze, controllery i w /config/route.rb wstawia wpis:

resources :childs

Zgodnie z przykładem omawianym w serii:

(dokładnie film: https://www.youtube.com/watch?v=HVuawlZTLBw&index=29&list=PLgYiyoyNPrv-j6vFyXP8mgRyvpRqFkjb8 )

przeniosłem folder /app/views/childs do katalogu rodzica, czyli /app/views/parents/childs i zmodyfikowałem je zgodnie z instrukcjami

Zgodnie z instrukcjami utworzyłem w app/controllers folder parents i przeniosłem do niego childs_controller.rb.

Zmodyfikowałem także zawartość tego app/controllers/parents/childs_controller.rb.
dokonując wpisów wg wskazówek z filmu.

Musiałem także zmienić zawartość /config/route.rb.

 resources :parents do
    resources :childs, excpt: [:index], controller: 'parents/childs'
  end

Wszystko gra i buczy jak w przykładzie. SUPER! :smiley:
…Ale zachciało mi się wyświetlać i listować “dzieci” nie tylko poprzez formularz rodzica,
ale także listując wszystkie dzieci i dodawać nowe pozycje, edytować (dodając na formularzu f.select Parent.all …)

No i pojawia się pierwszy “zgryz”
Nie mogę listować http://127.0.0.1:3000/childs, bo nie ma takiej ścieżki routingu.
Zmieniam zatem route.rb i mam teraz wpisy:

  resources :childs, controller: 'parents/childs'
  
  resources :parents do
    resources :childs, excpt: [:index], controller: 'parents/childs'
  end

i listowanie bezpośrednio “dzieci” już działa ale sięga do kotrolera parentss/childs’, który jest przecież zmodyfikowany!
Podobnie wywołuje formularze z app/views/parents/childs, które zmodyfikowane zostały na potrzeby wywołań z okna rodzica!

np. “_form.html.erb”

<%= form_for [@parent, @child] do |f| %>

a było przecież:

<%= form_for (@child) do |f| %>

Pytanie jakie mam do praktyków, którzy już na niejednym projekcie zęby stępili.
Jak powinno się prawidłowo postępować, tj …

  1. Czy należy tworzyć dwa kontrolery (app/controllers/parents/childs_controller.rb. i app/controllers/childs_controller.rb.), by obsługiwać raz “dzieci”, które dodajemy/usuwamy/modyfikujemy z okna rodzica, a innym razem bezpośrednio?
  2. Czy należy tworzyć osobno /app/views/parents/childs/* i drugi zestaw /app/views/childs/* ?
  3. A może należy stosować if-y i mieć jeden kontroler i jeden zestaw widoków, który będzie różnie działał w zależności od tego, czy obsługujemy dzieci bezpośrednio, czy za pośrednictwem formularzy rodzica?

Wdzięczny będę za wskazówki, bo ucząc się nie chciałbym ani sięgać lewą ręką do prawej kieszeni, ani złych nawyków w sobie wyrabiać.

  1. Liczba mnoga od child to children.

  2. Kontroler wystarczy jeden. Jeśli potrzebujesz ścieżki http://localhost/children to dodaj ją osobno do config/routes.rb. Niech wskazuje na akcję np. all_children. Przez zagnieżdzenie child w parent sugerujesz, że dzieci zawsze należą do rodzica.

    get '/children', to: 'children#all_children', as: 'all_children'

  3. Używając render możesz wyświetlić dowolny partial. Nie ma potrzeby ich dublowania.

  4. Jeśli musisz skorzystać z if/else w widokach to prawdopodobnie robisz coś źle.

Oczywiście, że Children :smile:
…w rzeczywistości tabele nazywają się inaczej, ale słuszna uwaga, że skaleczyłem ten angielski

3(4) Czyli sugerujesz osobne formularze /app/views/children/* i drugi zestaw /app/views/parents/children/* ?

  1. Jeden kontroler i w nim “ify”?

Przez zagnieżdzenie child w parent sugerujesz, że dzieci zawsze należą do rodzica.

Bo przecież tak jest :smile: , co jednak nie przeszkadza mi, by chcieć wylistować sobie wszystkie dzieci z bazy, a na formularzu “niezależnym” mieć selecta do tabeli z rodzicami.

Pytam, jakie stosuje się zasady z kontrolerami i formularzami, przy takich konstrukcjach typu rodzic->dzieci

Wylistuj wszystkie dzieci z bazy w osobnej, nie CRUDowej, akcji all_children. Potrzebujesz wtedy stworzyć tylko jeden dodatkowy view: parents/children/all_children.html.erb. Z zawartością:

render @children

Podobna linijka powinna znaleźć się w miejscu gdzie wyświetlasz rodzica z dziećmi.

render @parent.children

W ten sposób nie potrzebujesz niczego dodatkowego. Jeśli renderujesz kolekcję (np. @children) Rails domyślnie odszuka partial o nazwie _child.html.erb i wyświetli go dla każdego elementu z kolekcji.

OK, a co z edytowaniem tak wyświetlonych dzieci?

Domyślnie w kontrolerze są takie wpisy:

  def new
    @child = Child.new
  end

a ja, chcąc mieć obsługę dzieci w formularzu rodzica przerabiałem to na:

  def new
    @parent = Parent.find(params[:parent_id])
    @child = Child.new
  end

Podobnie w innych miejscach tego kontrolera.
Teraz, gdy chcę dodawać nowe pozycje, to wysypuje się na wierszu:

@parent = Parent.find(params[:parent_id])

Czy powinienem się bawić w ify w jednym kontrolerze, czy obsługiwać to innym kontrolerem “wyjętym” z folderu app/controllers/parents ?

Nie widziałem kursu z którego się uczysz i nie wiem jakie podejście jest tam przedstawione, ale zakładam, że najpierw wybiera się Parent  i do niego dodaje Child. Aby obsłużyć odwrotne podejście Child -> Parent będziesz musiał trochę pokombinować z formularzami i widokami.

Na przykład gdybyś chciałbyś wybierać Parent dopiero w formularzu Child wtedy usuń linijkę:

@parent = Parent.find(params[:parent_id])

A do formularza Child dodaj pole do edycji wartości parent_id.