Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Include Flex::Scopes in module throws "uninitialized constant ModelName::Flex::Scopes" #9

Open
BartlomiejSkwira opened this issue Oct 30, 2013 · 6 comments

Comments

@BartlomiejSkwira
Copy link

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
@ddnexus
Copy link
Owner

ddnexus commented Oct 30, 2013

True! Thanks for pointing that out: I will fix the example in the doc.

@BartlomiejSkwira
Copy link
Author

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 ...

@ddnexus
Copy link
Owner

ddnexus commented Oct 30, 2013

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.

@BartlomiejSkwira
Copy link
Author

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?

@ddnexus
Copy link
Owner

ddnexus commented Oct 30, 2013

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.

@BartlomiejSkwira
Copy link
Author

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!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants