Giter Club home page Giter Club logo

queryable_array's Introduction

A QueryableArray inherits from Array and is intended to store a group of objects which share the same attributes allowing them to be searched. It overrides [], find_all and method_missing to provide a simplified DSL for looking up objects by querying their attributes.

View the full documentation over at rubydoc.info.

Installation

gem install queryable_array

Requirements

Ruby 1.9+

Usage

Basic

Initialize the QueryableArray with a collection of objects e.g. Page objects from a JSON response or database query (although you should probably restrict database queries with WHERE conditions instead if you have the opportunity)

pages = QueryableArray.new Page.all

The pages object can then be queried by passing a search hash to the [] method

pages[uri: '/']                    # => #<Page @uri='/' @name='Home'>
pages[name: 'About']               # => #<Page @uri='/about' @name='About'>
pages[uri: '/', name: 'Home']      # => #<Page @uri='/' @name='Home'>
pages[uri: '/', name: 'Mismatch']  # => nil

Notice that it only returns the first matching object or nil if one is not found. If you’d like to find all matching objects, simply wrap your search hash in an array

pages[[published: true]]  # => [#<Page @uri='/' @name='Home' @published=true>, #<Page @uri='/about' @name='About' @published=true>, ...]
pages[[uri: '/missing']]  # => []

Attributes may also be searched by regular expressions

pages[name: /home/i]   # => #<Page @uri='/' @name='Home'>
pages[[uri: /users/]]  # => [#<Page @uri='/users/bob' @name='Bob'>, #<Page @uri='/users/steve' @name='Steve'>, ...]

The methods find_by and find_all behave as aliases for [search_hash] and [[search_hash]] respectively

pages.find_by(name: 'Home')     # => #<Page @uri='/' @name='Home'>
pages.find_by(name: 'Missing')  # => nil
pages.find_all(uri: /users/)    # => [#<Page @uri='/users/bob' @name='Bob'>, #<Page @uri='/users/steve' @name='Steve'>, ...]

The existing block form for those methods work as well

pages.find_all { |page| page.uri =~ /users/ }  # => [#<Page @uri='/users/bob' @name='Bob'>, #<Page @uri='/users/steve' @name='Steve'>, ...]

A Proc object may be passed to [] as well

pages[uri: proc { |uri| uri.split('/').size > 1 }]  # => #<Page @uri='/users/bob' @name='Bob'>
pages[proc { |page| page.uri == '/' }]              # => #<Page @uri='/' @name='Home'>

Lookups by index or ranges still behave exactly as they do in regular Array objects

pages[0]     # => #<Page @uri='/' @name='Home'>
pages[-1]    # => #<Page @uri='/zebras' @name='Zebras'>
pages[99]    # => nil
pages[0..1]  # => [#<Page @uri='/' @name='Home'>, #<Page @uri='/about' @name='About'>]

Default finders

A QueryableArray object can be initialized with a default_finder to make lookups even simpler

pages = QueryableArray.new Page.all, :uri

Now the pages object can be searched easily by uri

pages['/']         # => #<Page @uri='/' @name='Home'>
pages['/about']    # => #<Page @uri='/about' @name='About'>
pages['/missing']  # => nil

You can even specify multiple default_finders

pages = QueryableArray.new Page.all, [:uri, :name]

pages['/about']  # => #<Page @uri='/about' @name='About'>
pages['About']   # => #<Page @uri='/about' @name='About'>
pages[/home/i]   # => #<Page @uri='/' @name='Home'>

Wrapping your search inside an array still returns all matches

pages[[/users/]]  # => [#<Page @uri='/users/bob' @name='Bob'>, #<Page @uri='/users/steve' @name='Steve'>, ...]

Dynamic attribute-based finders

QueryableArray#method_missing allows you to lookup objects using a notation like the ActiveRecord dynamic finders

pages.find_by_uri('/')                   # => #<Page @uri='/' @name='Home'>
pages.find_by_uri_and_name('/', 'Home')  # => #<Page @uri='/' @name='Home'>
pages.find_by_uri('/missing')            # => nil

pages.find_all_by_uri('/')               # => [#<Page @uri='/' @name='Home'>]
pages.find_all_by_uri(/users/)           # => [#<Page @uri='/users/bob' @name='Bob'>, #<Page @uri='/users/steve' @name='Steve'>, ...]

Dot notation finders

If any default_finders are defined you may even use dot notation to lookup objects by those attributes

pages = QueryableArray.new Page.all, :name

pages.sitemap               # => #<Page @uri='/sitemap' @name='Sitemap'>
pages.missing               # => NoMethodError
QueryableArray.new.missing  # => NoMethodError

Calling pages.sitemap behaves the same as pages[/sitemap/i]

To perform a case-sensitive search, simply append a ! to the end of your method call e.g. pages.sitemap! which calls pages['sitemap']

You may also query to see if a match exists by appending a ? to your search

pages.sitemap?  # => true
pages.missing?  # => false

Composable

Functionality for QueryableArray has been separated out into individual modules containing their own features which allows you to create your own objects and only include the features you care about

  • QueryableArray::DefaultFinder - Allows objects to be searched by default_finders thru []

  • QueryableArray::DotNotation - Allows objects to be searched using dot notation thru method_missing which behaves like an alias to QueryableArray::DefaultFinder#[]

  • QueryableArray::DynamicFinder - Allows objects to be searched by dynamic finders thru method_missing similar to the ActiveRecord dynamic attribute-based finders e.g. find_by_email or find_all_by_last_name

  • QueryableArray::Queryable - Allows find_by and find_all to accept search hashes which are converted into Proc searches and passed as the block arguments for find and find_all respectively

  • QueryableArray::Shorthand - Makes [search_hash] and [[search_hash]] behave as an alias for find_by and find_all respectively

Try making your own classes with them

class Collection < Array
  include QueryableArray::Queryable
end

pages = Collection.new Page.all
pages.find_all(published: true)  # => [#<Page @uri='/' @published=true>, #<Page @uri='/about' @published=true>]

Real world example

Try using it inside of your templates:

<div class="posts">
  <%- posts[[published: true]].each do |post| -%>
    <div class="post">
      <h2><a href="<%= post.url -%>"><%= post.title -%></a></h2>
      <div class="excerpt"><%= post.excerpt -%></div>
      <a href="<%= post.url -%>#comments"><%= post.comments[[approved: true]].size -%> comments</a>
    </div>
  <%- end -%>
</div>

Testing

bundle exec rake

queryable_array's People

Contributors

shuber avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

ilatif

queryable_array's Issues

update documentation after composable refactor

  • methods missing documentation
  • examples of proc queries
  • examples of queried attributes that don't exist
  • respond_to? examples
  • real world use cases (template object)
  • composable examples
  • callable objects

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.