ruby on rails filtragem pg_search_scope v2.2

votos
46

Eu sou muito novo para Ruby on Rails e eu preciso de ajuda para descobrir como alterar uma consulta db existente. Estou usando versões antigas, que eu não posso atualizar: Rubi 2.2.3p173 e Rails 4.0.2.

Eu quero filtrar os resultados da consulta existentes para remover registros que não têm nenhum vídeo. A hierarquia do modelo eu acho que é: Artist, AlbumGroup, Album, Track, Vídeo.

Para esclarecer: eu quero artistas com pelo menos 1 vídeo, a partir da associação modelo de artista-> AlbumGroup-> álbuns-> tracks-> vídeos (não ARTISTA> vídeos).

A consulta existente está contida no modelo do artista:

require_dependency tagging
require_dependency similar
class Artist < ActiveRecord::Base
  has_many :images, dependent: :destroy
  has_many :taggings, dependent: :destroy
  has_many :artforms, through: :taggings
  has_many :similars, foreign_key: similar_id, dependent: :destroy
  has_many :similar_artists, through: :similars, source: :similar_to
  has_many :reverse_similars, foreign_key: similar_to_id, class_name: Similar, dependent: :destroy
  has_many :similar_to_artists, through: :reverse_similars, source: :similar
  has_many :memberships, foreign_key: member_id, dependent: :destroy
  has_many :groups, through: :memberships, source: :membership
  has_many :group_members, foreign_key: membership_id, class_name: Membership, dependent: :destroy
  has_many :members, through: :group_members, source: :member
  has_many :users, through: :followed_artists
  has_many :videos, dependent: :destroy
  has_many :audios, dependent: :destroy
  has_many :metrics, through: :audios
  has_many :releases, foreign_key: 'artist_id', class_name: AlbumGroup
  has_many :albums
  has_many :collaborations
  has_many :album_groups, through: :collaborations
  mount_uploader :mugshot, MugshotUploader
  include PgSearch
  pg_search_scope :for_name,
      against: :name,
      using: { tsearch: {threshold: '1', dictionary: 'simple', tsvector_column: 'tsv_name', prefix: true, normalization: 2}},
      ranked_by: (artists.popularity / 50 * :tsearch) + :tsearch
end

Quero acrescentar algo como o seguinte para filtrar os registros que não têm nenhum vídeo: (para a consulta):

if: artist.releases.albums.tracks.videos.count > 1

Ou o modelo de artista talvez ?:

scope :valid, -> {where(video_count > 1)}

O outro código para os diferentes modelos está abaixo:

class AlbumGroup < ActiveRecord::Base
  belongs_to :artist
  has_many :collaborations
  has_many :artists, through: :collaborations
  has_many :albums
  has_many :taggings, dependent: :destroy
  has_many :artforms, through: :taggings
  mount_uploader :artwork, MugshotUploader
  def as_json options={}
    {
      id: id,
      title: title
    }
  end
end

class Album < ActiveRecord::Base
  belongs_to :album_group
  belongs_to :artist
  has_many :tracks
end

class Track < ActiveRecord::Base
  has_many :playlist_tracks, dependent: :destroy
  has_many :playlists, through: :playlist_tracks
  belongs_to :audio
  belongs_to :video
  has_many :videos
  has_many :audios
  has_many :taggings, dependent: :destroy
  has_many :artforms, through: :taggings
  belongs_to :album
  belongs_to :artist
  default_scope order: position ASC
  after_save :cache_columns

  def cache_columns
    if image_url.nil?
      img = album.album_group.artwork_url(:tiny)
      unless img.nil?
        update_column(:image_url,img)
      end
    end
    if artist_name.nil?
      if artist_id
        name = Artist.find(artist_id).name
        update_column(:artist_name,name)
      end
    end
    if album_name.nil?
      if album_id
        title = Album.find(album_id).title
        update_column(:album_name,title)
      end
    end
  end
end

class Video < ActiveRecord::Base
  belongs_to :artist
  belongs_to :event
  belongs_to :track
  has_many :tracks
  has_many :playlists, through: :tracks, order: tracks.position ASC
  scope :valid, -> {where(flag_count < 2).order(score DESC) }
  scope :flagged, -> {where(flag_count > ?, 1) }
#   validates :url, uniqueness: {scope: :artist_id}
end
Publicado 07/11/2017 em 14:20
usuário
Em outras línguas...                            


2 respostas

votos
0

Do ActiveRecord has_manye belongs_tométodos de dar-lhe a capacidade de definir escopos diretamente na associação. Dessa forma, você pode personalizar o SQL que é gerado quando você acessar a associação.

digamos que você queria definir um escopo no modelo artista que retorna todos os artistas que têm de zero vídeos. No Rails 5, para encontrar todos os artistas que não tem vídeos, você pode usarleft_outer_joins

class Artist < ActiveRecord::Base
  has_many :videos
  scope :with_zero_videos, -> { left_outer_joins(:videos).where(videos: {id: nil}) }
end

Outra boa solução é usar includesassim:

Artist.includes(:videos).where(videos: { videos_id: nil })

Você pode escolher o que você mais gosta!

Espero que isso ajudou.

Respondeu 07/11/2017 em 15:12
fonte usuário

votos
0

Graças Gabriel, eu adicionei uma consulta SQL cru para artists_controller.rb, que se parece com:

  def index
    #artists = Artist.for_name(params[:name])
    artists = Artist.find_by_sql ["SELECT artists.*, ((artists.popularity / 50 * (ts_rank((artists.tsv_name), (to_tsquery('simple', ''' ' || ? || ' ''' || ':*')), 2))) + (ts_rank((artists.tsv_name), (to_tsquery('simple', ''' ' || ? || ' ''' || ':*')), 2))) AS pg_search_rank FROM artists " +
      "JOIN album_groups on (artists.id = album_groups.artist_id) " +
      "JOIN tracks on (tracks.album_group_id = album_groups.id) " +
      "JOIN videos on (videos.track_id = tracks.id) " +
      "WHERE (((artists.tsv_name) @@ (to_tsquery('simple', ''' ' || ? || ' ''' || ':*')))) " +
      "GROUP BY artists.id " +
      "ORDER BY pg_search_rank DESC, artists.id ASC", params[:name], params[:name], params[:name]]
    render json: artists, each_serializer: SimpleArtistSerializer
  end
Respondeu 08/11/2017 em 13:42
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more