1

在我的應用程序,我有一個評論系統,主要是基於此railscast。現在在我的模型中,我將to_param更改爲隨機字符串,因此該ID不在url中。但是那樣就打破了評論。Rails多態評論與永久鏈接/令牌網址

status.rb

class Status < ActiveRecord::Base 
    attr_accessible :content, :member_id, :document_attributes, :permalink 
    belongs_to :member 
    belongs_to :document 
    has_many :comments, as: :commentable, dependent: :destroy 

    before_create :make_it_permalink 

    accepts_nested_attributes_for :document 

    def to_param 
     permalink 
    end 

    private 

    def make_it_permalink 
     # this can create permalink with random 12 digit alphanumeric 
     self.permalink = SecureRandom.hex(12) 
    end 

end 

statuses_controller.rb

class StatusesController < ApplicationController 

before_filter :authenticate_member!, only: [:index, :new, :create, :destroy] 
before_filter :find_member 

rescue_from ActiveRecord::RecordNotFound do 
    render file: 'public/404', status: 404, formats: [:html] 
end 

def index 
    @statuses = Status.order('created_at desc').page(params[:page]).per_page(21) 
    respond_to do |format| 
     format.html # index.html.erb 
     format.js 
    end 
end 

def show 
    @status = Status.find_by_permalink(params[:id]) 
    @commentable = @status 
    @comments = @commentable.comments.order('created_at desc').page(params[:page]).per_page(15) 
    @comment = @commentable.comments.new 
    respond_to do |format| 
     format.html # show.html.erb 
     format.json { redirect_to profile_path(current_member) } 
    end 
end 

def new 
    @status = Status.new 
    @status.build_document 

    respond_to do |format| 
     format.html # new.html.erb 
     format.json { render json: @status } 
     format.js 
    end 
end 

def create 
    @status = current_member.statuses.new(params[:status]) 

    respond_to do |format| 
     if @status.save 
     @activity = current_member.create_activity(@status, 'created') 
     format.html { redirect_to :back } 
     format.json 
     format.js 
     else 
     format.html { redirect_to profile_path(current_member), alert: 'Post wasn\'t created. Please try again and ensure image attchments are under 10Mbs.' } 
     format.json { render json: @status.errors, status: :unprocessable_entity } 
     format.js 
     end 
    end 
end 

def destroy 
    @status = current_member.statuses.find(params[:id]) 
    @activity = Activity.find_by_targetable_id(params[:id]) 
    @commentable = @status 
    @comments = @commentable.comments 
    if @activity 
     @activity.destroy 
    end 
    if @comments 
     @comments.destroy 
    end 
    @status.destroy 

    respond_to do |format| 
     format.html { redirect_to profile_path(current_member) } 
     format.json { head :no_content } 
    end 
end 

private 

def find_member 
    @member = Member.find_by_user_name(params[:user_name]) 
end 

def find_status 
    @status = current_member.statuses.find_by_permalink(params[:id]) 
end 

end 

comments_controller.rb

class CommentsController < ApplicationController 

before_filter :authenticate_member! 
before_filter :load_commentable 
before_filter :find_member 

def index 
    redirect_to root_path 
end 

def new 
    @comment = @commentable.comments.new 
end 

def create 
    @comment = @commentable.comments.new(params[:comment]) 
    @comments = @commentable.comments.order('created_at desc').page(params[:page]).per_page(15) 
    @comment.member = current_member 
    respond_to do |format| 
     if @comment.save 
     format.html { redirect_to :back } 
     format.json 
     format.js 
     else 
     format.html { redirect_to :back } 
     format.json 
     format.js 
     end 
    end 
end 

def destroy 
    @comment = Comment.find(params[:id]) 
    respond_to do |format| 
     if @comment.member == current_member || @commentable.member == current_member 
     @comment.destroy 
     format.html { redirect_to :back } 
     format.json 
     format.js 
     else 
     format.html { redirect_to :back, alert: 'You can\'t delete this comment.' } 
     format.json 
     format.js 
     end 
    end 
end 

private 

# def load_commentable 
#  resource, id = request.path.split('/')[1,2] # photos/1/ 
#  @commentable = resource.singularize.classify.constantize.find(id) # Photo.find(1) 
# end 

# alternative option: 
def load_commentable 
    klass = [Status, Medium, Project, Event, Listing].detect { |c| params["#{c.name.underscore}_id"] } 
    @commentable = klass.find(params["#{klass.name.underscore}_id"]) 
end 

#def load_commentable 
# @commentable = params[:commentable_type].camelize.constantize.find(params[:commentable_id]) 
#end 

def find_member 
    @member = Member.find_by_user_name(params[:user_name]) 
end 

end 

Ť他的問題在於comments_controller中的load_commentable方法。我已經嘗試了一些方法的不同變體,但第二個對我的應用程序最爲有效,它在URL的ID已經存在時正在工作。但因爲我已改寫了to_param使用我的隨機永久鏈接評論停止工作,因爲它試圖找到id它等於permalink。因爲它似乎試圖找到通過URL的ID,我如何通過實際的ID,而不是永久或我怎麼覺得commentable通過它的永久鏈接,而不是ID的?

回答

1

這是很難說,如果你的PARAM永遠是id的值或總是固定鏈接,或有時會一個ID,有時一個固定鏈接。

如果它永遠是一個固定鏈接,然後執行:

@commentable = klass.find_by_permalink(params["#{klass.name.underscore}_id"]) 

代替

@commentable = klass.find(params["#{klass.name.underscore}_id"]) 

如果有時ID,有時等,那麼你需要做的邏輯,以確定哪些是基於班級需要。

+0

謝謝。它再次正常工作,它們將永遠是永久鏈接,所以這就是我所需要的。 – iamdhunt