Ruby on Rails - настройка функций отзывов

Я пытаюсь настроить функцию в своем приложении Ruby on Rails, которая позволяет пользователям просматривать фотографии.

Я следовал этому руководству в качестве ссылки.

http://ruby.about.com/od/rubyonrails/ss/blogpart4_4.htm

Исходя из моего опыта работы над другими проектами Ruby on Rails, я думаю, что модель отношений Posts/Comments может быть использована здесь для отношений Pictures/Reviews.

Я сначала создал эшафот.

rails g scaffold review name:string body:text picture:references

Мне бы хотелось, чтобы на каждой странице с картинками была отдельная страница для собственных обзоров.

Так как мне не нужна страница индекса для моего контроллера обзоров, я удалил эту строку из моего файла rout.rb

resources: reviews

Я заменил это, создав маршруты

match '/pictures/:id/reviews', to: 'reviews#show', via: 'get'
match '/pictures/:id/reviews/edit', to: 'reviews#edit', via: 'get'
match '/pictures/:id/reviews/new', to: 'reviews#new', via: 'get'

Здесь мой путь включает в себя вложенные обзоры внутри картинок.

маршрут

favorite_picture_path   PUT     /pictures/:id/favorite(.:format)    pictures#favorite
pictures_path           GET     /pictures(.:format)                 pictures#index
                        POST    /pictures(.:format)                 pictures#create
new_picture_path        GET     /pictures/new(.:format)             pictures#new
edit_picture_path       GET     /pictures/:id/edit(.:format)        pictures#edit
picture_path            GET     /pictures/:id(.:format)             pictures#show
                        PATCH   /pictures/:id(.:format)             pictures#update
                        PUT     /pictures/:id(.:format)             pictures#update
                        DELETE  /pictures/:id(.:format)             pictures#destroy
users_path              GET     /users(.:format)                    users#index
                        POST    /users(.:format)                    users#create
new_user_path           GET     /users/new(.:format)                users#new
edit_user_path          GET     /users/:id/edit(.:format)           users#edit
user_path               GET     /users/:id(.:format)                users#show
                        PATCH   /users/:id(.:format)                users#update
                        PUT     /users/:id(.:format)                users#update
                        DELETE  /users/:id(.:format)                users#destroy
sessions_path           POST    /sessions(.:format)                 sessions#create
new_session_path        GET     /sessions/new(.:format)             sessions#new
session_path            DELETE  /sessions/:id(.:format)             sessions#destroy
contacts_path           POST    /contacts(.:format)                 contacts#create
new_contact_path        GET     /contacts/new(.:format)             contacts#new
root_path               GET     /                                   pictures#welcome
users_new_path          GET     /users/new(.:format)                users#new
about_path              GET     /about(.:format)                    pictures#about
                        GET     /contacts(.:format)                 contacts#new
                        GET     /users/:id/favorites(.:format)      users#favorites
signup_path             GET     /signup(.:format)                   users#new
signin_path             GET     /signin(.:format)                   sessions#new
signout_path            DELETE  /signout(.:format)                  sessions#destroy
                        GET     /pictures/:id/reviews(.:format)     reviews#show
                        GET     /pictures/:id/reviews/edit(.:format)    reviews#edit
                        GET     /pictures/:id/reviews/new(.:format) reviews#new
updated_path            GET     /updated(.:format)              pictures#newest_updates
                        GET     /top-rated(.:format)            pictures#high_ratings

ReviewsController

class ReviewsController < ApplicationController
  before_action :set_review, only: [:show, :edit, :update, :destroy]

  def show
    @picture = Picture.find(params[:id])
    @review = Review.find(params[:id])
  end

  def new
    @review = Review.new
  end

  def edit
     @picture = Picture.find(params[:picture_id])
     @review = Review.find(params[:id])
  end

  def create
    @picture = Picture.find(params[:picture_id])
    @review = @picture.reviews.build(params[:review])

    if @review.save
      ;flash[:notice] = 'Review was successfully created.'
      redirect_to @picture
    else
      flash[:notice] = "Error creating review: #{@review.errors}"
      redirect_to @picture
    end
  end

  def update
    @picture = Picture.find(params[:picture_id])
    @review = Review.find(params[:id])

    if @review.update_attributes(params[:review])
      flash[:notice] = "Review updated"
      redirect_to @picture
    else
      flash[:error] = "There was an error updating your review"
      redirect_to @picture
    end
  end

  def destroy
    @picture = Picture.find(params[:picture_id])
    @review = Review.find(params[:id])
    @review.destroy
    redirect_to(@review.post)
  end

  private

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

    def review_params
      params.require(:review).permit(:username, :body, :picture_id)
    end
end

Я удалил действие index из моего ReviewsController.

модели

class Review < ActiveRecord::Base
  belongs_to :picture
end

class Picture < ActiveRecord::Base
  has_many :reviews
end

Выше я установил отношения один-ко-многим между фотографиями и рецензиями.

Отзывы Миграция

class CreateReviews < ActiveRecord::Migration
  def change
    create_table :reviews do |t|
      t.string :username
      t.text :body
      t.references :picture, index: true

      t.timestamps
    end
  end
end

Исходя из моего понимания Rails, это должно работать.

