Вложенный маршрут Создание нового объекта не завершается, если цикл - PullRequest
0 голосов
/ 21 марта 2020

В настоящее время у меня есть модель обзора, которая позволит пользователю создавать обзоры для чайной модели. Пользователь, который создает обзор, может редактировать или удалять обзор. У меня есть вложенный маршрут в чаях, который позволяет вам создавать новый обзор для чая, поскольку вы просматриваете все отзывы для этого конкретного c чая. В настоящее время новый вложенный маршрут не позволяет создавать, так как аутентифицированный пользователь Google не может создать обзор. Ниже мой контроллер действия и вид. Я не вижу никаких ошибок, просто кажется, что выполняется откат базы данных и следование логам else c и повторное отображение новой страницы.

Terminal actions

Model
class Review < ApplicationRecord
  belongs_to :user
  belongs_to :tea


  validates :title, presence: true
  validates :rating, numericality: {only_integer: true, greater_than_or_equal_to: 0, less_than: 11}

  validates :tea, uniqueness: {scope: :user, message: "has already been reviewed by you" }

  scope :order_by_rating, ->{left_joins(:reviews).group(:id).order('avg(rating) desc')}


end
Controller Action
      def create
        @review = current_user.reviews.build(review_params)
        if @review.valid?
          @review.save
          redirect_to new_review_path(@review)
        else
          render :new
        end
      end
View
<%= form_for Review.new do |f|%>
    <% if params[:tea_id] %>
     <%= f.hidden_field :tea_id %>
    <% else %>
      <div>
        <%= f.label :tea_id, "Select a Tea Blend" %>
        <%= f.collection_select :tea_id, Tea.alpha, :id, :flavor_and_brand, include_blank: true %>
      </div>
    <% end %>
    <div>
        <%= f.label :rating %>
        <%= f.number_field :rating, min:0, max:10 %>
    </div>
    <br>
    <div>
        <%= f.label :title %>
        <%= f.text_field :title %>
    </div> 
    <br>
    <div>
        <%= f.label :content  %>
        <br>
        <%= f.text_area :content, size: "60x25" %>
    </div> 
    <br>
    <%= f.submit %>
<% end %>                  

Ответы [ 2 ]

0 голосов
/ 22 марта 2020

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

# config/routes.rb
resources :teas do
  resources :reviews, shallow: true
end

shallow: true делает так, чтобы действия члена (показ, редактирование, обновление, уничтожение) не были вложенными.

Затем настройте частичное для формы, чтобы вы могли использовать его повторно:

# app/views/reviews/_form.html.erb
<%= form_for([local_assigns(:tea), review]) do |f| %>
  <div class="field">
    <%= f.label :rating %>
    <%= f.number_field :rating, min:0, max:10 %>
  </div>
  <div class="field">
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div> 
  <div class="field">
    <%= f.label :content  %>
    <%= f.text_area :content, size: "60x25" %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

By передавая массив, вы получаете вложенный маршрут в качестве атрибута действия (/teas/1/reviews), и вам не нужно возиться со скрытым вводом. local_assigns(:tea) избегает ошибки NoMethodError, если она не передана в частичное. Массив сжат, так что этот фрагмент будет работать как для создания, так и для обновления.

# app/views/reviews/new.html.erb
<%= render partial: 'form', tea: @tea, review: @review >
# app/views/reviews/edit.html.erb
<%= render partial: 'form', review: @review >
# app/views/teas/show.html.erb
<h2>Review this tea</h2>
<%= render partial: 'reviews/form', tea: @tea, review: @tea.reviews.new >

В контроллере вы можете просто получить чай из params[:tea_id], так как вы передали его в путь.

class ReviewsController < ApplicationController
  before_action :set_tea, only: [:new, :index, :create]
  before_action :set_review, only: [:show, :edit, :update, :destroy]

  # POST /teas/1/reviews
  def create
    # creating the review off the tea reveals intent better than doing
    # it off the user
    @review = @tea.reviews.new(review_params) do |r|
      r.user = current_user
    end
    # Always check if the record is actually persisted 
    # - not just if the applications validations pass!
    if @review.save
      # you could also redirect to the review but this makes more 
      # sense from a ux perspective
      redirect_to @tea, notice: 'Thank you for your review'
    else
      render :new
    end
  end

  # GET /reviews/:id/edit
  def edit
  end

  # PUT|PATCH /reviews/:id
  def update
    if @review.update(review_params)
      redirect_to @review, notice: 'Review updated.'
    else
      render :edit
    end
  end

  private
  def set_tea
    @tea = Tea.find(params[:tea_id])
  end

  def set_review
    @review = Review.find(params[:id])
  end

  def review_params
    params.require(:review).permit(:rating, :title)
  end
end
0 голосов
/ 21 марта 2020

Простой ответ состоял в том, что я не включил создание в мое действие до. Это то, что заставляло мой set_tea не выполняться автоматически как действие до.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...