Note that there are some explanatory texts on larger screens.

plurals
  1. POVariable scope definitions and inheritance
    primarykey
    data
    text
    <p>I'm working on a extended search feature for my webpage.</p> <p>I looked at <a href="https://github.com/ernie/ransack" rel="nofollow noreferrer">ransack</a>, however it's lacking some functionalities I need, makes the url-query string very long and has some bugs (reported).</p> <p>Thus I started to implement my own hack.</p> <p>First I want to present my idea, afterwards I want to ask kindly how to fix my issue and in the end if there are other ways to improve this.</p> <p>The idea:</p> <p>A model defines something like this (additionally, the model is inside an engine):</p> <pre><code>module EngineName class Post &lt; ActiveRecord::Base search_for :name, :as =&gt; :string do |b, q| b.where{name =~ "%#{q}%"} end end end </code></pre> <p>:name is to define the query-param to use e.g. this would be ?q[name]=something I know that this is not fully generic like ransack, but well...</p> <p>:as is to build up the correct form-tag. :string would be for text_field, :integer for number_field and so on. I want to extend it further to implement auto-generating of collections for associations etc.</p> <p>Now the block is a simple scope to use. I run into several shortcomings with ransack when building up complex queries (like with count() etc.). Now I can specify my own optimized query in <a href="https://github.com/ernie/squeel" rel="nofollow noreferrer">squeel</a>.</p> <p>I extended ActiveRecord::Base to set up the logic (the global one, not inside the engine. I want to use it everywhere). I defined a scope :search so I can use Model.search(param[q]) like in ransack. Also I tried to keep a list of keys which are "searchable" defined by the search_for calls.</p> <pre><code>class ActiveRecord::Base @@searchable_attributes = Hash.new({}) def self.search_for(name, *opts, &amp;search_scope) return unless search_scope @@searchable_attributes[name] = { :type =&gt; opts[:as], :condition =&gt; search_scope } unless @@searchable_attributes.has_key? :nil @@searchable_attributes[:nil] = Proc.new { scoped } end end scope :search, lambda {|q| next unless q.kind_of?(Hash) base = @@searchable_attributes[:nil].call q.each do |key, search| next unless base.class.searchable_attributes.has_key?(key) base = @@searchable_attributes[key][:condition].call(base, search) end base } end </code></pre> <p>Now the issues:</p> <p>It has mostly to do with inheritance of the classes. But even after reading and trying <a href="https://stackoverflow.com/questions/5452910/named-scopes-with-inheritance-in-rails-3-mapping-to-wrong-table">3</a>, <a href="https://stackoverflow.com/questions/5897196/rails-named-scope-inheritance">4</a> it does not worked.</p> <p>Please take a look at the second line in the scope :search.</p> <p>There I'm calling the simple Proc I definied above which only includes "scoped" This is to get arround the issue that self returns "ActiveRecord::Base" and not the model itself like "Post" or "Comment".</p> <p>It's because the scope is called on the Base class on inheritance, however I did not find anything to fix this.</p> <p>As search_for is called on the model itself (e.g. Post) the scope-model returned there is "the right one".</p> <p>Does anyone know how to circumvent this?</p> <p>The next question would be, how to store the list of "searchable" scopes. I used @@variables. But as they are shared within every subclass, this would be a no-go. However, it needs to be static as the search_for is called without initialize a instance (isn't it?)</p> <p>Last but not least, it is somekind horrible to always specify the base-model to use on every scope so that I can chain them together.</p> <p>Is there any other possibilities to improve this?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload