globalized search first draft

Confirmed features:
    * Output (retrieval, sorting, etc.)
    * Name (positive and negative, but new behavior)
    * Flags (positive and negative)

Planned features:
    * users:owns, user:wants

Known issues:
    * Sets are broken
        * Don't render properly
        * Shouldn't actually be done as joined sets, anyway, since
          we actually want (set1_zone1 OR set1_zone2) AND
          (set2_zone1 OR set2_zone2), which will require breaking
          it into multiple terms queries.
    * Name has regressed: ignores phrases, doesn't require *all*
      words. While we're breaking sets into multiple queries,
      maybe we'll do something similar for name. In fact, we
      really kinda have to if we're gonna keep sorting by name,
      since "straw hat" returns all hats. Eww.
This commit is contained in:
Emi Matchu 2013-01-18 23:23:37 -06:00
parent c9ae7155b1
commit 6e09b8bc10
71 changed files with 594 additions and 43 deletions

View file

@ -43,7 +43,7 @@ gem 'neopets', :git => 'git://github.com/matchu/neopets.git'
gem "mini_magick", "~> 3.4"
gem "fog", "~> 1.1.2"
gem "fog", "~> 1.8.0"
gem "carrierwave", "~> 0.5.8"
gem "parallel", "~> 0.5.17"
@ -51,6 +51,11 @@ gem "parallel", "~> 0.5.17"
gem "http_accept_language", :git => "git://github.com/iain/http_accept_language.git"
gem "globalize3"
# My flex branch fixes a minor pagination bug. Once it's merged into the
# original gem, we can switch back.
gem "flex", :require => "flex/rails", :git => "git@github.com:matchu/flex.git"
gem "patron", "~> 0.4.18"
group :development do
gem "bullet", "~> 4.1.5"
end

View file

