W moim ReviewsController mam dwie prywatne metody zwane before_action:

def find_course
  @course = Course.where(:id=>params[:course_id]).first
end

def find_professor
  @professor = Professor.where(:id=>params[:professor_id]).first
end

Naprawdę Course przez params i z jakiegoś powodu dostaję undefined method ID 'dla NIL: Błąd NilClass` w mojej metodzie tworzenia:

def create
  @review = Review.new(review_params)
  @review.course_id = @course.id
  @review.professor_id = @professor.id
  @review.user_id = current_user.id

  if @review.save
    redirect_to course_path(@course)
  else
    render 'new'
  end
end

Metoda tworzenia jest wywoływana w formie częściowej jako takiej:

<%= simple_form_for @review do |f| %>
  <%= f.input :rating %>
  <%= f.input :comment %>
  <%= f.button :submit %>
<% end %>

Formularz jest wyświetlany przez link na szablonie pokazu kursu:

<h2><%= @course.name %></h2>
<table class="table">
  <thead>
    <tr>
      <th scope="col">Professors</th>
      <th scope="col">Reviews</th>
    </tr>
  </thead>
  <tbody>
    <% @course.professors.each do |professor| %>
      <tr>
        <td><%= professor.name %></td>
        <td><%= link_to "Add Review", new_review_path(course_id: @course.id, professor_id: professor.id) %></td>
      </tr>
    <% end %>
  </tbody>
</table>

I new_review_path zgodnie z definicją routes.rb:

resources :reviews, path_names: { new: 'course/:course_id/professor/:professor_id' }

Dla pewnego dziwnego powodu, jeśli zastąpię @course = Course.where(:id=>params[:course_id]).first za pomocą @course = Course.find(7) (7 będąc identyfikatorem istniejącego kursu), metoda tworzenia działa idealnie dobrze. Jak odpowiednio pobrać kurs i rekordy profesora z danym parametrem?

-1
Bargain23 4 czerwiec 2018, 07:55

3 odpowiedzi

Najlepsza odpowiedź
<td><%= link_to "Add Review", new_review_path(course_id: @course.id, professor_id: professor.id) %></td>

To pójdzie reviews/new.html.erb,

Tutaj będziesz musiał wysłać course_id i professor_id z ukrytym polem, dzięki czemu można pobrać @course i @professor przed utworzeniem działania. W przeciwnym razie @course i @professor powróci nil.

Zmodyfikowany kod: -

O ile rozumiem, że nie musisz find_professor i find_course i find_course i find_course i find_course Przed utworzeniem działania, ponieważ te dwa pola są już w modelu Review, więc po prostu przekazać go forma_For owijką i przejść te wszystkie razem w Strong_params.

<%= simple_form_for @review do |f| %>
  <%= f.input :rating %>
  <%= f.input :comment %>
  <%= f.hidden_field :course_id, :value => params[:course_id]%>
  <%= f.hidden_field :professor_id, :value => params[:professor_id] %>
  <%= f.hidden_field :user_id, :value => current_user.id %>
  <%= f.button :submit %>
<% end %>

W kontrolerze

def create
  @review = Review.new(review_params)
  if @review.save
    course = @review.course
    #redirect_to course_path(@course)
    redirect_to course_path(course)
  else
    render 'new'
  end
end

private
  def review_params
    params.require(:review).permit(:rating,:comment,:course_id, :professor_id, :user_id)
  end
1
Gabbar 4 czerwiec 2018, 06:14

Musisz sprawdzić, czy kurs i profesor obiekty są pobierane i istnieją, zanim zadzwonią do .id

Na przykład:

if @course && @professor
  @review = Review.new(review_params)
  @review.course_id = @course.id
  @review.professor_id = @professor.id
  @review.user_id = current_user.id

  if @review.save
    redirect_to course_path(@course)
  else
    render 'new'
  end
end
0
Rajesh V 4 czerwiec 2018, 06:27

To dobry zwyczaj używania,

@course = Course.find(params[:course_id])
@professor = Professor.find(params[:professor_id])

Proszę przejść do góry, możesz uzyskać odpowiednio.

-2
Gautam Kathrotiya 4 czerwiec 2018, 05:25