2012-04-01 7 views
1

So habe ich ein Self-Joining-Modell definiert. Im Grunde ein Post in einem Forum und ein parent_post, zu dem es gehört.Selbst beitreten ActiveRecord, Parent_Post_ID und mich

class Post < ActiveRecord::Base 
    has_many :replies, :class_name => "Post" 
    belongs_to :thread, :class_name => "Post", :foreign_key => "parent_post_id" 
end 

Das scheint grundsätzlich gesund. Ich habe eine neue RESTful-Route für die Antwortaktion und eine Aktion und Ansicht erstellt.

Routen:

resources :forums do 
    resources :posts do 
     member do 
     get 'reply' 
     end 
    end 
    end 

Die Ebenenansicht und die Regelung scheint, ich bin zu sein, wo bis abgespritzt zu werden.

def reply 
    @forum = Forum.find(params[:forum_id]) 
    @post = @forum.posts.build 
    @post.thread = @forum.posts.find(params[:id]) 
    @post.title = "RE: #{@post.thread.title}" 
end 

def create 
    @forum = Forum.find(params[:forum_id]) 
    @post = @forum.posts.build(params[:post]) 
    @post.user = current_user 
    if @post.save 
    redirect_to forum_post_path(@forum, @post), notice: 'Post was successfully created.' 
    else 
    render action: "new" 
    end 
end 

Und in der View-Schicht erzeugt Ich habe nur versucht, das gleiche Gerüst verwenden Teil bilden ich bin für die Standard neue und bearbeiten Aktionen verwenden.

#reply.html.erb 
<%= render :partial => 'form' %> 

#_form.html.erb 
<%= form_for [@forum,@post], :html => { :class => 'form-horizontal' } do |f| %> 
    <fieldset> 
    <legend><h1>New Thread</h1></legend> 

    <div class="control-group"> 
     <%= f.label :title, :class => 'control-label' %> 
     <div class="controls"> 
     <%= f.text_field :title, :class => 'text_field span9' %> 
     </div> 
    </div> 
     <div class="control-group"> 
     <%= f.label :body, :class => 'control-label' %> 
     <div class="controls"> 
     <%= f.text_area :body, :class => 'text_area span9' %> 
     </div> 
    </div> 
    <div class="form-actions"> 
     <%= f.submit 'Submit', :class => 'btn btn-primary' %> 
     <%= link_to 'Cancel', forum_posts_path(@forum), :class => 'btn' %> 
    </div> 
    </fieldset> 
<% end %> 

Allerdings ist die parent_post_id verloren, wenn ich den Posten bin zu schaffen und es wird auf Null gesetzt zu werden. Muss ich eine andere Aktion erstellen? Gibt es eine andere Möglichkeit, den Thread zu setzen? Irgendeine dritte Sache?

Antwort

0

Dies funktioniert:

Antworten Aktion:

@forum = Forum.find(params[:forum_id]) 
@post = @forum.posts.build 
@post.thread = @forum.posts.find(params[:id]) 
@post.title = "RE: #{@post.thread.title}" 

Dann ist diese zu Ihrer Ansicht hinzufügen

<%= f.hidden_field :parent_post_id, @post.thread.id %> 

BTW Ich Frage, ob Sie eine benutzerdefinierte reply Methode im Gegensatz zu integrierten RESTful Methoden benötigen, aber das sollte Ihr Problem beheben und das war nicht wirklich Ihre Frage.

+0

Mein Denken war, dass ich zwischen der Schaffung eines neuen Threads gegenüber einer Antwort unterscheiden würde, aber das mag falsch sein, sollte ich einfach diese Logik zu neuen hinzufügen und es einen Tag nennen? – DVG

+1

