тег form_for и вложенная форма - использовать пользовательский метод из контроллера - PullRequest
0 голосов
/ 26 марта 2012

Я новичок в Rails и создаю приложение, в котором члены колледжа (преподаватели и студенты) могут создавать посты и комментировать их.Позже я хочу добавить в него систему вложений (родословная) и систему баллов.

У меня есть Post, Comment и Member model.Модель Post была создана с помощью Scaffolding, модель Member была создана с помощью Devise, а Comment - просто модель.

На моей странице показа Post я хотел бы иметь комментарии под сообщениями, я 'Мы достигли некоторого прогресса (благодаря SO я узнал совсем немного), но теперь я столкнулся с проблемой, что всякий раз, когда я пытаюсь опубликовать пустой комментарий, rails перенаправлял на страницу редактирования.Как изменить это так, чтобы рельсы оставались только на странице показа и отображали ошибки?

Для этого я немного искал, создал новый метод 'update_comments' в post_controller.rb и попытался изменить атрибуты тега forms_for, какв коде ниже, но теперь я получаю ошибку маршрутизации при отправке.

app / models / member.rb

class Member < ActiveRecord::Base
  #Associations
  belongs_to :department

  has_one :student, :dependent => :destroy
  accepts_nested_attributes_for :student

  has_one :nstudent, :dependent => :destroy
  accepts_nested_attributes_for :nstudent

  has_many :posts, :dependent => :destroy
  has_many :comments, :dependent => :destroy  
end

app / models / post.rb

class Post < ActiveRecord::Base

  #Associations
  belongs_to :member
  has_many :comments, :dependent => :destroy

  accepts_nested_attributes_for :comments
end

app / models / comment.rb

class Comment < ActiveRecord::Base

  # Associations
  belongs_to :member
  belongs_to :post

  validates_presence_of :content
end

config / rout.rb

Urdxxx::Application.routes.draw do
  devise_for :members

  resources :posts do
    member do
     get 'update_comment'
    end
  end

  root :to => 'posts#index'

app / controllers / posts_controller.rb

class PostsController < ApplicationController
  # Devise filter that checks for an authenticated member
  before_filter :authenticate_member!

# GET /posts
# GET /posts.json
def index
  @posts = Post.find(:all, :order => 'points DESC')

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @posts }
  end
end
...
# GET /posts/1/edit
def edit
  @post = Post.find(params[:id])    
end

# POST /posts
# POST /posts.json
def create
  @post = Post.new(params[:post])
  @post.member_id = current_member.id if @post.member_id.nil?

  respond_to do |format|
    if @post.save
      format.html { redirect_to @post, notice: 'Post was successfully created.' }
      format.json { render json: @post, status: :created, location: @post }
    else
      format.html { render action: "new" }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

# PUT /posts/1
# PUT /posts/1.json
def update
  @post = Post.find(params[:id])

  respond_to do |format|
    if @post.update_attributes(params[:post])
      format.html { redirect_to @post, notice: 'Post was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: "edit" }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

# DELETE /posts/1
# DELETE /posts/1.json
def destroy
  @post = Post.find(params[:id])
  @post.destroy

  respond_to do |format|
    format.html { redirect_to posts_url }
    format.json { head :no_content }
  end
end

# Not made by scaffold
def update_comment
  @post = Post.find(params[:id])        

  respond_to do |format|
    if @post.update_attributes(params[:post])
      format.html { redirect_to @post, notice: 'Comment was successfully created.' }
      format.json { head :no_content }
    else
      format.html { render action: "show" }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end
end

app / views / posts / show.html.erb

<p> Have your say </p>
<%= form_for @post, :url => {:action => 'update_comment'} do |p| %>
  <%= p.fields_for :comments do |c| %>
     <!-- Following 3 lines saved my life -->
      <% if c.object.new_record? %>
        <%= c.text_area :content, :rows => 4 %>
        <%= c.hidden_field :member_id, value: current_member.id %>
      <% end %>
   <% end %>
   <%= p.submit "Reply" %>
<% end %>

изображение моей страницы показа: http://i.stack.imgur.com/TBgKy.png

при комментировании: http://i.stack.imgur.com/JlWeR.png

Обновление:

Оглянулся и внес изменения здесь, после чегоКен сказал.Я не знаю как, но пока это работает.

app / controllers / posts_controller.rb

def update
  @post = Post.find(params[:id])

  respond_to do |format|
  if @post.update_attributes(params[:post])
    format.html { redirect_to @post, notice: 'Post was successfully updated.' }
    format.json { head :no_content }
  elsif :comments
    format.html { render action: "show" }
    format.json { render json: @post.errors, status: :unprocessable_entity }
  else
    format.html { render action: "edit" }
    format.json { render json: @post.errors, status: :unprocessable_entity }
  end
  end
end

Ответы [ 2 ]

0 голосов
/ 26 марта 2012

Вам не нужен пользовательский метод. Это не очень приятно. Смотрите, например, http://www.sitepoint.com/restful-rails-part-i/ для получения информации о REST. Это не тот случай, когда есть оправдание использовать пользовательский метод.

Всякий раз, когда вы обнаруживаете, что добавляете собственные методы, вы должны долго и усердно думать о том, нужно ли это. Обычно, если вам нужны пользовательские методы, вам нужен другой контроллер (или другой набор контроллеров).

Метод обновления - это все, что вам нужно. Если вы действительно хотите перейти к методу show после неудачного обновления (хотя я не знаю почему), измените вызов render edit в блоке в методе update после сбоя обновления.

Кажется, ваша настоящая проблема в том, что в окне редактирования не отображаются ошибки. Хотя созданный скаффолдом вид должен это делать, возможно, вы его изменили.

В случае, если вы пропустили его, вы также можете воспользоваться этой скринкастом:

http://railscasts.com/episodes/196-nested-model-form-part-1

0 голосов
/ 26 марта 2012

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

Urdxxx::Application.routes.draw do
  devise_for :members

  resources :posts do
    collection do
     post :update_comment
    end
  end

  root :to => 'posts#index'

<p> Have your say </p>
<%= form_for :post, :url => {:action => 'update_comment'} do |p| %>
  <%= p.fields_for :comments do |c| %>
     <!-- Following 3 lines saved my life -->
      <% if c.object.new_record? %>
        <%= c.text_area :content, :rows => 4 %>
        <%= c.hidden_field :member_id, value: current_member.id %>
      <% end %>
   <% end %>
   <%= p.submit "Reply" %>
<% end %>
...