Картинки # Показать страницу

<% @title = "#{@picture.title}" %>

<h4 class = 'indent'>Picture Statistics</h4>

  <ul id = 'view'>
    <li><strong>Title:</strong> <%= @picture.title %></li>
    <li><strong>Category:</strong> <%= @picture.category %></li>
    <li><strong>Rating:</strong> <%= pluralize(@picture.rating, 'Star') %></li>
    <li><strong>Favorited:</strong> By <%= pluralize(@picture.users.count, 'User') %></li></br>
  </ul>

  <% if @picture.rating > 4 %>

  <button class = 'top-picture'>Top Rated</button>

  <% end %>

<%= form_for @picture do |f| %>

  <p>
    <%= f.label :stars, 'Rating', class: 'indent' %>
    <div class= "rating">
      1 &#9734;<%= f.radio_button :stars, '1' %>
      2 &#9734;<%= f.radio_button :stars, '2' %>
      3 &#9734;<%= f.radio_button :stars, '3' %>
      4 &#9734;<%= f.radio_button :stars, '4' %>
      5 &#9734;<%= f.radio_button :stars, '5' %>
    </div>
  </p>

  <p class = 'indent'>
   <input class="btn btn-info" type="submit" value="Review">
  </p>

  <a href = "/pictures/:id/reviews">Reviews</a>

<% end %>
<p class = 'indent'>
  <a class="btn btn-info" href="/pictures" role="button">Index</a>
</p>

Однако, когда я нажимаю на ссылку в моем Pictures/:id(показать страницу)

<a href = "/pictures/:id/reviews">Reviews</a>

Ошибка RecordNotFound

Active Record::RecordNotFound in ReviewsController#show
Couldn't find Review with id=:id

Extracted source (around line #54):
53 def set_review
54  @review = Review.find(params[:id])
55 end
56
57 def review_params

Так как я столкнулся с ошибкой RecordNotFound, я подозреваю, что проблема лежит в ReviewsController, скорее всего, с параметрами.

Я верю, что у меня правильная идея, но я где-то допустил ошибку. Обратная связь и критика очень ценятся. Извините, если это звучит как глупый вопрос, я просто не очень хорош в Ruby.

4 ответа

Решение

Маршруты

Ради потомков вам лучше всего настроить маршруты следующим образом:

#config/routes.rb
resources :pictures do
   resources :reviews, only: [:show, :edit, :new]
end

Всякий раз, когда вы создаете маршруты в Rails, вы должны помнить, что вся структура была построена вокруг "объектов" / "ресурсов". Вот почему маршруты известны как resourceful маршруты (и почему у них есть resources директива) - они позволяют вам определять маршруты вокруг различных ресурсов вашего приложения

Я рекомендую использовать nestedструктура ресурсов.

-

Помощники

Ваша проблема была решена с использованием кода, предоставленного Santosh и тому подобное. IE:

<%= link_to "Your Link", your_link_path(@object) %>

Вы должны оценить, как это работает. Каждый раз, когда вы используете route помощник в Rails (в link_to помощник), он будет просматривать ваши маршруты и найти детали, которые ему нужны.

Вы ссылались на следующий путь: pictures/:id/reviews - как выяснилось, это неправильно, потому что Rails не имеет никакого отношения к URL ссылки, кроме ее построения во время рендеринга.

Учитывая, что Rails - это основанная на HTTP инфраструктура без сохранения состояния, Rails должен сопоставлять любые данные при каждом запросе. Это означает, что если вы хотите создавать ссылки, вы должны позволить Rails создавать ссылки при рендеринге, передавая статический набор данных вашему контроллеру в серверной части.

Надеюсь, это поможет?

Как у вас .html.erb файл, старайтесь не писать сырой HTML.

Просто обновите эту ссылку:

<a href = "/pictures/:id/reviews">Reviews</a>

к

<%= link_to "Reviews", picture_reviews_path(@picture) %>

Редактировать:

Вы должны присвоить имена своим match заявления как:

match '/pictures/:id/reviews', to: 'reviews#show', via: 'get', :as => 'picture_reviews'

Это сгенерирует:

picture_reviews GET    /pictures/:id/reviews(.:format)          reviews#show
match '/pictures/:id/reviews', to: 'reviews#show', via: 'get'
match '/pictures/:id/reviews/edit', to: 'reviews#edit', via: 'get'

Эти 2 маршрута не имеют идентификатора проверки, но ваш контроллер ожидает их. внести это изменение

match '/pictures/:picture_id/reviews/:id', to: 'reviews#show', via: 'get'
match '/pictures/:picture_id/reviews/:id/edit', to: 'reviews#edit', via: 'get'

И изменить это

<a href = "/pictures/:id/reviews">Reviews</a>

в

<a href = "/pictures/#{@picture.id}/reviews/#{@review.id}">Reviews</a>

Но вы должны серьезно рассмотреть вопрос об использовании ресурсов ресурсов и помощников

Попробуйте использовать вложенные ресурсы, а не создавать их вручную

resources :pictures, except: [:index] do
  resources :reviews
end

И как уже упоминалось, вы должны использовать rails link_to для генерации правильных URL

Другие вопросы по тегам