@ -1,8 +1,8 @@
GIT
remote: git://github.com/eventmachine/eventmachine.git
revision: 69151c3ebb3e4ecf2bb9b6e2fab2022dc34f8541
revision: d7c8a14dc494193a775add4b16c1e303cab5b285
specs:
eventmachine (1.0.0.beta.4)
eventmachine (1.0.0)
GIT
remote: git://github.com/iain/http_accept_language.git
@ -12,9 +12,9 @@ GIT
GIT
remote: git://github.com/igrigorik/em-http-request.git
revision: ce50f322ce08d43a4a747cf333ea576765d764c4
revision: 322f2273fa7ea07c1eeb92755bf67f1f05058e54
specs:
em-http-request (1.0.1)
em-http-request (1.0.3)
addressable (>= 2.2.3)
cookiejar
em-socksify
@ -30,21 +30,21 @@ GIT
GIT
remote: git://github.com/igrigorik/em-synchrony.git
revision: c7209a58f9eb92e1dc81fb141297f9f257c2fdcb
revision: fe592a4b9b5345bca329477cb8f2f8d186b6fc7f
specs:
em-synchrony (1.0.0)
em-synchrony (1.0.2)
eventmachine (>= 1.0.0.beta.1)
GIT
remote: git://github.com/matchu/neopets.git
revision: fe694681a302243d2937e811355473f358035403
revision: d33aaf63d4617d9236ef0d99452b3bdc577cbc8e
specs:
neopets (0.0.2)
neopets (0.1.0)
nokogiri (~> 1.5.2)
GIT
remote: git://github.com/oldmoe/mysqlplus.git
revision: 3dbaa7c00ff0bb75ad9538cdef176c72de35d231
revision: f07936d2eb9b0893994ed99fe82267b5e7770d06
specs:
mysqlplus (0.1.1)
@ -54,6 +54,15 @@ GIT
specs:
RocketAMF (1.0.0)
GIT
remote: git@github.com:matchu/flex.git
revision: d62f508f795ecdbb383f406865daa72368b43ba5
specs:
flex (0.4.1)
multi_json (~> 1.3.4)
progressbar (~> 0.11.0)
prompter (~> 0.1.5)
GEM
remote: http://rubygems.org/
specs:
@ -88,17 +97,17 @@ GEM
activemodel (= 3.0.19)
activesupport (= 3.0.19)
activesupport (3.0.19)
addressable (2.2.6)
addressable (2.3.2)
arel (2.0.10)
bcrypt-ruby (2.1.4)
builder (2.1.2)
bullet (4.1.5)
bullet (4.1.6)
uniform_notifier (~> 1.0.0)
carrierwave (0.5.8)
activesupport (~> 3.0)
character-encodings (0.4.1)
chronic (0.6.7)
closure-compiler (1.1.4)
closure-compiler (1.1.8)
compass (0.10.6)
haml (>= 3.0.4)
cookiejar (0.3.0)
@ -106,27 +115,28 @@ GEM
bcrypt-ruby (~> 2.1.2)
warden (~> 1.0.2)
diff-lcs (1.1.3)
em-socksify (0.1.0)
eventmachine
dye (0.1.4)
em-socksify (0.2.1)
eventmachine (>= 1.0.0.beta.4)
erubis (2.6.6)
abstract (>= 1.0.0)
excon (0.9.6)
factory_girl (2.3.2)
activesupport
factory_girl_rails (1.4.0)
factory_girl (~> 2.3.0)
excon (0.16.10)
factory_girl (2.6.4)
activesupport (>= 2.3.9)
factory_girl_rails (1.7.0)
factory_girl (~> 2.6.0)
railties (>= 3.0.0)
fog (1.1.2)
fog (1.8.0)
builder
excon (~> 0.9.0)
excon (~> 0.14)
formatador (~> 0.2.0)
mime-types
multi_json (~> 1.0.3)
multi_json (~> 1.0)
net-scp (~> 1.0.4)
net-ssh (>= 2.1.3)
nokogiri (~> 1.5.0)
ruby-hmac
formatador (0.2.1)
formatador (0.2.4)
globalize3 (0.3.0)
activemodel (>= 3.0.0)
activerecord (>= 3.0.0)
@ -150,23 +160,28 @@ GEM
mime-types (1.19)
mini_magick (3.4)
subexec (~> 0.2.1)
msgpack (0.4.6)
multi_json (1.0.4)
mysql2 (0.2.6)
msgpack (0.4.7)
multi_json (1.3.7)
mysql2 (0.2.18)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
net-ssh (2.3.0)
newrelic_rpm (3.5.3.25)
nokogiri (1.5.3)
net-ssh (2.6.3)
newrelic_rpm (3.5.5.38)
nokogiri (1.5.6)
open4 (1.3.0)
openneo-auth-signatory (0.1.0)
ruby-hmac
paper_trail (2.7.0)
activerecord (~> 3.0)
railties (~> 3.0)
parallel (0.5.17)
parallel (0.5.21)
patron (0.4.18)
polyglot (0.3.3)
rack (1.2.6)
progressbar (0.11.0)
prompter (0.1.5)
dye (>= 0.1.1)
yard (>= 0.6.3)
rack (1.2.7)
rack-fiber_pool (0.9.2)
rack-mount (0.6.14)
rack (>= 1.0.0)
@ -190,9 +205,9 @@ GEM
rdiscount (1.6.8)
rdoc (3.12)
json (~> 1.4)
redis (2.2.2)
redis-namespace (1.1.0)
redis (< 3.0.0)
redis (3.0.2)
redis-namespace (1.2.1)
redis (~> 3.0.0)
resque (1.15.0)
json (~> 1.4.6)
redis-namespace (>= 0.10.0)
@ -221,14 +236,14 @@ GEM
rspec-rails (2.0.1)
rspec (~> 2.0.0)
ruby-hmac (0.4.0)
rufus-scheduler (2.0.16)
rufus-scheduler (2.0.17)
tzinfo (>= 0.3.23)
sanitize (2.0.3)
nokogiri (>= 1.4.4, < 1.6)
sinatra (1.2.8)
rack (~> 1.1)
tilt (>= 1.2.2, < 2.0)
subexec (0.2.1)
subexec (0.2.2)
swf_converter (0.0.3)
thor (0.14.6)
tilt (1.3.3)
@ -237,14 +252,15 @@ GEM
polyglot (>= 0.3.1)
tzinfo (0.3.35)
uniform_notifier (1.0.2)
vegas (0.1.8)
vegas (0.1.11)
rack (>= 1.0.0)
warden (1.0.6)
rack (>= 1.0)
whenever (0.7.3)
activesupport (>= 2.3.4)
chronic (~> 0.6.3)
will_paginate (3.0.2)
will_paginate (3.0.4)
yard (0.8.3)
yui-compressor (0.9.6)
POpen4 (>= 0.1.4)
@ -264,7 +280,8 @@ DEPENDENCIES
em-synchrony!
eventmachine!
factory_girl_rails (~> 1.0)
fog (~> 1.1.2)
flex!
fog (~> 1.8.0)
globalize3
haml (~> 3.0.18)
hoptoad_notifier
@ -280,6 +297,7 @@ DEPENDENCIES
nokogiri (~> 1.5.2)
openneo-auth-signatory (~> 0.1.0)
parallel (~> 0.5.17)
patron (~> 0.4.18)
rack-fiber_pool
rails (= 3.0.19)
rdiscount (~> 1.6.5)

