2016-10-07 1 views
1

Il semble que le filtre ne prenne pas en compte le contenu des tables de traduction (Globalize).Filterrific et globaliser

Y a-t-il un moyen de rechercher des tables de traduction? Ma configuration fonctionne parfaitement si le contenu est dans le modèle actuel. Cependant, une fois que les champs sont vides et seulement entrés dans la table de traduction, aucun résultat n'est affiché (évidemment).

Mon modèle:

class Manual < ApplicationRecord 
    translates :title, :content, :teaser, :slug 

    extend FriendlyId 
    friendly_id :title, :use => :globalize 

    belongs_to :user 
    belongs_to :support_category 
    has_many :manual_faqs 
    has_many :faqs, :through => :manual_faqs 

    validates :title, presence: true 
    validates :content, presence: true 
    validates :user_id, presence: true 

    update_index('manuals#manual') { self } 

    filterrific(
     default_filter_params: { sorted_by: 'created_at_desc' }, 
     available_filters: [ 
      :sorted_by, 
      :search_query, 
      :with_user_id, 
      :with_created_at_gte 
     ] 
) 

    scope :with_user_id, lambda { |user_ids| 
    where(user_id: [*user_ids]) 
    } 

    scope :search_query, lambda { |query| 
    # Searches the students table on the 'first_name' and 'last_name' columns. 
    # Matches using LIKE, automatically appends '%' to each term. 
    # LIKE is case INsensitive with MySQL, however it is case 
    # sensitive with PostGreSQL. To make it work in both worlds, 
    # we downcase everything. 
    return nil if query.blank? 

    # condition query, parse into individual keywords 
    terms = query.downcase.split(/\s+/) 

    # replace "*" with "%" for wildcard searches, 
    # append '%', remove duplicate '%'s 
    terms = terms.map { |e| 
     ('%' + e.gsub('*', '%') + '%').gsub(/%+/, '%') 
    } 
    # configure number of OR conditions for provision 
    # of interpolation arguments. Adjust this if you 
    # change the number of OR conditions. 
    num_or_conds = 2 
    where(
     terms.map { |term| 
      "(LOWER(manuals.title) LIKE ? OR LOWER(manuals.content) LIKE ?)" 
     }.join(' AND '), 
     *terms.map { |e| [e] * num_or_conds }.flatten 
    ) 
    } 

    scope :sorted_by, lambda { |sort_option| 
    # extract the sort direction from the param value. 
    direction = (sort_option =~ /desc$/) ? 'desc' : 'asc' 
    case sort_option.to_s 
     when /^created_at_/ 
     # Simple sort on the created_at column. 
     # Make sure to include the table name to avoid ambiguous column names. 
     # Joining on other tables is quite common in Filterrific, and almost 
     # every ActiveRecord table has a 'created_at' column. 
     order("manuals.created_at #{ direction }") 
     else 
     raise(ArgumentError, "Invalid sort option: #{ sort_option.inspect }") 
    end 
    } 

    scope :created_at_gte, lambda { |reference_time| 
    where('manuals.created_at >= ?', reference_time) 
    } 

    def self.options_for_sorted_by 
    [ 
     ['Date received (newest first)', 'created_at_desc'], 
     ['Date received (oldest first)', 'created_at_asc'] 
    ] 
    end 
end 

Mon contrôleur:

def index 
    @filterrific = initialize_filterrific(
     Manual, 
     params[:filterrific], 
     select_options: { 
      sorted_by: Manual.options_for_sorted_by, 
      with_user_id: User.options_for_select 
     } 
    ) or return 

    @manuals = @filterrific.find.page(params[:page]) 

    respond_to do |format| 
     format.html 
     format.js 
    end 

    rescue ActiveRecord::RecordNotFound => e 
    # There is an issue with the persisted param_set. Reset it. 
    puts "Had to reset filterrific params: #{ e.message }" 
    redirect_to(reset_filterrific_url(format: :html)) and return 
    #respond_with(@references) 
    end 

Répondre

1

Je ne sais pas filterrific du tout, mais je ne sais Globalize, et depuis filterrific est basée sur AR oscilloscopes il devrait être tout simplement une question de rejoindre la table de traduction pour obtenir des résultats à afficher.

Voici votre search_query champ modifié pour rejoindre et rechercher la table des traductions jointes (sans les commentaires pour plus de clarté):

scope :search_query, lambda { |query| 
    return nil if query.blank? 

    terms = query.downcase.split(/\s+/) 

    terms = terms.map { |e| 
    ('%' + e.gsub('*', '%') + '%').gsub(/%+/, '%') 
    } 

    num_or_conds = 2 
    where(
    ('(LOWER(manual_translations.title) LIKE ? OR'\ 
    ' LOWER(manual_translations.content) LIKE ?)' * (terms.count)).join(' AND '), 
    *terms.map { |e| [e] * num_or_conds }.flatten 
).with_translations 
} 

Avis que j'ai seulement changé deux choses: (1) J'ai joint en annexe with_translations, une méthode described in this SO answer qui joint les traductions pour les paramètres régionaux en cours et (2) j'ai permuté la table manuals pour la table manual_translations dans la requête.

Donc, si vous appelez cette requête dans les paramètres régionaux anglais:

Manual.search_query("foo") 

vous obtenez ce SQL:

SELECT "manuals".* FROM "manuals" 
INNER JOIN "manual_translations" ON "manual_translations"."manual_id" = "manuals"."id" 
WHERE (LOWER(manual_translations.title) LIKE '%foo%' OR 
     LOWER(manual_translations.content) LIKE '%foo%') 
     AND "manual_translations"."locale" = 'en'" 

Notez que with_translations est marquage automatiquement sur cette manual_translations.locale = 'en' de sorte que vous filtrer uniquement les résultats en votre locale, que je suppose est ce que vous voulez. Faites-moi savoir si cela fonctionne pour vous.

+0

Merci Chris! Fonctionne comme un charme! –

+0

Super! J'ai remarqué que la requête 'where' avait plus de complexité que nécessaire, donc elle l'a simplifiée un peu (voir ci-dessus). –

+0

Désolé, j'ai eu une erreur, je l'ai réparée. Devrait fonctionner maintenant, légèrement plus court. –