rubí en los carriles de filtrado v2.2 pg_search_scope

votos
46

Estoy muy nuevo en Ruby on Rails y necesito ayuda para saber cómo modificar una consulta db existente. Estoy usando versiones antiguas, que no puedo actualizar: Rubí 2.2.3p173, y Rails 4.0.2.

Quiero filtrar los resultados de la consulta existentes para eliminar registros que no tienen ningún vídeo. La jerarquía del modelo que pienso es: artista, AlbumGroup, álbum, pista, vídeo.

Para aclarar: Quiero artistas con al menos 1 de vídeo, desde la asociación modelo de artista-> AlbumGroup-> álbumes->> TRACKS- vídeos (no Artist-> videos).

La consulta existente está contenida en el modelo del 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

Quiero añadir algo como lo siguiente para filtrar los registros que no tienen ningún vídeo: (a) la consulta:

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

O el modelo del artista tal vez ?:

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

El otro tipo de código para los diferentes modelos es el siguiente:

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 el 07/11/2017 a las 11:20
por usuario
En otros idiomas...                            


2 respuestas

votos
0

De ActiveRecord has_manyy belongs_tométodos le dan la capacidad para definir ámbitos directamente en la asociación. De esta manera, se puede personalizar el SQL que se genera cuando se acceda a la asociación.

digamos que quería definir un ámbito en el modelo de artista que devuelve todos los artistas que tienen vídeos cero. En los carriles 5, para encontrar todos los artistas que no tienen vídeos, puede utilizarleft_outer_joins

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

Otra buena solución es utilizar includesla siguiente manera:

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

Usted puede elegir el que más le guste!

Espero que ayudó.

Respondida el 07/11/2017 a las 12:12
fuente por usuario

votos
0

Gracias Gabriel, ¡Tengo una consulta SQL en bruto a artists_controller.rb, que se parece a:

  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
Respondida el 08/11/2017 a las 10:42
fuente por usuario

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