Iteracja dwóch tabel, zaczytywanie id


#1

Witam, ucząc się Railsów napotkałem problem. Nie wiem jak zaiterować dwie tabele oraz jak zaczytać ID usługi.

Pierwszy problem. Chciałbym wyświetlać średnią z ocen serwisu/usługi (rating.rate) wraz z tabelą usług.
Posiadam 2 tabele:
class Service < ApplicationRecord
belongs_to :user
has_many :ratings, :foreign_key => “service_id”
end

class Rating < ApplicationRecord
belongs_to :user
belongs_to :service
end

oraz devise:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :services, :foreign_key => “user_id”
has_many :ratings, :foreign_key => “user_id”
end

Chciałbym zaiterować Service i Rating i wyświetlić je w jednej tabeli. Stworzyłem zmienną:
@services = Service.left_outer_joins(:ratings) #(nie wiem czy to dobrze, ale nie wyświetla błędu)

Samo services iterowałem tak:
<% @services.each do |service| %> i było dobrze.
Niestety nie wiem, jak zaiterować services wraz ratings z left outer joinem (tak żeby tam gdzie jest ocena, to wyświetlało średnią z wszystkich ocen użytkowników, a gdzie nie ma, to było “brak”)

Drugi problem, to przy dodawaniu nowej oceny jak zaczytać service_id?
user_id z devise wczytuję w metodzie create:
@service.user = current_user
Gdzie powinien najlepiej znajdować się przycisk dodawania oceny żeby zaczytać stamtąd service_id? index, czy show czy jeszcze inaczej?

Mam nadzieję że opisałem w miarę jasno moje problemy i niczego nie zamieszałem :slight_smile:


#2

Z góry przepraszam za post pod postem. Pierwszy problem chyba rozwiązany, okaże się jak poprawnie naprawię drugi.

Co do drugiego problemu, chciałbym rozwinąć wątek:

do routes.rb dodałem:
resources :services do
resources :ratings

Teraz przechodzi mi do dodawania oceny, przycisk z akcji services/index:
<%= link_to ‘Dodaj ocenę’, new_rating_path(service), class: “btn btn-default btn-xs” %>

URL wygląda tak:
http://localhost:3000/services/4/ratings/new
lub
http://localhost:3000/ratings/new.4

Która forma dodawania oceny jest prawidłowa? Jak zaczytać id serwisu (w tym przypadku 4) do pola rating.service_id ?

Próbowałem zaczytać na wiele sposobów i albo zapisuje id jako null
albo “Couldn’t find Service without an ID” przy @service = Service.find(params[:id]) w akcji create.


#3

ta:
http://localhost:3000/services/4/ratings/new

A co do paramsow to podejrzyj sobie wszystkie params i znajdziesz tam co potrzeba :slight_smile:


#4

Porządany params mi się pokazuje w konsoli, próbowałem na wiele sposobów go zaczytać…i nie mogę. Myślę że już przekombinowałem i przegapiłem gdzieś prosty sposób żeby to zrobić…


#5

Metoda create w kontrolerze mogłaby zaczynać się mniej więcej tak:

def create
  service = Service.find(params[:service_id])
  rating = service.ratings.build(rating_params)
...

przy założeniu, że masz jeszcze jakieś rating_params które dodajesz do rating podczas tworzenia


#6

wyrzuca błąd: Couldn’t find Service without an ID

# ActiveRecord::RecordNotFound in RatingsController#create

:confused:

moja cała metoda create w ratings_controller:

  def create
    @rating = Rating.new(rating_params)
    service = Service.find(params[:service_id])
    rating = service.ratings.build(rating_params)
    @rating.user = current_user
    @rating.save #(:validate => false)
    redirect_to services_path
  end

dodatkowo

private
def rating_params
params.require(:rating).permit(:rate, :comment, :signature, :service_id, :user_id)
end


#7

Z której linijki kodu leci ten błąd? Użyj byebuga w create i sprawdź co rzeczywiście przychodzi w paramsach i co zwraca rating_params.

jak już deklarujesz @rating to robienie drugi raz tego samego z rating nie ma sensu, wybierz jedno z dwóch i na nim wywołaj .save.
Problem na pewno jest z paramsami, bo najwidoczniej params[:service_id] jest nilem. Może musisz poprawić formularz


#8
<%= form_for @rating do |f| %>
  <div class="form-group">
    <%= f.label :rate, "Twoja ocena" %>
    <%= f.select :rate, [['5', '5'], ['4', '4'], ['3', '3'], ['2', '2'], ['1', '1']], class: "form-control" %>
  </div>
  <div class="form-group">
      <%= f.label :comment, "Komentarz" %>
      <%= f.text_field :comment, class: "form-control" %>
  </div>
  <div class="form-group">
      <%= f.label :signature, "Podpis" %>
      <%= f.text_field :signature, class: "form-control" %>
  </div>
  <%= f.submit "Dodaj ocenę", class: "btn btn-primary" %><%= link_to "Wróć do usług",  services_path, class: "btn btn-default" %>

<% end %>

tak wygląda formularz

błąd wyskakuje przy linijce @service = Service.find(params[:id])

Później sprawdzę tego byebuga.


#9

Wg twoich paramsow ze screena powinno być:

@service = Service.find(params[:service_id])