Reputation: 9
I'm trying to retrieve from the database two contents: the first one with the field source equal to "imported"
(which means that we import it from the excel spreadsheet), and the second one with source != imported
(we create it from scratch). Attached is my code:
def index
add_breadcrumb 'Projects', projects_path
add_breadcrumb @project.name, @project
add_breadcrumb "List #{@category.display_name} Content", project_category_contents_path(@project, @category)
@contents_imported = Content.of_project(@project).with_category(@category).imported.order('contents.created_at asc')
@contents_not_imported = Content.of_project(@project).with_category(@category).not_imported.order('contents.created_at desc')
@page = params[:page]
@contents = @contents_not_imported << @contents_imported
@q = @contents.search(params[:q])
@content = @q.result(distinct: true).page(@page).per(20)
end
@contents_imported = Content.of_project(@project).with_category(@category).imported.order('contents.created_at asc')
@contents_not_imported = Content.of_project(@project).with_category(@category).not_imported.order('contents.created_at desc')
And I want to combine the two results before showing it:
@contents = @contents_not_imported << @contents_imported
but it didn't work. How can I do that?
Upvotes: 0
Views: 1578
Reputation: 5229
Just create a new Relation with the conditions of imported or not imported, after that, order all the records (if order is important to @contents
and @content
):
def index
add_breadcrumb 'Projects', projects_path
add_breadcrumb @project.name, @project
add_breadcrumb "List #{@category.display_name} Content", project_category_contents_path(@project, @category)
@contents_imported = Content.of_project(@project).with_category(@category).imported.order('contents.created_at asc')
@contents_not_imported = Content.of_project(@project).with_category(@category).not_imported.order('contents.created_at desc')
@page = params[:page]
imported = @contents_imported.where_values.reduce(:and)
not_imported = @contents_not_imported.where_values.reduce(:and)
@contents = Content.where(imported.or(not_ipmorted)).order('CASE contents.imported WHEN true THEN contents.created_at asc ELSE contents.created_at desc END')
@q = @contents.search(params[:q])
@content = @q.result(distinct: true).page(@page).per(20)
end
Now you can call Ransack#search
on @contents
because it is an ActiveRecord::Relation. I assume that the imported scope take a field contents.imported
with value true.
If I wrote this without errors, this must works.
Upvotes: 0
Reputation: 35533
The problem is that you want to concatenate results, but you also want to continue treating the combined results as an ActiveRelation (call .search
on it). Here's a simpler approach that avoids the need for concatenation in the first place. You will need a more complex ORDER BY clause to accomplish this, however:
@page = params[:page]
@contents = Content.of_project(@project).with_category(@category).
order('CASE WHEN source <> "imported" THEN contents.created_at END desc, CASE WHEN source = "imported" THEN contents.created_at END asc')
@q = @contents.search(params[:q])
Upvotes: 1
Reputation: 2575
Concatenating the arrays is done with the plus sign
You are getting undefined method search for Array
because, concatenating will return you an array. And you can't call search method on that Array
EDIT
def index
add_breadcrumb 'Projects', projects_path
add_breadcrumb @project.name, @project
add_breadcrumb "List #{@category.display_name} Content", project_category_contents_path(@project, @category)
contents_imported_ids = Content.of_project(@project).with_category(@category).imported.order('contents.created_at asc').map(&:id)
contents_not_imported_ids = Content.of_project(@project).with_category(@category).not_imported.order('contents.created_at desc').map(&:id)
@page = params[:page]
contents_ids = contents_imported_ids + contents_not_imported_ids
contents = Content.where(content_ids)
@contents = content_ids.collect{|id| contents.detect{|c| c.id == id}}
@q = @contents.search(params[:q])
@content = @q.result(distinct: true).page(@page).per(20)
end
Upvotes: 0
Reputation: 1313
If both of them are arrays and are having same type of objects you can do Result = Arr1 | Arr1
That also removes the duplicates. Its like boolean UNION. In your case @contents = @contents_not_imported | @contents_imported
Upvotes: 1