View file

@ -8,12 +8,11 @@ class ItemsController < ApplicationController
per_page = params[:per_page].to_i
per_page = 50 if per_page && per_page > 50
else
per_page = nil
per_page = 30
end
# Note that we sort by name by hand, since we might have to use
# fallbacks after the fact
@items = Item.search(@query, current_user, I18n.default_locale).
alphabetize_by_translations.
@items = Item::Search::Query.from_text(@query, current_user).
paginate(:page => params[:page], :per_page => per_page)
assign_closeted!
respond_to do |format|

18
app/flex/flex_search.rb Normal file
View file

@ -0,0 +1,18 @@
# inspect the methods loaded in this module and their usage
# in the rails console by just typing:
# >> puts FlexSearch.flex.info
# you can eventually restrict the info to a single method by pasing its name:
# >> puts FlexSearch.flex.info :search
# see the detailed doc for this feature at https://github.com/ddnexus/flex/wiki/Selfdoc
module FlexSearch
extend self
include Flex::Loader
flex.load_search_source
# you may need to add more method here, usually wrapper methods
# that use one of the autogenerated methods from the loaded templates
end

45
app/flex/flex_search.yml Normal file
View file

@ -0,0 +1,45 @@
# Add here your search queries
# see the detailed Source documentation at https://github.com/ddnexus/flex/wiki/Sources
# ANCHORS litheral key: it will not be used as template
# you can store here fragments of queries to reuse in the templates below
ANCHORS:
- &name_locale_partial
"name.<<locale>>^<<boost= 1>>"
_name_locales:
*name_locale_partial
_negative_name_locales:
*name_locale_partial
item_search:
- query:
bool:
must:
- multi_match:
query: <<name= ~>>
fields: <<_name_locales>>
- term:
is_nc: <<is_nc= ~>>
- term:
is_pb: <<is_pb= ~>>
- term:
species_support_id: <<species_support_id= ~>>
- term:
occupied_zone_id: <<occupied_zone_id= ~>>
- term:
restricted_zone_id: <<restricted_zone_id= ~>>
must_not:
- term:
species_support_id: <<negative_species_support_id= ~>>
- term:
occupied_zone_id: <<negative_occupied_zone_id= ~>>
- term:
restricted_zone_id: <<negative_restricted_zone_id= ~>>
- multi_match:
query: <<negative_name= ~>>
fields: <<_negative_name_locales>>
sort:
- name.<<locale>>.untouched

View file

@ -0,0 +1,36 @@
# see the detailed Extenders documentation at https://github.com/ddnexus/flex/wiki/Extenders
module FlexSearchExtender
# set this method to restrict this extender to certain types of results
# see the other Flex extenders for reference (https://github.com/ddnexus/flex/tree/master/lib/flex/result)
def self.should_extend?(response)
true
end
def scoped_loaded_collection(options)
options[:scopes] ||= {}
@loaded_collection ||= begin
records = []
# returns a structure like {Comment=>[{"_id"=>"123", ...}, {...}], BlogPost=>[...]}
h = Flex::Utils.group_array_by(collection) do |d|
d.mapped_class(should_raise=true)
end
h.each do |klass, docs|
scope = options[:scopes][klass.name] || klass.scoped
records |= scope.find(docs.map(&:_id))
end
class_ids = collection.map { |d| [d.mapped_class.to_s, d._id] }
# Reorder records to preserve order from search results
records = class_ids.map do |class_str, id|
records.detect do |record|
record.class.to_s == class_str && record.id.to_s == id.to_s
end
end
records.extend Flex::Result::Collection
records.setup(self['hits']['total'], variables)
records
end
end
end

View file

@ -1,4 +1,5 @@
class Item < ActiveRecord::Base
include Flex::Model
include PrettyParam
set_inheritance_column 'inheritance_type' # PHP Impress used "type" to describe category
@ -45,6 +46,27 @@ class Item < ActiveRecord::Base
scope :with_closet_hangers, joins(:closet_hangers)
flex.sync self
def flex_source
indexed_attributes = {
:is_nc => self.nc?,
:is_pb => self.pb?,
:species_support_id => self.species_support_ids,
:occupied_zone_id => self.occupied_zone_ids,
:restricted_zone_id => self.restricted_zone_ids,
:name => {}
}
I18n.usable_locales_with_neopets_language_code.each do |locale|
Globalize.with_locale(locale) do
indexed_attributes[:name][locale] = self.name
end
end
indexed_attributes.to_json
end
def closeted?
@owned || @wanted
end
@ -79,6 +101,10 @@ class Item < ActiveRecord::Base
NCRarities.include?(rarity_index)
end
def pb?
(self.description == PAINTBRUSH_SET_DESCRIPTION)
end
def owned?
@owned
end
@ -97,6 +123,14 @@ class Item < ActiveRecord::Base
@restricted_zones
end
def restricted_zone_ids
restricted_zones.map(&:id)
end
def occupied_zone_ids
occupied_zones.map(&:id)
end
def occupied_zones
all_body_ids = []
zone_body_ids = {}

View file

@ -0,0 +1,8 @@
class Item
module Search
def self.error(key, *args)
message = I18n.translate("items.search.errors.#{key}", *args)
raise Item::Search::Error, message
end
end
end

View file

@ -0,0 +1,7 @@
class Item
module Search
class Contradiction < Error
end
end
end

View file

@ -0,0 +1,7 @@
class Item
module Search
class Error < RuntimeError
end
end
end

View file

@ -0,0 +1,11 @@
class Item
module Search
class Field
attr_reader :key
def initialize(key)
@key = key
end
end
end
end

View file

@ -0,0 +1,20 @@
class Item
module Search
module Fields
class Flag < Field
def <<(filter)
if @value.nil?
@value = filter.positive?
elsif @value != filter.positive?
raise Item::Search::Contradiction,
"flag #{key} both positive and negative"
end
end
def to_flex_params
{key => @value}
end
end
end
end
end

View file

@ -0,0 +1,44 @@
class Item
module Search
module Fields
class SetField < Field
def initialize(*args)
super(*args)
@values = {true => Set.new, false => Set.new}
end
def <<(filter)
if filter.value.respond_to?(:each)
filter.value.each do |value|
add_value(value, filter.positive?)
end
else
add_value(filter.value, filter.positive?)
end
end
def to_flex_params
{
key => nil_if_empty(@values[true]),
:"negative_#{key}" => nil_if_empty(@values[false])
}
end
private
def add_value(value, is_positive)
if @values[!is_positive].include?(value)
raise Item::Search::Contradiction,
"positive #{key} and negative #{key} both contain #{value}"
end
@values[is_positive] << value
end
def nil_if_empty(set)
set unless set.empty?
end
end
end
end
end

View file

@ -0,0 +1,29 @@
class Item
module Search
module Fields
class TextField < Field
def initialize(*args)
super(*args)
@values = {true => '', false => ''}
end
def <<(filter)
@values[filter.positive?] << (filter.value + ' ')
end
def to_flex_params
{
key => nil_if_empty(@values[true]),
:"negative_#{key}" => nil_if_empty(@values[false])
}
end
private
def nil_if_empty(str)
str unless str.empty?
end
end
end
end
end

View file

@ -0,0 +1,17 @@
class Item
module Search
class Filter
attr_reader :key, :value
def initialize(key, value, is_positive)
@key = key
@value = value
@is_positive = is_positive
end
def positive?
@is_positive
end
end
end
end

View file

