Extracting
1
|
|
Compressing
1
|
|
1
|
|
1
|
|
The documentation rspec formatter is nice to read, but the bad thing about it is that when a failure occurs, it doesn’t show a stack trace until the end of the test run. If you have a long running test suite, you might want to look into the first few failures you encounter while the test suite finishes running.
With this simple formatter, it accomplishes exactly that.
Now when the test suite runs, the stack trace gets printed right away upon failures.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
I recently released a gem that wraps the jQuery autoSuggest Plugin. It provides helpers that make it easy to use in Rails 3. It supports ActiveRecord, Mongoid, and MongoMapper. The code is hosted on github. Feel free to fork and improve it!
Include the gem on your Gemfile
1
|
|
Install it
1
|
|
Run the generator
1
|
|
And include jquery.autoSuggest.js
and autoSuggest.css
on your layouts or add them to your assets file
1 2 |
|
Assuming you have a Tag model:
1 2 3 4 5 6 |
|
Your controller will need an action to respond to the autosuggest textfield. To add it to your controller call the autosuggest method and pass it the name of the model and column name as in the following example:
1 2 3 |
|
This will create a autosuggest_tag_name
action. You then need to add a route for that action
1 2 3 |
|
From the view you can create an autosuggest field with the autosuggest_field_tag helper
1 2 3 4 5 6 7 8 9 |
|
You can also use the autosuggest_field
helper
1 2 3 |
|
By default, autosuggest only queries the db for existing entries, but if you want to be able to create new ones, just pass these options:
1
|
|
Then you can do whatever you want from the controller using params[:recipes][:new_tags]
These are the default options:
1 2 3 4 5 |
|
But you can pass options in by using the autosuggest_options
param
1
|
|
Here are the other options you can pass in:
asHtmlName
: string (false by default) – Enables you to specify your own custom name that will be attributed to the text
field
newValuesInputName
: string (false by default) – Enables you to define a name for a hidden field that will catch new names
that don’t match any in the db
asHtmlID
: string (false by default) – Enables you to specify your own custom ID that will be appended to the top level
AutoSuggest UL element’s ID name. Otherwise it will default to using a random ID. Example: id=“CUSTOM_ID”. This is also
applies to the hidden input filed that holds all of the selected values. Example: id=“as-values-CUSTOM_ID”
startText
: string (“Enter Name Here” by default) – Text to display when the AutoSuggest input field is empty.
emptyText
: string (“No Results” by default) – Text to display when their are no search results.
preFill
: object or string (empty object by default) – Enables you to pre-fill the AutoSuggest box with selections when the
page is first loaded. You can pass in a comma separated list of values (a string), or an object. When using a string, each
value is used as both the display text on the selected item and for it’s value. When using an object, the options
selectedItemProp will define the object property to use for the display text and selectedValuesProp will define the object
property to use for the value for the selected item. Note: you must setup your preFill object in that format. A preFill
object can look just like the example objects laid out above.
limitText
: string (“No More Selections Are Allowed” by default) – Text to display when the number of selections has reached
it’s limit.
selectedItemProp
: string (“value” by default) – Name of object property to use as the display text for each chosen item.
selectedValuesProp
: string (“value” by default) – Name of object property to use as the value for each chosen item. This
value will be stored into the hidden input field.
searchObjProps
: string (“value” by default) – Comma separated list of object property names. The values in these objects
properties will be used as the text to perform the search on.
queryParam
: string (“q” by default) – The name of the param that will hold the search string value in the AJAX request.
retrieveLimit
: number (false by default) – If set to a number, it will add a ‘&limit=’ param to the AJAX request. It also
limits the number of search results allowed to be displayed in the results dropdown box.
extraParams
: string (“” by default) – This will be added onto the end of the AJAX request URL. Make sure you add an ‘&’
before each param.
matchCase
: true or false (false by default) – Make the search case sensitive when set to true.
minChars
: number (1 by default) – Minimum number of characters that must be entered into the AutoSuggest input field before
the search begins.
keyDelay
: number (400 by default) – Number of milliseconds to delay after a keydown on the AutoSuggest input field and
before search is started.
resultsHighlight
: true or false (true by default) – Option to choose whether or not to highlight the matched text in each
result item.
neverSubmit
: true or false (false by default) – If set to true this option will never allow the ‘return’ key to submit the
form that AutoSuggest is a part of.
selectionLimit
: number (false by default) – Limits the number of selections that are allowed to be made to the number
specified.
showResultList
: true or false (true by default) – If set to false, the Results Dropdown List will never be shown at any
time.
start
: callback function – Custom function that is run only once on each AutoSuggest field when the code is first applied.
selectionClick
: callback function – Custom function that is run when a previously chosen item is clicked. The item that is
clicked is passed into this callback function as ‘elem’.
1
|
|
selectionAdded
: callback function – Custom function that is run when a selection is made by choosing one from the Results
dropdown, or by using the tab/comma keys to add one. The selection item is passed into this callback function as ‘elem’.
1
|
|
selectionRemoved
: callback function – Custom function that is run when a selection removed from the AutoSuggest by using
the delete key or by clicking the “x” inside the selection. The selection item is passed into this callback function as
‘elem’.
1
|
|
formatList
: callback function – Custom function that is run after all the data has been retrieved and before the results
are put into the suggestion results list. This is here so you can modify what & how things show up in the suggestion results
list.
beforeRetrieve
: callback function – Custom function that is run right before the AJAX request is made, or before the local
objected is searched. This is used to modify the search string before it is processed. So if a user entered “jim” into the
AutoSuggest box, you can call this function to prepend their query with “guy_”. Making the final query = “guy_jim”. The
search query is passed into this function. Example: beforeRetrieve: function(string){ return string; }
retrieveComplete
: callback function – Custom function that is run after the ajax request has completed. The data object
MUST be returned if this is used. Example: retrieveComplete: function(data){ return data; }
resultClick
: callback function – Custom function that is run when a search result item is clicked. The data from the item
that is clicked is passed into this callback function as ‘data’.
1
|
|
resultsComplete
: callback function – Custom function that is run when the suggestion results dropdown list is made visible.
Will run after every search query.
Envy Labs just released some Rails 3 cheat sheets to aid the API usage of several components. The pdf can be found here.
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 |
|
1 2 |
|
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1
|
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
1 2 3 4 5 |
|
After adding or removing dependencies from Gemfile
Commit Gemfile and Gemfile.lock After modifying existing dependency versions
$ bundle update
1
|
|
Copies all app gems to vendor/cache
1
|
|
Installs gems from vendor/cache - no external server communication
For more info, visit http://gembundler.com
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 |
|
1 2 3 4 |
|
1 2 3 4 5 6 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
Go to https://github.com/rails/jquery-ujs for instructions
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
1 2 3 4 5 6 7 8 9 |
|
SHORTCUTS
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Having different configurations for different environments can get messy especially as your project grows. Environment files start to get long and switching between all the different files becomes a hassle. One technique I like is to encapsulate all of the configuration variables in a YAML file and then loading it up into a global hash during initialization.
I recently dealt with a case using paperclip and had different settings depending on the environment. On production servers
we wanted to use s3 for storage and locally we wanted to use the filesystem. At first we set up constants (to hold paperclip
settings) in each of our environment files. So we had something like this in each of our environment(test.rb
,
development.rb
, production.rb
, etc) files:
1 2 3 4 5 6 7 |
|
In translating it to YAML (config/config.yml
in my case), it looked like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
And so now each environment can have its own configurations and it’s nicely encapsulated in one file. You may notice that we
have embedded ruby in the YAML file. We just have to feed it into ERB when we load the YAML. Let’s take a look at
config/initializers/config.rb
:
1
|
|
You can actually ignore the recursive_symbolize_keys, as I only had to do that since paperclip only takes symbolized arguments. While this snippet of code isn’t the prettiest, it works well and enables global config encapsulation. First it’s reading the YAML file, interpreting the ruby code, converting it into a hash, and then finally storing it into a constant.
Surprisingly there isn’t a Hash#recursive_symbolize_keys
method so here’s code to accomplish that:
1 2 3 4 5 6 7 |
|
Sometimes gems/plugins only take arguments in the form of symbols so this can method can be handy if you have some sort of nested config hash.
Credits to: http://grosser.it/2009/04/14/recursive-symbolize_keys/
To make capistrano build your gems with bundler you can use the following code snippet:
1 2 3 4 5 6 7 8 9 |
|
Of course, this is assuming that you already have bundler installed on your remote server.
Sunspot is a ruby driver for Solr and is pretty easy to integrate into rails using sunspot_rails.
First add it to your Gemfile:
1
|
|
Update your bundle:
1
|
|
Run this task to create your sunspot.yml
file:
1
|
|
To start the sunspot server run:
1
|
|
You probably don’t need the rails env variable set but I usually do it to be explicit. The first time you run this command,
it will create a solr/ directory
in your Rails root. This contains Solr’s configuration, as well as the actual data files
for the Solr index. You’ll probably want to add solr/data
to your .gitignore
.
There are two ways to setup your models for indexing. First way (and more appropriate for rails) is to use the ‘searchable’ macro. Suppose we have a model called Provider with first_name, middle_name, and last_name columns in the database. We can setup those fields to indexing with the following:
1 2 3 4 5 |
|
The second way is the following:
1 2 3 |
|
This code can be stored at the end of the model (outside of the class), or in an initializer, though it isn’t too pretty. For more information on setting up classes with search and indexing, check out this page
To reindex, run the following rake task:
1
|
|
You can also reindex in the console by running:
1
|
|
Normally I use before(:each)
blocks to set up my data, but setting up search data is a use case for using a before(:all)
block. With search, we’re not manipulating the data, so having test data setup before all search specs is not only
acceptable, but efficient. Below are specs for testing that a provider can be found by all parts of his/her name:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
One gotcha. Don’t forget to start your sunspot server in the test environment:
1
|
|
If you’re not already using RVM, I’d highly recommend it as it makes it easier to manage different versions of ruby. You can have different projects running on different versions of ruby and switch rubies with ease. One way to make this easier is to make use of the .rvmrc file. It will automatically switch to the ruby version that your project is running on when you cd into it.
Suppose we have a rails project called donut running on ruby 1.9.2.
1
|
|
Once in the rails root of the project, create a file called .rvmrc
and add this:
1
|
|
To list known rubies you can use this:
1
|
|
Now when you cd into the directory, it will automatically use ruby 1.9.2.
1 2 3 4 |
|
Notice that it is using the gemset donut. Gemsets are basically compartmentalized ruby setups. Gems installed in this gemset will be separated from other projects (assuming they use different gemsets). You can read more about it here
You can dump the database into a file using:
1
|
|
You can load the dump into the database using:
1
|
|