两张关联表的实现方式 - tianlu1677/tianlu1677.github.io GitHub Wiki

假设我们这里有两个关联的表 Article和comments文章 因为要实现两个关联,嵌套,因此需要记录一下。

resources :articles do
    get 'category_index', on: :collection
    resources :comments do
      member do
        post 'useful'
        post 'useless'
      end
    end
  end
- category_index_articles_path	GET	/articles/category_index(.:format)	articles#category_index
- useful_article_comment_path	POST	/articles/:article_id/comments/:id/useful(.:format)	comments#useful
- useless_article_comment_path	POST	/articles/:article_id/comments/:id/useless(.:format)	comments#useless
- article_comments_path	GET	/articles/:article_id/comments(.:format)	comments#index
POST	/articles/:article_id/comments(.:format)	comments#create
- new_article_comment_path	GET	/articles/:article_id/comments/new(.:format)	comments#new
- edit_article_comment_path	GET	/articles/:article_id/comments/:id/edit(.:format)	comments#edit
- article_comment_path	GET	/articles/:article_id/comments/:id(.:format)	comments#show

首先是article.rb

class Article
  include Mongoid::Document
  include Mongoid::Timestamps


  field :title,        type:String        #文章标题
  field :category,     type:String      #所属类别
  field :content,      type:String         #内容

  has_and_belongs_to_many :career_paths
  has_many :comments

end

comment.rb

class Comment
  include Mongoid::Document
  include Mongoid::Timestamps

  field :content, type: String
  field :useful_count, type: Integer, default: 0
  field :useless_count, type: Integer, default: 0
  field :child_comments_count, type: Integer, default: 0
  field :voted_user, type: Array, default: []

  recursively_embeds_many # 自己嵌套自己
  belongs_to :user
  belongs_to :article

end

articles_controller.rb

class ArticlesController < FrontResourceController
  before_action :authenticate_user!, :forbidden_company_user!

  layout "person"

  def index
    @articles = current_user.career_path.articles
  end

  def show
    @article = Article.find(params[:id])
    @comments = @article.comments
  end

  def category_index
    @category_articles = Article.where(category: params[:category])
  end

end

comments_controller.rb

class CommentsController < FrontResourceController
  before_action :authenticate_user!, :forbidden_company_user!

  layout "person"

  def create
    @comment = current_user.comments.new
    @comment.article_id = params[:article_id]
    @comment.content = params[:comment][:content]
    @comment.save!
  end

  def edit
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
  end

  def update
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
    @comment.content = params[:comment][:content]
    @comment.save!
  end

  def useful
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
    unless @comment.voted_user.include? current_user.id
      @comment.inc(useful_count: 1)
      @comment.voted_user << current_user.id
      @comment.save
    end
  end

  def useless
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
    unless @comment.voted_user.include? current_user.id
      @comment.inc(useless_count: 1)
      @comment.voted_user << current_user.id
      @comment.save
    end
  end

  protected


  def permitted_params
    params.permit(:comment => [:content, :useful_count, :useless_count])
  end

  def comment_params
    params.permit(:comment => [:content, :useful_count, :useless_count])
  end

end

因为在文章中的显示部分

<% if resource.present? %>
    <div class="my-growth-article">
      <ol class="breadcrumb">
        <li><%= link_to "我的成长", articles_path %></li>
        <li><%= link_to resource.category, category_index_articles_path(category: resource.category) %></li>
        <li class="active"><%= resource.title %></li>
      </ol>
      <div class="panel panel-default">
        <div class="panel-body">
          <div class="blk-header custom-bg">
            <h3><%= resource.title %></h3>
          </div>

          <div class="article">
            <%= raw resource.content %>
          </div>

          <hr>

          <div class="reply clearfix">
            <div class="form-group">
              <label for="article-reply">我的评价</label>

              <div id="comment_form">
                <% comment = resource.comments.find_or_initialize_by(user_id: current_user.id) %>
                <% if comment.content.present? %>
                    <%= render "comments/show", article: resource, comment: comment %>
                <% else %>
                    <%= render "comments/form", article: resource, comment: comment %>
                <% end %>
              </div>
            </div>
          </div>


        </div>
        <!-- /.panel-body -->
      </div>
      <!-- /.panel -->

      <div class="blk-header">
        <h3>评价</h3>
      </div>
      <%= render "comments/index" %>
    </div>
<% end %>

