#ruby-on-rails #ruby-on-rails-4
#ruby-on-rails #ruby-on-rails-4
Вопрос:
Мое действие show:
def show
# Multiple keywords
if current_user.admin?
@integration = Integration.find(params[:id])
else
@integration = current_user.integrations.find(params[:id])
end
@q = @integration.profiles.search(search_params)
@profiles = @q.result.where(found: true).select("profiles.*").group("profiles.id, profiles.email").includes(:integration_profiles).order("CAST( translate(meta_data -> '#{params[:sort_by]}', ',', '') AS INT) DESC NULLS LAST").page(params[:page]).per_page(20)
@profiles = @profiles.limit(params[:limit]) if params[:limit]
end
Здесь может быть много разных фильтров, будь то с помощью Ransacker, с параметрами [:limit] или другими. В конце у меня есть подмножество профилей.
Теперь я хочу пометить все эти профили, которые являются результатом поискового запроса.
Модель профилей:
def self.tagging_profiles
#Some code
end
Я хотел бы создать действие в том же контроллере, что и show, которое будет выполнять self.tagging_profiles
функцию @profiles
из действия show, учитывая, что эти профили были отфильтрованы.
def tagging
@profiles.tagging_profiles
end
Я хочу, чтобы пользователь мог выполнять поисковый запрос, иметь профили в представлении, а затем, если они будут удовлетворены, отмечать все из них, поэтому потребуется форма
Обновить:
Вот как я обошел это, не знаю, насколько это чисто, но здесь:
def show # Несколько ключевых слов
if current_user.admin?
@integration = Integration.find(params[:id])
else
@integration = current_user.integrations.find(params[:id])
end
@q = @integration.profiles.search(search_params)
@profiles = @q.result.where(found: true).select("profiles.*").group("profiles.id, profiles.email").includes(:integration_profiles).order("CAST( translate(meta_data -> '#{params[:sort_by]}', ',', '') AS INT) DESC NULLS LAST").page(params[:page]).per_page(20)
@profiles = @profiles.limit(params[:limit]) if params[:limit]
tag_profiles(params[:tag_names]) if params[:tag_names]
end
private
def tag_profiles(names)
@profiles.tagging_profiles
end
На мой взгляд, я создал форму, вызывающую self:
<%= form_tag(params.merge( :controller => "integrations", :action => "show" ), method: :get) do %>
<%= text_field_tag :tag_names %>
<%= submit_tag "Search", class: "btn btn-default"%>
<% end %>
Это лучший способ сделать это?
Комментарии:
1. Не могли бы вы уточнить свой вопрос?
2. @steel Я обновил свой вопрос!
3. Вы пробовали передавать @profiles.pluck(:id) через сеансы? Вы также можете передать информацию в скрытой форме на странице или через кнопку link_to, которую пользователь нажимает, чтобы запустить следующее действие. Google «rails, передающие переменные между контроллерами», и вы получите множество ответов, многие из них на SO.
4. Ваш вопрос неясен. Вы хотите реализовать функцию, которая будет помечать все профили, содержащиеся в
@profiles
? Вы всегда будете выполнять этот процесс тегирования каждый раз, когда выполняется действие show?5. Я думаю, я спрашиваю о том, что я хочу, чтобы пользователь мог выполнять поисковый запрос, иметь профили в представлении, а затем, если они будут удовлетворены, отмечать все из них, поэтому потребуется форма.
Ответ №1:
Действия общедоступного контроллера Rails всегда соответствуют http-запросу. Но здесь просто нет необходимости в 2 http-запросах. Простым решением было бы просто создать методы для частных контроллеров filter_profiles(params)
tag_profiles(profiles)
и просто вызывать их последовательно.
Вы также можете полностью извлечь эту проблему в ServiceObject, например:
class ProfileTagger
attr_reader :search_params
def initialize(search_params)
@search_params = search_params
end
def perform
search
tag
end
def tag
#tag found profiles
end
def search
@profiles = #do the search
end
end
Поскольку обработка 30 000 записей является трудоемкой операцией, было бы разумно выполнять ее вне запроса rails в фоновом режиме. Эта структура позволит вам с легкостью делегировать эту операцию работнику sidekiq или delayed_job
Комментарии:
1. Вы также выполняете много манипуляций с данными в контроллере вместо модели.
2. Как я могу пометить без запросов, но только с одним запросом и формой?
3. Думаю, я понял вашу проблему. Сначала вы показываете отфильтрованные данные, а затем хотите пометить их, верно?
4. В этом случае. Вы должны выполнить поиск дважды. Первый раз, при отображении профилей, и второй раз, при их пометке. Вы можете отобразить параметры поиска в виде скрытых полей в форме тегов или просто сохранить их во flash. При отправке формы с тегами вы делаете то, что я описал в ответе
Ответ №2:
Если вы хотите «поделиться» переменными данными между действиями контроллера, вам нужно взглянуть на ролевую @instance variables
игру.
Экземпляр класса означает, что при отправке запроса у вас будет доступ к @instance
переменной, пока вы находитесь в этом экземпляре класса, т.Е.:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
before_action :create_your_var
def your_controller
puts @var
end
private
def create_your_var
@var = "Hello World"
end
end
Это означает, что если вы хотите использовать данные в своем контроллере, я бы просто установил @instance variables
, к которым вы сможете получить доступ с помощью любого количества различных действий, которые вы пожелаете
—
Методы экземпляра
Разница будет заключаться в том, как вы вызываете эти действия —
#app/controllers/your_controller.rb
Class YourController < ApplicationController
def action
#-> your request resolves here
method #-> calls the relevant instance method
end
private
def method
#-> this can be called within the instance of the class
end
end