Реализован метод tagged_with, возвращающий все микросообщения - PullRequest
0 голосов
/ 27 января 2019

Я следовал руководству Hartl, чтобы создать ToDoList с системой тегов, также с помощью этого словесного руководства и RailsCast Tutorial .Однако я не очень понимаю, как система тегов работает с точки зрения фильтрации, поэтому я просто скопировал ее и импровизировал.Мое лучшее предположение состоит в том, что он должен использовать метод tagged_with, но консольный тест по-прежнему отображает все микросообщения.

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

До homepage

После wrong filter

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

Started GET "/tags/try2" for 127.0.0.1 at 2019-01-27 17:33:53 +0800
Processing by MicropostsController#index as HTML
  Parameters: {"tag"=>"try2"}
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 101], ["LIMIT", 1]]
  ↳ app/helpers/sessions_helper.rb:10
  Tag Load (0.3ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."name" = $1 LIMIT $2  [["name", "try2"], ["LIMIT", 1]]
  ↳ app/models/micropost.rb:13

  Rendering microposts/index.html.erb within layouts/application
   (0.6ms)  SELECT COUNT(*) FROM "microposts" INNER JOIN "taggings" ON "microposts"."id" = "taggings"."micropost_id" WHERE "taggings"."tag_id" = $1  [["tag_id", 10]]
  ↳ app/views/microposts/index.html.erb:2

  Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = $1 ORDER BY "microposts"."created_at" DESC  [["user_id", 101]]
  ↳ app/views/microposts/index.html.erb:3

  Tag Load (0.3ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."micropost_id" = $1  [["micropost_id", 62]]
  ↳ app/views/microposts/index.html.erb:5

  ##The taggings.micropost_id = $1 for some reason here
  ##It's strange why the next even tag loads again for the 2nd time, when there are only 2 tags

  Tag Load (0.3ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."micropost_id" = $1  [["micropost_id", 61]]
  ↳ app/views/microposts/index.html.erb:5
  Rendered microposts/index.html.erb within layouts/application (7.1ms)
  Rendered layouts/_rails_default.html.erb (58.5ms)
  Rendered layouts/_shim.html.erb (0.3ms)
  Rendered layouts/_header.html.erb (0.8ms)
  Rendered layouts/_footer.html.erb (1.3ms)
Completed 200 OK in 96ms (Views: 84.1ms | ActiveRecord: 2.4ms)

Вот мой код контроллера:

MicropostsController

class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:index, :show, :create, :destroy]
  before_action :correct_user,   only: :destroy

  def index
    @microposts = current_user.microposts
    @microposts = @microposts.tagged_with(params[:tag]) if params[:tag]
    @microposts = @microposts.paginate(page: params[:page])
  end

  def show
    @micropost = Micropost.find(params[:id])
  end


  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'static_pages/home'
    end
  end

  def destroy
    @micropost.destroy
    flash[:success] = "You have deleted a task!"
    redirect_to request.referrer || root_url
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content, :tag_list, :tag, 
        {tag_ids: [] }, :tag_ids)
    end

    def correct_user
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to root_url if @micropost.nil?
    end
end

SessionsController

class SessionsController < ApplicationController

  def new
  end

  def create
    @user = User.find_by(email: params[:session][:email].downcase)
    if (@user && @user.authenticate(params[:session][:password]))
      log_in @user
      flash[:success] = "Welcome back, #{@user.name}!"
      params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
      redirect_back_or root_path
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

  def destroy
    log_out if logged_in?
    redirect_to root_url
  end
end

StaticPagesController

class StaticPagesController < ApplicationController
  def home
    if logged_in?
      @new_micropost = Micropost.new
      @feed_items = current_user.microposts.paginate(page: params[:page]) 
    end 
  end

  def help
  end

  def about
  end

  def contact
  end
end

UsersController

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update, :destroy]
  before_action :correct_user,   only: [:edit, :update]
  before_action :admin_user,     only: [:destroy]


  def show
    @user = User.find(params[:id])
    @microposts = @user.microposts.paginate(page: params[:page])
  end

  def new
    @user = User.new
  end

  def index
    @users = User.paginate(page: params[:page])
  end


  def create
   @user = User.new(user_params)
   if @user.save
     log_in @user
     flash[:info] = "Welcome to the to-do app, #{@user.name}"
     redirect_to @user
   else
     render 'new'
   end
  end

  def admin
    @users = User.paginate(page: params[:page])
  end

  def destroy
    a = User.find(params[:id]).name
    User.find(params[:id]).destroy
    flash[:success] = "#{a} has been deleted!"
    redirect_to users_url
  end

  def admin_user
    redirect_to(root_url) unless current_user.admin?
  end

 def edit
   @user = User.find(params[:id])
 end

 def update
  @user = User.find(params[:id])
  if @user.update_attributes(user_params)
    flash[:success] = "Profile for @user.name has been updated"
    redirect_to(@user)
  else
    flash[:danger] = "Update Failed."
    render 'edit'
  end
