Coder Social home page Coder Social logo

kristianmandrup / periscope Goto Github PK

View Code? Open in Web Editor NEW

This project forked from laserlemon/periscope

1.0 3.0 0.0 591 KB

Push your models' scopes up to the surface.

Home Page: http://laserlemon.github.com/periscope

License: MIT License

Ruby 100.00%

periscope's Introduction

Periscope Build Status Dependency Status

Periscope provides a simple way to chain scopes on your models and to open those scopes up to your users.

Installation

Periscope sits on top of your favorite ORM. Currently, the following ORMs are supported through individual gems extending Periscope:

Simply add the gem to your bundle and you're off!

The Problem

More often than not, the index action in a RESTful Rails controller is expected to do a lot more than simply return all the records for a given model. We ask it to do all sorts of stuff like filtering, sorting and paginating results. Of course, this is typically done using scopes.

But it can get ugly building long, complicated chains of scopes in the controller, especially when you try to give your users control over the scoping. Picture this:

def index
  @articles = Article.scoped
  @articles = @articles.published_after(params[:published_after]) if params.key?(:published_after)
  @articles = @articles.published_before(params[:published_before]) if params.key?(:published_before)
end

You can imagine how bad this would get if more than two scopes were involved.

The Solution

With Periscope, you can have this instead:

def index
  @articles = Article.periscope(request.query_parameters)
end

The periscope method will find keys in your params matching your scope names and chain your scopes for you.

Note: We're using request.query_parameters so that we can exclude our controller and action params. request.query_parameters will just return the params that appear in the query string.

But Wait!

"What if I don't want to make all my scopes publicly accessible?"

Within your model you can use the scope_accessible method to specify which scopes you want Periscope to honor.

class User < ActiveRecord::Base
  scope :gender, lambda{|g| where(gender: g) }
  scope :makes, lambda{|s| where('salary >= ?', s) }

  scope_accessible :gender
end

And in your controller:

class UsersController < ApplicationController
  def index
    @users = User.periscope(request.query_parameters)
  end
end

Requests to /users?gender=male will filter results to only male users. But a request to /users?makes=1000000 will return all users, silently ignoring the protected scope.

By default, all scopes are protected.

There's More!

Custom Parameter Parsing

Sometimes the values you get from the query parameters aren't quite good enough. They may need to be massaged in order to work with your scopes and class methods. In those cases, you can provide a :parser option to your scope_accessible method.

Parsers must respond to the call method, receiving the raw query parameter and returning an array of arguments to pass to the scope or class method.

class User < ActiveRecord::Base
  scope :gender, lambda{|g| where(gender: g) }

  scope_accessible :gender, parser: lambda{|g| [g.downcase] }
end

On/Off Scopes

But not all scopes accept arguments. For scopes that you want to toggle on or off, you can set a :boolean => true option. Whenever the received parameter is truthy, the scope will be applied. Otherwise, it will be skipped.

class User < ActiveRecord::Base
  scope :male, where(gender: 'male')
  scope :female, where(gender: 'female')

  scope_accessible :male, :female, boolean: true
end

Custom Method Names

Sometimes the query parameters you want to open up to your users may collide with existing method names or reserved Ruby words. In order to avoid collision, you can set a :method option to specify what method to use for a query parameter.

class Project < ActiveRecord::Base
  scope_accessible :begin, method: :begins_after
  scope_accessible :end, method: :ends_before

  def self.begins_after(date)
    where('begins_at >= ?', date)
  end

  def self.ends_before(date)
    where('ends_at <= ?', date)
  end
end

Alternatively, you can set :prefix and/or :suffix options, which will be applied to the query parameter name to determine the corresponding method name.

class Project < ActiveRecord::Base
  scope_accessible :begin, :end, suffix: '_date'

  def self.begin_date(date)
    where('begins_at >= ?', date)
  end

  def self.end_date(date)
    where('ends_at <= ?', date)
  end
end

This sucks.

How can I make it better?

  1. Fork it.
  2. Make it better.
  3. Send me a pull request.

periscope's People

Contributors

fxn avatar kristianmandrup avatar laserlemon avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

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.