@ -0,0 +1,151 @@
class Item
module Search
class Query
FIELD_CLASSES = {
:is_nc => Fields::Flag,
:is_pb => Fields::Flag,
:species_support_id => Fields::SetField,
:occupied_zone_id => Fields::SetField,
:restricted_zone_id => Fields::SetField,
:name => Fields::TextField
}
def initialize(filters, user)
@filters = filters
end
def fields
initial_fields.tap do |fields|
@filters.each { |filter| fields[filter.key] << filter }
end
end
def to_flex_params
fields.values.map(&:to_flex_params).inject(&:merge)
end
def paginate(options={})
begin
flex_params = self.to_flex_params
rescue Item::Search::Contradiction
# If we have a contradictory query, no need to raise a stink about
# it, but no need to actually run a search, either.
return []
end
final_flex_params = {
:page => (options[:page] || 1),
:size => (options[:per_page] || 30)
}.merge(flex_params)
locales = I18n.fallbacks[I18n.locale] &
I18n.locales_with_neopets_language_code
final_flex_params[:locale] = locales.first
if final_flex_params[:name] || final_flex_params[:negative_name]
locale_entries = locales.map do |locale|
boost = (locale == I18n.locale) ? 4 : 1
{:locale => locale, :boost => boost}
end
if final_flex_params[:name]
final_flex_params[:_name_locales] = locale_entries
end
if final_flex_params[:negative_name]
final_flex_params[:_negative_name_locales] = locale_entries
end
end
result = FlexSearch.item_search(final_flex_params)
result.scoped_loaded_collection(:scopes => {'Item' => Item.with_translations})
end
# Load the text query labels from I18n, so that when we see, say,
# the filter "species:acara", we know it means species_support_id.
TEXT_KEYS_BY_LABEL = {}
I18n.available_locales.each do |locale|
TEXT_KEYS_BY_LABEL[locale] = {}
FIELD_CLASSES.keys.each do |key|
# A locale can specify multiple labels for a key by separating by
# commas: "occupies,zone,type"
labels = I18n.translate("items.search.labels.#{key}",
:locale => locale).split(',')
labels.each { |label| TEXT_KEYS_BY_LABEL[locale][label] = key }
end
end
TEXT_QUERY_RESOURCE_FINDERS = {
:species => lambda { |name|
species = Species.find_by_name(name)
unless species
Item::Search.error 'not_found.species', :species_name => name
end
species.id
},
:zone => lambda { |name|
zone_set = Zone.find_set(name)
unless zone_set
Item::Search.error 'not_found.zone', :zone_name => name
end
zone_set.map(&:id)
}
}
TEXT_QUERY_RESOURCE_TYPES_BY_KEY = {
:species_support_id => :species,
:occupied_zone_id => :zone,
:restricted_zone_id => :zone
}
TEXT_FILTER_EXPR = /([+-]?)(?:([a-z]+):)?(?:"([^"]+)"|(\S+))/
def self.from_text(text, user=nil)
filters = []
text.scan(TEXT_FILTER_EXPR) do |sign, label, quoted_value, unquoted_value|
label ||= 'name'
raw_value = quoted_value || unquoted_value
is_positive = (sign != '-')
if label == 'is'
# is-filters are weird. "-is:nc" is transposed to something more
# like "-nc:<nil>", then it's translated into a negative "is_nc"
# flag.
label = raw_value
raw_value = nil
end
key = TEXT_KEYS_BY_LABEL[I18n.locale][label]
if key.nil?
message = I18n.translate('items.search.errors.not_found.label',
:label => label)
raise Item::Search::Error, message
end
if TEXT_QUERY_RESOURCE_TYPES_BY_KEY.has_key?(key)
resource_type = TEXT_QUERY_RESOURCE_TYPES_BY_KEY[key]
finder = TEXT_QUERY_RESOURCE_FINDERS[resource_type]
value = finder.call(raw_value)
else
value = raw_value
end
filters << Filter.new(key, value, is_positive)
end
self.new(filters, user)
end
private
# The fields start out empty, then have the filters inserted into 'em,
# so that the fields can validate and aggregate their requirements.
def initial_fields
{}.tap do |fields|
FIELD_CLASSES.map do |key, klass|
fields[key] = klass.new(key)
end
end
end
end
end
end

36
config/flex.yml Normal file
View file

@ -0,0 +1,36 @@
# ANCHORS litheral key: it will not be used as template
# you can store here fragments of structures to reuse below
ANCHORS:
-
# This is a dynamic index name The settings and mapping below will work with any index.
# The default index name generated by Flex is usually <application_name>_<environment>,
# but you may have changed it in the initializers/flex.rb or you can hardcode it if you prefer.
<%= Flex::Configuration.variables[:index] %>:
settings:
number_of_shards: 5
number_of_replicas: 1
# add your custom mappings here
mappings:
item:
properties:
# Name is an object of locale fields, which are in turn multi_fields.
# First, an analyzed string for searching. Second, an untouched
# string for sorting. Elasticsearch requires that both be expliticly
# named in the mapping, but will handle the copy implicitly.
name:
type: object
properties:
<% I18n.usable_locales_with_neopets_language_code.each do |locale| %>
<%= locale %>:
type: multi_field
fields:
<%= locale %>:
type: string
index: analyzed
untouched:
type: string
index: not_analyzed
<% end %>

