Reputation: 13862
My show action:
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
There can be many different filters taking place in here whether with Ransacker, with the params[:limit] or others. At the end I have a subset of profiles.
Now I want to tag all these profiles that are a result of the search query.
Profiles model:
def self.tagging_profiles
#Some code
end
I'd like to create an action within the same controller as the show that will execute the self.tagging_profiles
function on the @profiles
from the show action given those profiles have been filtered down.
def tagging
@profiles.tagging_profiles
end
I want the user to be able to make a search query, have profiles in the view then if satisfied tag all of them, so there would be a need of a form
UPDATE:
This is how I got around it, don't know how clean it is but here:
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]
tag_profiles(params[:tag_names]) if params[:tag_names]
end
private
def tag_profiles(names)
@profiles.tagging_profiles
end
In my view, I created a form calling to 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 %>
Is this the best way to do it?
Upvotes: 0
Views: 3343
Reputation: 76774
If you want to "share" variable data between controller actions, you'll want to look at the role @instance variables
play.
An instance of a class means that when you send a request, you'll have access to the @instance
variable as long as you're within that instance of the class, I.E:
#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
This means if you wish to use the data within your controller, I would just set @instance variables
, which you will then be able to access with as many different actions as you wish
--
Instance Methods
The difference will be through how you call those actions -
#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
Upvotes: 0
Reputation: 8044
Rails public controller actions correspond always to a http request. But here there is just no need for 2 http requests. A simple solution would be just creating to private controllers methods filter_profiles(params)
and tag_profiles(profiles)
and just call them sequentially.
You can also extract this problem entirely to a ServiceObject, like this:
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
As processing 30,000 records is a time consuming operation, it would make sence to perform it outside of the rails request in background. This structure will allow you to delegate this operation to a sidekiq or delayed_job worker with ease
Upvotes: 0