Es scheint mir, dass der einzige Unterschied ist, dass eine (Antwort Post) eine Parent_id und die andere (neue Post) wird nicht. Bei beiden wird lediglich ein neuer Beitrag erstellt. Wenn die Unterschiede komplizierter werden, können Sie einen Thread-Controller in Erwägung ziehen. Mein Hauptvorschlag war, sich selbst zu fragen, wie wichtig es ist, REST-konforme Routen mit eigenen Methoden zu erweitern. Wenn Sie sich dabei befinden, müssen Sie möglicherweise die Notwendigkeit eines anderen Controllers in Betracht ziehen. –

+0

Wow, die 'thread'-Controller-Idee ließ mich tatsächlich an eine völlig gegensätzliche Idee denken. Warum nicht ein "Antwort" Controller? Ich poste was ich denke. – Azolo

0

hinzufügen

<%= hidden_field_tag :forum_id , @forum.id %> 

zum Formular

0

Also im Grunde, wenn Sie auf die Posts#create Aktion sind einreichen Sie einreichen eine URL, die so etwas wie dieses /forum/1/posts sieht, die die parent_post_id aus der URL entfernt. Da Sie das parent_post_id verwenden, um diese URL zu erstellen, benötigen Sie einen Weg zu POST damit.

Mein Vorschlag ist eine POST zu einer reply Ressource, die in der posts Ressource geschachtelt ist.
(dh POST /forums/1/posts/1/reply)

Also vielleicht so etwas wie dieses

resources :forums do 
    resources :posts do 
    # :show is actually just pointing to a form 
    resource :reply, :only => [:show, :create], 
        :controller => 'reply' #otherwise gets routed to 'replies' 
    end 
end 

So würden Sie brauchen auch ein ReplyController aber das wäre im Grunde auf Ihre Post-Controller mit ein paar Änderungen Ihrer reply Methode entsprechen.

def show 
    @forum = Forum.find(params[:forum_id]) 
    @post = @forum.posts.find(params[:post_id]) 
    @reply = @forum.posts.build 
    @reply.thread = @post 
    @reply.title = "RE: #{@post.thread.title}" 
end 

def create 
    @forum = Forum.find(params[:forum_id]) 
    @post = @forum.posts.find(params[:post_id]) 
    @reply = @forum.posts.build(params[:reply]) 
    @reply.thread = @post 
    @reply.user = current_user 
    if @reply.save 
    redirect_to forum_post_path(@forum, @post), notice: 'Reply was successfully created.' 
    else 
    render action: "show" 
    end 
end 

Das größte Problem wäre, dass Sie zu abstrahieren Ihre Post Felder aus form for Block haben würde. Das liegt daran, dass die URL, die Sie versuchen, zu POST wird anders sein.Aber es sollte nicht so schlimm sein, nur so etwas wie dies zu tun:

Antwort/show.html.erb

<%= 
    form_for @reply, :url => forum_post_reply_path(@forum, @post), 
        :html => { :class => 'form-horizontal' } do |builder| 
%> 
    <fieldset> 
    <legend><h1>New Reply</h1></legend> 

    <%= render "posts/post_fields", :f => builder %> 

    <div class="form-actions"> 
     <%= builder.submit 'Submit', :class => 'btn btn-primary' %> 
     <%= link_to 'Cancel', forum_post_path([@forum, @post]), :class => 'btn' %> 
    </div> 
    </fieldset> 

<% end %> 

Beiträge/_form.html.erb

<%= form_for [@forum,@post], :html => { :class => 'form-horizontal' } do |builder| %> 
    <fieldset> 
    <legend><h1>New Thread</h1></legend> 

    <%= render "post_fields", :f => builder %> 

    <div class="form-actions"> 
     <%= builder.submit 'Submit', :class => 'btn btn-primary' %> 
     <%= link_to 'Cancel', forum_posts_path(@forum), :class => 'btn' %> 
    </div> 
    </fieldset> 
<% end %> 

Beiträge/_post_fields.html.erb

Hinweis: Es gibt wahrscheinlich eine bessere Möglichkeit, die Routen zu deklarieren als ich, aber ich weiß es nicht wirklich.