flex
flex copied to clipboard
Include Flex::Scopes in module throws "uninitialized constant ModelName::Flex::Scopes"
Example:
class Project < ActiveRecord::Base
include Flex::ModelIndexer
flex.sync self
def flex_source
{ :name => name }
end
module Flex
include Flex::Scopes
flex.context = Project
scope :search_by_name, ->(name) { terms(name: name) }
end
end
This throws NameError: uninitialized constant Project::Flex::Scopes
on server start. I had to do
module Flex
include ::Flex::Scopes
...
end
True! Thanks for pointing that out: I will fix the example in the doc.
BTW: how do I chain a Flex scope (which is in a module) with an ActiveRecord scope/relation? Example:
#search_by_name is in Flex module like in first post
@projects = @user.projects.search_by_name('Tom')
#I can get the indexer, but don't know how can I use it
#@projects = @user.projects.flex ...
Not sure to understand what you need. A Flex scope and a AR scope are 2 different things: the first is defining a search criteria in the index, the second in the DB. Index and DB have usually quite different structures and it's practically impossible to integrate them.
If you need to search the index, then use Project::Flex.search_by_name('Tom')
and you will get the elasticsearch documents with the term 'Tom'. If you want to restrict the search to a specific subset of projects (like the projects of a user) then you should create add the criteria to restrict to that use.
For example, supposing you have a :user_id field in the projects:
def flex_source
{ :name => name, :user_id => user_id }
end
module Flex
...
scope :search_by_user_id_and_name, ->(user_id, name) { terms(user_id: user_id, name: name) }
...
end
Or you can write 2 scopes one for the user_id and another for the project name, then chain them together when you need both or use them separately at will.
Yeah, I thought so, this was actually my first solution - I was just curious if maybe there is a way. I'm having a problem actually with a basic search, just by :name
class Project < ActiveRecord::Base
include Flex::ModelIndexer
flex.sync self
def flex_source
{ :name => name }
end
module Flex
include ::Flex::Scopes
flex.context = Project
scope :search_by_name, ->(name) { terms(name: name) }
end
end
Flex has the data
Flex.count => 11
Flex.all[8] =>
=> {"_index"=>"karma_tracker_development",
"_type"=>"project",
"_id"=>"825",
"_score"=>1.0,
"_source"=>{"name"=>"Public test"}}
But when I do:
Project::Flex.search_by_name('Public').all
=> []
Nada, any ideas?
If you enter the complete content of the field ("Public test") you should get it. Please, refer to the elasticsearch doc for the term query.
Well, actually it doesn't work for complete fraze because the words need to be seperate (and downcase as well). I ended up with custom filters (to get prefixes and filter ids)
scope :search_by_id_and_name, ->(names, ids) { filters(prefix: { name: names }).
filters(ids: { values: ids } ) }
Thanks for the help!