comments/*.html.erb

form.html.erb

<%= simple_form_for [article, comment], remote: true do |f| %>
  <%= f.input :content, as: :text, label: false, input_html: {class: "form-control", rows: 5, maxlength: "500", placeholder: "留个脚印呗"} %>
  <%= f.submit class: "btn btn-lg btn-primary pull-right", id: "comment-submit-btn", value: "发送" %>
<% end %>

index.html.erb

<% if @comments.blank? %>
    还没有人评价过
<% else %>
<ul class="media-list comments">
  <% @comments.all.each do |comment| %>
  <li class="media">
          <%= image_tag(comment.user.try(:avatar_dynamic_url, :thumb), size: "50x50", class: "pull-left pic")%>
    <div class="media-body">
      <h5 class="media-heading"><span class="username"><%= comment.user.try(:username) %></span> <span class="date"><%= time_ago_in_words(comment.created_at) %>前</span></h5>
      <p><%= comment.content %></p>
      <div id="vote_comment_<%= dom_id(comment) %>">
        <%= render "comments/vote_comment", article: @article, comment: comment %>
      </div>
      <a href="#" class="vote-comment text-orange pull-right">回复(<%= comment.child_comments.count %>)</a>

      <div class="comments-reply">
        <div class="reply clearfix">
          <form action="" method="POST" role="form">
            <div class="form-group">
              <textarea name="article-reply" id="article-reply" cols="30" rows="5" maxlength="500" class="form-control" placeholder="请输入回复内容"></textarea>
            </div>
            <button type="submit" class="btn btn-lg btn-primary pull-right">发送</button>
          </form>
        </div>

        <!--<ul class="media-list">-->

          <!--<% 3.times do %>-->
              <!--<li class="media">-->
	      			<!--<span class="pull-left" href="#">-->
	      				<!--<img class="media-object" src="/assets/images/temp_user_avatar.jpg" alt="avatar">-->
	      			<!--</span>-->
                <!--<div class="media-body">-->
                  <!--<h5 class="media-heading"><span class="username">yangguangft</span> <span class="date">5 天前</span></h5>-->
                  <!--<p>真是个程序猿啊~~~以后自己不会变成这样啊。。。。</p>-->
                  <!--<p class="vote">-->
                    <!--<a href="#" class="up"><span class="glyphicon glyphicon-thumbs-up"></span>有用(251)</a>-->
                    <!--<a href="#" class="down"><span class="glyphicon glyphicon-thumbs-down"></span>没用(12)</a>-->
                  <!--</p>-->
                <!--</div>-->
              <!--</li>-->
          <!--<% end %>-->

        <!--</ul>-->

        <a href="#" class="btn btn-bg btn-block btn-lg">查看全部回复...</a>
      </div>

    </div>
  </li>
  <% end %>
  <li class="media">
	    <span class="pull-left" href="#">
	      <img class="media-object" src="/assets/images/temp_user_avatar.jpg" alt="avatar">
	    </span>
    <div class="media-body">
      <h5 class="media-heading"><span class="username">zhou307418603</span> <span class="date">11 天前</span></h5>
      <p>6分37的时候,我看到impl.js中定义的事getFeoLocation,难道不是getGeoLocation吗?为何最后还是成功了,函数名称就不对啊,初学者表示不理解。6分37的时候,我看到impl.js中定义的事getFeoLocation,难道不是getGeoLocation吗?为何最后还是成功了,函数名称就不对啊,初学者表示不理解。6分37的时候,我看到impl.js中定义的事getFeoLocation,难道不是getGeoLocation吗?为何最后还是成功了,函数名称就不对啊,初学者表示不理解。</p>
      <p class="vote">
        <a href="#" class="up"><span class="glyphicon glyphicon-thumbs-up"></span>有用(251)</a>
        <a href="#" class="down"><span class="glyphicon glyphicon-thumbs-down"></span>没用(12)</a>
        <a href="#" class="vote-comment text-orange pull-right">回复(12)</a>
      </p>
    </div>
  </li>
</ul>
<% end %>
<script>
    $(function () {
        $('.vote-comment').click(function (evt) {
            evt.preventDefault();
            var $content = $(this).closest('.vote').siblings('.comments-reply');
            if($(this).hasClass('active')) {
                $content.slideUp('600');
            } else {
                $content.slideDown('600');
            }
            $(this).toggleClass('active');
        });
    });
</script>

show.html.erb


<% if @comments.blank? %>
    还没有人评价过
<% else %>
<ul class="media-list comments">
  <% @comments.all.each do |comment| %>
  <li class="media">
          <%= image_tag(comment.user.try(:avatar_dynamic_url, :thumb), size: "50x50", class: "pull-left pic")%>
    <div class="media-body">
      <h5 class="media-heading"><span class="username"><%= comment.user.try(:username) %></span> <span class="date"><%= time_ago_in_words(comment.created_at) %>前</span></h5>
      <p><%= comment.content %></p>
      <div id="vote_comment_<%= dom_id(comment) %>">
        <%= render "comments/vote_comment", article: @article, comment: comment %>
      </div>
      <a href="#" class="vote-comment text-orange pull-right">回复(<%= comment.child_comments.count %>)</a>

      <div class="comments-reply">
        <div class="reply clearfix">
          <form action="" method="POST" role="form">
            <div class="form-group">
              <textarea name="article-reply" id="article-reply" cols="30" rows="5" maxlength="500" class="form-control" placeholder="请输入回复内容"></textarea>
            </div>
            <button type="submit" class="btn btn-lg btn-primary pull-right">发送</button>
          </form>
        </div>

        <!--<ul class="media-list">-->

          <!--<% 3.times do %>-->
              <!--<li class="media">-->
	      			<!--<span class="pull-left" href="#">-->
	      				<!--<img class="media-object" src="/assets/images/temp_user_avatar.jpg" alt="avatar">-->
	      			<!--</span>-->
                <!--<div class="media-body">-->
                  <!--<h5 class="media-heading"><span class="username">yangguangft</span> <span class="date">5 天前</span></h5>-->
                  <!--<p>真是个程序猿啊~~~以后自己不会变成这样啊。。。。</p>-->
                  <!--<p class="vote">-->
                    <!--<a href="#" class="up"><span class="glyphicon glyphicon-thumbs-up"></span>有用(251)</a>-->
                    <!--<a href="#" class="down"><span class="glyphicon glyphicon-thumbs-down"></span>没用(12)</a>-->
                  <!--</p>-->
                <!--</div>-->
              <!--</li>-->
          <!--<% end %>-->

        <!--</ul>-->

        <a href="#" class="btn btn-bg btn-block btn-lg">查看全部回复...</a>
      </div>

    </div>
  </li>
  <% end %>
  <li class="media">
	    <span class="pull-left" href="#">
	      <img class="media-object" src="/assets/images/temp_user_avatar.jpg" alt="avatar">
	    </span>
    <div class="media-body">
      <h5 class="media-heading"><span class="username">zhou307418603</span> <span class="date">11 天前</span></h5>
      <p>6分37的时候,我看到impl.js中定义的事getFeoLocation,难道不是getGeoLocation吗?为何最后还是成功了,函数名称就不对啊,初学者表示不理解。6分37的时候,我看到impl.js中定义的事getFeoLocation,难道不是getGeoLocation吗?为何最后还是成功了,函数名称就不对啊,初学者表示不理解。6分37的时候,我看到impl.js中定义的事getFeoLocation,难道不是getGeoLocation吗?为何最后还是成功了,函数名称就不对啊,初学者表示不理解。</p>
      <p class="vote">
        <a href="#" class="up"><span class="glyphicon glyphicon-thumbs-up"></span>有用(251)</a>
        <a href="#" class="down"><span class="glyphicon glyphicon-thumbs-down"></span>没用(12)</a>
        <a href="#" class="vote-comment text-orange pull-right">回复(12)</a>
      </p>
    </div>
  </li>
</ul>
<% end %>
<script>
    $(function () {
        $('.vote-comment').click(function (evt) {
            evt.preventDefault();
            var $content = $(this).closest('.vote').siblings('.comments-reply');
            if($(this).hasClass('active')) {
                $content.slideUp('600');
            } else {
                $content.slideDown('600');
            }
            $(this).toggleClass('active');
        });
    });
</script>

_vote_comment.html.erb

<p class="vote">
  <%= link_to useful_article_comment_path(article, comment), method: :post, remote: true do %>
    <span class="glyphicon glyphicon-thumbs-up"></span>有用(<%= comment.useful_count %>)
  <% end %>
  <%= link_to useless_article_comment_path(article, comment), method: :post, remote: true do %>
    <span class="glyphicon glyphicon-thumbs-down"></span>没用(<%= comment.useless_count %>)
  <% end %>

</p>

create.js.erb

$("#comment_form").html("");
$("#comment_form").html(<%= raw render("comments/show", article: @article, comment: @comment).inspect %>);

edit.js.erb

$("#comment_form").html("");
$("#comment_form").html(<%= raw render("comments/form", article: @article, comment: @comment ).inspect %>);

update.js.erb

$("#comment_form").html("");
$("#comment_form").html(<%= raw render("comments/show", article: @article, comment: @comment).inspect %>);

useful_js.erb

$("#vote_comment_<%= dom_id(@comment) %>").html(<%= raw render("comments/vote_comment", article: @article, comment: @comment.reload).inspect %>);
⚠️ **GitHub.com Fallback** ⚠️