end

  private
    def user_params
      params.require(:user).permit(:name, :email, :password,
                                  :password_confirmation, :admin)
    end
    def logged_in_user
      unless logged_in?
        store_location
        flash[:danger] = "You are not logged in. Please log in."
        redirect_to login_url
      end
    end

    def correct_user
      @user = User.find(params[:id])
      if !current_user?(@user)
        flash[:danger] = "You are not authorized to visit this page."
        redirect_to(root_url)
      end
    end
  end

microposts / index.html.erb

<h1>Filtered Tasks</h1>
<%= will_paginate %>
  <% @current_user.microposts.each do |micropost| %>
    <p><%= truncate(micropost.content, length: 50) %></p>
    <p><small>Tags: <%= raw micropost.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %></small></p>
        <span class="timestamp">
            Posted <%= time_ago_in_words(micropost.created_at) %> ago.
            <% if current_user?(micropost.user) %>
              <%= link_to "Done", micropost_path(micropost), method: :delete, data: { confirm: "Keep up the good work!" } %>
            <% end %>
        </span>
        <br><br>
    <% end %>
<%= will_paginate %>

Модель микросообщений

class Micropost < ApplicationRecord
  belongs_to :user
  has_many :taggings
  has_many :tags, through: :taggings, :dependent => :delete_all
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :content, presence: true, length: {maximum: 140 }
  attr_accessor :tag_list



  def self.tagged_with(name)
    Tag.find_by!(name: name).microposts
  end

  def self.tag_counts
    Tag.select('tags.*, count(taggings.tag_id) as count')
    .joins(:taggings).group('taggings.tag_id')
  end

  def tag_list
    tags.map(&:name).join(', ')
  end

  def tag_list=(names)
    self.tags = names.split(',').map do |n|
      Tag.where(name: n.strip).first_or_create!
    end
  end
end

Кто-нибудь знает, как работает система тегирования и, в частности, почему tagged_with возвращает все микросообщения?Сообщите мне, если нужна дополнительная информация.Большое спасибо заранее.

1 Ответ

0 голосов
/ 27 января 2019

Я бы порекомендовал вам использовать проппер-тэг, вместо того, чтобы реализовывать его вручную, отметьте акты-как-теги-он, у него уже есть метод tagged_with https://github.com/mbleigh/acts-as-taggable-on/blob/0082724158e2f80ddbce095a97afd990a004bf26/lib/acts_as_taggable_on/taggable/core.rb#L103, и вы получите намного меньше головных болей. Я предполагаю, что драгоценный камень был построен вокруг этого RailSast, и Railscast является старым, единственным ограниченным для этого примера, у этого камня есть больше особенностей.

Проблема в том, что ваш метод tagged_with не заботится о предыдущих областях: вы выбрасываете их с помощью метода класса Tag, а не строите запрос с использованием текущей области.

def self.tagged_with(name)
  Tag.find_by!(name: name).microposts
end

ActsAsTaggableOn обрабатывает это правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...