Skip to content

Commit

Permalink
Init commit (#1)
Browse files Browse the repository at this point in the history
* Init commit
  • Loading branch information
deniskorobicyn committed May 4, 2016
1 parent 56d5ce8 commit 1d8e898
Show file tree
Hide file tree
Showing 23 changed files with 468 additions and 1 deletion.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
/gemfiles/*
/spec/internal/test
20 changes: 20 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
appraise 'rails3.1' do
gem 'rails', '~> 3.1.0'
end

appraise 'rails3.2' do
gem 'rails', '~> 3.2.0'
end

appraise 'rails4.0' do
gem 'rails', '~> 4.0.0'
end

appraise 'rails4.1' do
gem 'rails', '~> 4.1.0'
end

appraise 'rails4.2' do
gem 'rails', '~> 4.2.0'
end

4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'
gem 'mime-types', '< 3.0' if RUBY_VERSION < '2'

gemspec
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
RAILS_ENV = test
BUNDLE_VERSION = 1.11.2
BUNDLE = RAILS_ENV=${RAILS_ENV} bundle _${BUNDLE_VERSION}_
BUNDLE_OPTIONS = -j 2
RSPEC = rspec
APPRAISAL = appraisal

all: test

test: bundler/install appraisal/install
${BUNDLE} exec ${APPRAISAL} ${RSPEC} spec 2>&1

bundler/install:
gem install bundler --version=${BUNDLE_VERSION};
${BUNDLE} install ${BUNDLE_OPTIONS}

appraisal/install:
${BUNDLE} exec ${APPRAISAL} install

clean:
rm -f Gemfile.lock
rm -rf gemfiles

161 changes: 160 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,160 @@
# findit
# Findit

Tired of writing fat controllers? But you must do all these queries.. There is a solution, move it to a Finder class.

Don't write this:

```ruby
class SomeController
def index
@cache_key = (
# many_values
)
return if fragment_exists?(@cache_key)
search_scope = SearchEngine.scope
search_scope.add(some_conditions)
search_scope.add(some_conditions)
search_scope.add(some_conditions)
search_scope.add(some_conditions)
search_scope.add(some_conditions)
search_scope.add(some_conditions)
search_scope.add(some_conditions)
result = search_scope.search_and_return_ids
@scope = scope.where(ids: result)
....
end
end
```

Just do this:
```ruby
# /app/controllers/some_controller.rb
class SomeController
def index
@scope = SomeFinder.new(params)
end
end

# app/finders/some_finder.rb
class SomeFinder
include Findit::Collections

cache_key do
# calculate you cache_key from params
end

def initialize(params)
# some initialize, maybe params parse
end

def call
# put here you find logic
end
end
```

And that it! Now you can iterate over finder results by simple `each`:
```ruby
@scope = SomeFinder.new(params)
@scope.each do |d|
print d.description
end
```
or perform caching like ActiveRecord::Base
```ruby
# app/some_view
<% cache @scope do %>
<%scope.each do |res|%>
...
<%end%>
<%end%>

```

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'findit'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install findit

## Per module documentation

### Collections

It makes Finder work as Enumerator.
Result can be accessed with `each`, `[]` and `size` methods, but to make things work you *must* implement `call` method.
```
class PostFinder
incliude Findit::Collections
def call
Post.where(user_id: 1)
end
end
@posts = PostFinder.new
# load all matching posts and iterate over collection
@posts.each do |post|
print post.title
end
@posts[10] # get 10 element of posts
@posts.size # size of PostFinder results
# Also you can access result direcly by using `data` method.
@posts.data # access to all posts
```

For easier caching expirience we provide DSL to define you custom `cache_key`

```ruby
#/app/finders/posts_finders.rb
class PostFinder
include Findit::Collections

cache_key do
[@user.id, @query] # here you put any stuff that result of finder depend on it
end

# custom initializer, do whatever you want here
def initialize(user, options = {})
@user = user
@query = options[:query]
end

# Here we fetch results. You MUST implement it
def call
scope = scope.where(user_id: @user.id)
scope = scope.where('description like :query', query: @query) if @query.present?
scope
end
end

#/app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = PostFinder.new(user: current_user)
end
end

#/app/views/posts/index.html.haml
<% cache(@posts, expire_in: 30.minutes) do %>
<%=render 'post' colection: @posts, as: :post%> # it will automaticly iterate over finder results by each method
```

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/findit.
6 changes: 6 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)

task :default => :spec
14 changes: 14 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env ruby

require "bundler/setup"
require "findit"

# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.

# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start

require "irb"
IRB.start
8 changes: 8 additions & 0 deletions bin/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx

bundle install

# Do any other automated setup that you need to do here
7 changes: 7 additions & 0 deletions config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'rubygems'
require 'bundler'

Bundler.require :default, :development

Combustion.initialize! :all
run Combustion::Application
31 changes: 31 additions & 0 deletions findit.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'findit/version'

Gem::Specification.new do |spec|
spec.name = "findit"
spec.version = Findit::VERSION
spec.authors = ["Denis Korobicyn"]
spec.email = ["[email protected]"]

spec.summary = %q{Extensions for Finder classes}
spec.homepage = "https://github.com/abak-press/findit"

spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_runtime_dependency 'activesupport', '>= 3.1'

spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", ">= 3.2"
spec.add_development_dependency "rspec-rails", ">= 3.2"
spec.add_development_dependency 'combustion', '>= 0.5'
spec.add_development_dependency "appraisal", ">= 2.1.0"
spec.add_development_dependency 'pry-debugger'
spec.add_development_dependency 'shoulda-matchers', '< 3.0.0'
spec.add_development_dependency 'simplecov'
spec.add_development_dependency 'sqlite3'
end
6 changes: 6 additions & 0 deletions lib/findit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require 'active_support'
require "findit/version"
require 'findit/collections'

module Findit
end
67 changes: 67 additions & 0 deletions lib/findit/collections.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#
# Example usage:
#
# #/app/finders/posts_finders.rb
# class PostFinder
# include Findit::Collections
#
# cache_key do
# [@user.id, @query]
# end
#
# cache_tags do
# {user_id: @user.id}
# end
#
# expire_in 30.minutes
#
# def initialize(user, options = {})
# @user = user
# @query = options[:query]
# end
#
# def call
# scope = scope.where(user_id: @user.id)
# scope = scope.where('description like :query', query: @query) if @query.present?
# scope
# end
# end
#
# #/app/controllers/posts_controller.rb
# class PostsController < ApplicationController
# def index
# @posts = PostFinder.new(user: current_user)
# end
# end
#
# #/app/views/posts/index.html.erb
# <% cache(@posts, tags: @posts.cache_tags, expire_in: @posts.expire_in) do %>
# <%= render 'post' colection: @posts, as: :post%>
#
module Findit
module Collections
include Enumerable
extend ActiveSupport::Concern

included do
delegate :each, :[], :size, :empty?, to: :data
end

module ClassMethods
def cache_key(&block)
define_method :cache_key do
@cache_key ||= ActiveSupport::Cache.expand_cache_key(instance_exec(&block))
end
end
end

def call
end
undef :call

def data
return @data if defined?(@data)
@data = call
end
end
end
3 changes: 3 additions & 0 deletions lib/findit/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module Findit
VERSION = "0.1.0"
end
Loading

0 comments on commit 1d8e898

Please sign in to comment.