View file

@ -0,0 +1,44 @@
# see the detailed Configuration documentation at https://github.com/ddnexus/flex/wiki/Configuration
Flex::Configuration.configure do |config|
# you MUST add your indexed model names here
config.flex_models = %w[ Item ]
# Add the your result extenders here
config.result_extenders |= [ FlexSearchExtender ]
# Add the default variables here
# see also the details Variables documentation at https://github.com/ddnexus/flex/wiki/Variables
# config.variables.add :index => 'my_index',
# :type => 'project',
# :anything => 'anything
# The custom url of your ElasticSearch server
# config.base_uri = 'http://localhost:9200'
# Set it to true to log the debug infos (true by default in development mode)
# config.debug = false
# Debug info are actually valid curl commands
# config.debug_to_curl = false
# The custom logger you want Flex to use. Default Rails.logger
# config.logger = Logger.new(STDERR)
# Custom config file path
# config.config_file = '/custom/path/to/flex.yml',
# Custom flex dir path
# config.flex_dir = '/custom/path/to/flex',
# The custom http_client you may want to implement
# config.http_client = 'Your::Client'
# The options passed to the http_client. They are client specific.
# config.http_client_options = {:timeout => 5}
# Experimental: checks the response and return a boolean (should raise?)
# config.raise_proc = proc{|response| response.status >= 400}
end

View file

@ -32,6 +32,9 @@ config.each do |locale_str, locale_meta|
end
end
LocaleMeta::USABLE_LOCALES_WITH_NEOPETS_LANGUAGE_CODE = LocaleMeta::USABLE_LOCALES &
LocaleMeta::LOCALES_WITH_NEOPETS_LANGUAGE_CODE
module I18n
def self.public_locales
LocaleMeta::PUBLIC_LOCALES
@ -45,6 +48,10 @@ module I18n
LocaleMeta::LOCALES_WITH_NEOPETS_LANGUAGE_CODE
end
def self.usable_locales_with_neopets_language_code
LocaleMeta::USABLE_LOCALES_WITH_NEOPETS_LANGUAGE_CODE
end
def self.neopets_language_code_for(locale)
LocaleMeta::NEOPETS_LANGUAGE_CODES_BY_LOCALE[locale]
end

View file

@ -326,6 +326,21 @@ en:
header: Brought to you by
footer: Thanks!
search:
errors:
not_found:
label: Filter "%{label}" does not exist. Is it spelled correctly?
species:
Species "%{species_name}" does not exist. Is it spelled correctly?
zone: Zone "%{zone_name}" does not exist. Is it spelled correctly?
labels:
name: name
is_nc: nc
is_pb: pb
species_support_id: species
occupied_zone_id: occupies,zone,type
restricted_zone_id: restricts
neopets_pages:
create:
success: Page %{index} saved!

Binary file not shown.

BIN
vendor/cache/addressable-2.3.2.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/bullet-4.1.6.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/closure-compiler-1.1.8.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/dye-0.1.4.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/em-socksify-0.2.1.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/excon-0.16.10.gem vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/factory_girl-2.6.4.gem vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/fog-1.8.0.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/formatador-0.2.4.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/msgpack-0.4.7.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/multi_json-1.3.7.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/mysql2-0.2.18.gem vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/net-ssh-2.6.3.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/newrelic_rpm-3.5.5.38.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/nokogiri-1.5.6.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/parallel-0.5.21.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/patron-0.4.18.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/progressbar-0.11.0.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/prompter-0.1.5.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/rack-1.2.7.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/redis-3.0.2.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/redis-namespace-1.2.1.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/rufus-scheduler-2.0.17.gem vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/subexec-0.2.2.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/vegas-0.1.11.gem vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/cache/will_paginate-3.0.4.gem vendored Normal file

Binary file not shown.

BIN
vendor/cache/yard-0.8.3.gem vendored Normal file

Binary file not shown.