rubis sur des rails de filtrage pg_search_scope v2.2

voix
46

Je suis très nouveau pour Ruby on Rails et j'ai besoin d'aide pour déterminer comment modifier une requête existante db. J'utilise les anciennes versions, que je ne peux pas mettre à jour: Ruby 2.2.3p173 et Rails 4.0.2.

Je veux filtrer les résultats de la requête pour supprimer les enregistrements existants qui n'ont pas de vidéos. La hiérarchie de modèle que je pense est: Artiste, AlbumGroup, Album, Piste, Vidéo.

Pour clarifier: Je veux des artistes avec au moins 1 vidéo, de l'association modèle artiste-> AlbumGroup-> Albums->> tracks- vidéos (non artiste-> Vidéos).

La requête existante est contenue dans le modèle Artiste:

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

Je veux ajouter quelque chose comme ce qui suit pour filtrer les enregistrements qui n'ont pas de vidéos: (à la requête):

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

Ou le modèle de l'artiste peut-être ?:

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

L'autre code pour les différents modèles est ci-dessous:

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
Créé 07/11/2017 à 14:20
utilisateur
Dans d'autres langues...                            


2 réponses

voix
0

De ActiveRecord has_manyet belongs_tométhodes vous donnent la possibilité de définir des portées directement sur l'association. De cette façon, vous pouvez personnaliser le SQL qui est généré lorsque vous accédez à l'association.

disons que vous vouliez définir une portée sur le modèle de l'artiste qui retourne tous les artistes qui ont des vidéos zéro. Dans Rails 5, pour trouver tous les artistes qui ont pas de vidéos, vous pouvez utiliserleft_outer_joins

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

Une autre bonne solution consiste à utiliser includescomme ceci:

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

Vous pouvez choisir celui que vous aimez le plus!

Espérons que cela a aidé.

Créé 07/11/2017 à 15:12
source utilisateur

voix
0

Merci Gabriel, je l'ai ajouté une requête SQL brute à artists_controller.rb, qui ressemble à:

  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
Créé 08/11/2017 à 13:42
source utilisateur

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