Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Update to 1.9-style hash syntax #359

Merged
merged 6 commits into from

2 participants

This page is out of date. Refresh to see the latest.
View
70 source/projects/blogger.markdown
@@ -315,7 +315,7 @@ Now refresh your browser. The error message changed, but you've still got an err
```plain
Template is missing
-Missing template articles/index, application/index with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/Users/you/projects/blogger/app/views"
+Missing template articles/index, application/index with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/Users/you/projects/blogger/app/views"
```
The error message is pretty helpful here. It tells us that the app is looking for a (view) template in `app/views/articles/` but it can't find one named `index.erb`. Rails has *assumed* that our `index` action in the controller should have a corresponding `index.erb` view template in the views folder. We didn't have to put any code in the controller to tell it what view we wanted, Rails just figures it out.
@@ -401,20 +401,20 @@ We'll use the `link_to` helper, we want it to display the text `"Create a New Ar
But wait, there's one more thing. Our stylesheet for this project is going to look for a certain class on the link to make it look fancy. To add HTML attributes to a link, we include them in a Ruby hash style on the end like this:
```ruby
-<%= link_to article.title, article_path(article), :class => 'article_title' %>
+<%= link_to article.title, article_path(article), class: 'article_title' %>
```
Or, if you wanted to also have a CSS ID attribute:
```ruby
<%= link_to article.title, article_path(article),
- :class => 'article_title', :id => "article_#{article.id}" %>
+ class: 'article_title', id: "article_#{article.id}" %>
```
Use that technique to add the CSS class `new_article` to your "Create a New Article" link.
```ruby
-<%= link_to "Create a New Article", new_article_path, :class => "new_article" %>
+<%= link_to "Create a New Article", new_article_path, class: "new_article" %>
```
#### Review the Results
@@ -655,8 +655,8 @@ To clean it up, let me first show you a second way to create an instance of `Art
```ruby
def create
@article = Article.new(
- :title => params[:article][:title],
- :body => params[:article][:body])
+ title: params[:article][:title],
+ body: params[:article][:body])
@article.save
redirect_to article_path(@article)
end
@@ -748,7 +748,7 @@ You can't, exactly. Browsers should implement all four verbs, `GET`, `PUT`, `POS
Rails' solution to this problem is to *fake* a `DELETE` verb. In your view template, you can add another attribute to the link like this:
```erb
-<%= link_to "delete", article_path(@article), :method => :delete %>
+<%= link_to "delete", article_path(@article), method: :delete %>
```
Through some JavaScript tricks, Rails can now pretend that clicking this link triggers a `DELETE`. Try it in your browser.
@@ -770,7 +770,7 @@ Do that now on your own and test it.
There's one more parameter you might want to add to your `link_to` call:
```ruby
-:confirm => "Really delete the article?"
+confirm: "Really delete the article?"
```
This will popup a JavaScript dialog when the link is clicked. The Cancel button will stop the request, while the OK button will submit it for deletion.
@@ -843,7 +843,7 @@ Open your `app/views/articles/new.html.erb` and CUT all the text from and includ
Add the following code to that view:
```ruby
-<%= render :partial => 'form' %>
+<%= render partial: 'form' %>
```
Now go back to the `_form.html.erb` and paste the code from your clipboard.
@@ -1045,7 +1045,7 @@ c = a.comments.new
c.author_name = "Daffy Duck"
c.body = "I think this article is thhh-thhh-thupid!"
c.save
-d = a.comments.create(:author_name => "Chewbacca", :body => "RAWR!")
+d = a.comments.create(author_name: "Chewbacca", body: "RAWR!")
```
For the first comment, `c`, I used a series of commands like we've done before. For the second comment, `d`, I used the `create` method. `new` doesn't send the data to the database until you call `save`. With `create` you build and save to the database all in one step.
@@ -1065,7 +1065,7 @@ We want to display any comments underneath their parent article. Open `app/views
```ruby
<h3>Comments</h3>
-<%= render :partial => 'comment', :collection => @article.comments %>
+<%= render partial: 'comment', collection: @article.comments %>
```
This renders a partial named `"comment"` and that we want to do it once for each element in the collection `@article.comments`. We saw in the console that when we call the `.comments` method on an article we'll get back an array of its associated comment objects. This render line will pass each element of that array one at a time into the partial named `"comment"`. Now we need to create the file `app/views/articles/_comment.html.erb` and add this code:
@@ -1092,7 +1092,7 @@ But, in reality, we expect to enter the comment directly on the article page. Le
Just above the "Back to Articles List" in the articles `show.html.erb`:
```ruby
-<%= render :partial => 'comment_form' %>
+<%= render partial: 'comment_form' %>
```
This is expecting a file `app/views/articles/_comment_form.html.erb`, so create that and add this starter content:
@@ -1346,14 +1346,14 @@ In `app/models/article.rb`:
```ruby
has_many :taggings
- has_many :tags, :through => :taggings
+ has_many :tags, through: :taggings
```
In `app/models/tag.rb`:
```ruby
has_many :taggings
- has_many :articles, :through => :taggings
+ has_many :articles, through: :taggings
```
Now if we have an object like `article` we can just ask for `article.tags` or, conversely, if we have an object named `tag` we can ask for `tag.articles`.
@@ -1492,7 +1492,7 @@ tag = Tag.find_or_create_by_name(tag_name)
Once we find or create the `tag`, we need to create a `tagging` which connects this article (here `self`) to the tag like this:
```ruby
-self.taggings.build(:tag => tag)
+self.taggings.build(tag: tag)
```
The `build` method is a special creation method. It doesn't need an explicit save, Rails will wait to save the Tagging until the Article itself it saved. So, putting these pieces together, your `tag_list=` method should look like this:
@@ -1503,7 +1503,7 @@ The `build` method is a special creation method. It doesn't need an explicit sav
tag_names.each do |tag_name|
tag = Tag.find_or_create_by_name(tag_name)
- self.taggings.build(:tag => tag)
+ self.taggings.build(tag: tag)
end
end
```
@@ -1514,7 +1514,7 @@ Go back to your console and try these commands:
```ruby
reload!
-a = Article.new(:title => "A Sample Article for Tagging!",:body => "Great article goes here", :tag_list => "ruby, technology")
+a = Article.new(title: "A Sample Article for Tagging!", body: "Great article goes here", tag_list: "ruby, technology")
```
Whoops!
@@ -1540,7 +1540,7 @@ using that pesky mass-assignment. Let's write it like this instead:
```ruby
reload!
-a = Article.new(:title => "A Sample Article for Tagging!",:body => "Great article goes here", :tag_list => "ruby, technology")
+a = Article.new(title: "A Sample Article for Tagging!", body: "Great article goes here", tag_list: "ruby, technology")
a.save
a.tags
```
@@ -1668,7 +1668,7 @@ Refresh your view and you should see a list of articles with that tag. Keep in m
We've built the `show` action, but the reader should also be able to browse the tags available at `http://localhost:3000/tags/`. I think you can do this on your own. Create an `index` action in your `tags_controller.rb` and an `index.html.erb` in the corresponding views folder. Look at your `articles_controller.rb` and Article `index.html.erb` if you need some clues.
-If that's easy, try creating a `destroy` method in your `tags_controller.rb` and adding a destroy link to the tag list. If you do this, change the association in your `tag.rb` so that it says `has_many :taggings, :dependent => :destroy`. That'll prevent orphaned Tagging objects from hanging around.
+If that's easy, try creating a `destroy` method in your `tags_controller.rb` and adding a destroy link to the tag list. If you do this, change the association in your `tag.rb` so that it says `has_many :taggings, dependent: :destroy`. That'll prevent orphaned Tagging objects from hanging around.
With that, a long Iteration 3 is complete!
@@ -1774,7 +1774,7 @@ First we'll add the ability to upload the file when editing the article, then we
In the very first line, we need to specify that this form needs to accept "multipart" data. This is an instruction to the browser about how to submit the form. Change your top line so it looks like this:
```ruby
-<%= form_for(@article, :html => {:multipart => true}) do |f| %>
+<%= form_for(@article, html: {multipart: true}) do |f| %>
```
Then further down the form, right before the paragraph with the save button, let's add a label and field for the file uploading:
@@ -1841,7 +1841,7 @@ Yes, a model (in our case an article) could have many attachments instead of jus
Paperclip supports automatic image resizing and it's easy. In your model, you'd add an option like this:
```ruby
-has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
+has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }
```
This would automatically create a "medium" size where the largest dimension is 300 pixels and a "thumb" size where the largest dimension is 100 pixels. Then in your view, to display a specific version, you just pass in an extra parameter like this:
@@ -1926,7 +1926,7 @@ In this layout we'll put the view code that we want to render for every view tem
%html
%head
%title Blogger
- = stylesheet_link_tag "application", :media => "all"
+ = stylesheet_link_tag "application", media: "all"
= javascript_include_tag "application"
= csrf_meta_tags
%body
@@ -2044,7 +2044,7 @@ First, delete the file `public/index.html` if you haven't already. Files in the
Second, open `config/routes.rb` and right above the other routes add in this one:
```ruby
-root :to => 'articles#index'
+root to: 'articles#index'
```
Now visit `http://localhost:3000` and you should see your article list.
@@ -2116,7 +2116,7 @@ Now that we've updated our Author form we can open the model file and add a vali
```ruby
class Author < ActiveRecord::Base
authenticates_with_sorcery!
- validates_confirmation_of :password, :message => "should match confirmation", :if => :password
+ validates_confirmation_of :password, message: "should match confirmation", if: :password
end
```
@@ -2158,17 +2158,17 @@ class AuthorSessionsController < ApplicationController
end
def create
- if @author = login(params[:username], params[:password])
- redirect_back_or_to(articles_path, :message => 'Logged in successfully.')
+ if @author == login(params[:username], params[:password])
+ redirect_back_or_to(articles_path, message: 'Logged in successfully.')
else
flash.now.alert = "Login failed."
- render :action => :new
+ render action: :new
end
end
def destroy
logout
- redirect_to(:authors, :message => 'Logged out!')
+ redirect_to(:authors, message: 'Logged out!')
end
end
```
@@ -2180,7 +2180,7 @@ Let's create the template for the `new` action that contains the login form, in
```ruby
%h1 Login
-= form_tag author_sessions_path, :method => :post do
+= form_tag author_sessions_path, method: :post do
.field
= label_tag :username
= text_field_tag :username
@@ -2202,8 +2202,8 @@ Next we need some routes so we can access those actions from our browser. Open u
```ruby
resources :author_sessions
-match 'login' => 'author_sessions#new', :as => :login
-match 'logout' => 'author_sessions#destroy', :as => :logout
+match 'login' => 'author_sessions#new', as: :login
+match 'logout' => 'author_sessions#destroy', as: :logout
```
With the last two lines, we created the named routes helpers `login_path`/`login_url` and `logout_path`/`logout_url`. Now we can go back to our footer in `app/views/layouts/application.html.haml` and update it to include some links:
@@ -2238,7 +2238,7 @@ That way when the app is first setup we can create an account, then new users ca
We can create a `before_filter` which will run _before_ the `new` and `create` actions of our `authors_controller.rb`. Open that controller and put all this code:
```ruby
- before_filter :zero_authors_or_authenticated, :only => [:new, :create]
+ before_filter :zero_authors_or_authenticated, only: [:new, :create]
def zero_authors_or_authenticated
unless Author.count == 0 || current_user
@@ -2262,10 +2262,10 @@ Then try to reach the registration form and it should work! Create yourself an
The first thing we need to do is sprinkle `before_filters` on most of our controllers:
-* In `authors_controller`, add a before filter to protect the actions besides `new` and `create` like this:<br/>`before_filter :require_login, :except => [:new, :create]`
+* In `authors_controller`, add a before filter to protect the actions besides `new` and `create` like this:<br/>`before_filter :require_login, except: [:new, :create]`
* In `author_sessions_controller` all the methods need to be accessible to allow login and logout
-* In `tags_controller`, we need to prevent unauthenticated users from deleting the tags, so we protect just `destroy`. Since this is only a single action we can use `:only` like this:<br/>`before_filter :require_login, :only => [:destroy]`
-* In `comments_controller`, we never implemented `index` and `destroy`, but just in case we do let's allow unauthenticated users to only access `create`:<br/>`before_filter :require_login, :except => [:create]`
+* In `tags_controller`, we need to prevent unauthenticated users from deleting the tabs, so we protect just `destroy`. Since this is only a single action we can use `:only` like this:<br/>`before_filter :require_login, only: [:destroy]`
+* In `comments_controller`, we never implemented `index` and `destroy`, but just in case we do let's allow unauthenticated users to only access `create`:<br/>`before_filter :require_login, except: [:create]`
* In `articles_controller` authentication should be required for `new`, `create`, `edit`, `update` and `destroy`. Figure out how to write the before filter using either `:only` or `:except`
Now our app is pretty secure, but we should hide all those edit, destroy, and new article links from unauthenticated users.
View
6 source/projects/eventmanager.markdown
@@ -181,7 +181,7 @@ The data file begins with a row of headers labeling each column. The CSV library
Look in your `initialize` method, and add the extra `:headers` parameter to the `@file` line like this:
```ruby
-@file = CSV.open(filename, {:headers => true})
+@file = CSV.open(filename, {headers: true})
```
Run your existing `print_names` method and it should still work the same.
@@ -206,7 +206,7 @@ When you look at the output, you'll see that `line` now looks like a Hash. It ha
It's annoying that the weird header name formatting, with its inconsistent capitalization, is now polluting our program. The CSV library provides a way to help standardize the headers, triggered by adding another option to the loading:
```ruby
-@file = CSV.open(filename, {:headers => true, :header_converters => :symbol})
+@file = CSV.open(filename, {headers: true, header_converters: :symbol})
```
Now, in your `print_names` method, use `.inspect` to look at the structure of the `line` object. Update your `puts` instruction to use the newly standardized column names.
@@ -646,7 +646,7 @@ Now what can we actually DO with the `Sunlight` library? Check out the README o
We're interested in the `Legislator` object. Looking at the examples in the ReadMe you'll see this:
```ruby
-congresspeople = Sunlight::Legislator.all_for(:address => "123 Fifth Ave New York, NY 10003")
+congresspeople = Sunlight::Legislator.all_for(address: "123 Fifth Ave New York, NY 10003")
```
That's how to fetch information for a specific address, but our task is to find them via zipcode. Look back at the URL we used to view the XML. See how it has `legislators.allForZip`? The wrapper library should have a similar method. If you dig into the project's source code, open the `lib` folder, open the `sunlight` folder, then `legislator.rb`. Search the page for `zipcode` and find a method that starts like this:
View
114 source/projects/jscontact.textile
@@ -230,7 +230,7 @@ That sets us up to use Ryan's "nifty" scaffolding. Let's then generate a scaffol
rails generate nifty:scaffold Person first_name:string last_name:string
</pre>
-The first line of the output shows Ryan sneaking the @"mocha"@ gem into our Gemfile. To clean things up, let's move the gem dependency into the development/test block we already have. By doing this, you can remove @:group => :test@ from the @gem "mocha"@ line. Run @bundle@ and then run the migration with @rake db:migrate@.
+The first line of the output shows Ryan sneaking the @"mocha"@ gem into our Gemfile. To clean things up, let's move the gem dependency into the development/test block we already have. By doing this, you can remove @group: :test@ from the @gem "mocha"@ line. Run @bundle@ and then run the migration with @rake db:migrate@.
The generators created test-related files for us. They saw that we're using RSpec and created corresponding controller and model test files. Let's run those tests now:
@@ -300,7 +300,7 @@ First we'll implement the existing example to actually check that @first_name@ c
<pre class="brush:ruby">
it "should not be valid without a first name" do
- person = Person.new(:first_name => nil)
+ person = Person.new(first_name: nil)
person.should_not be_valid
end
</pre>
@@ -327,7 +327,7 @@ The test failed because it expected a person with no first name to be invalid, b
class Person < ActiveRecord::Base
attr_accessible :first_name, :last_name
- validates :first_name, :presence => true
+ validates :first_name, presence: true
end
</pre>
@@ -350,7 +350,7 @@ It's the other test! Now the first test fails because the blank @Person@ isn't v
<pre class="brush:ruby">
it "should be valid" do
- person = Person.new(:first_name => "Sample", :last_name => "Person")
+ person = Person.new(first_name: "Sample", last_name: "Person")
person.should be_valid
end
</pre>
@@ -369,8 +369,7 @@ First, just below the @describe@ line of our @person_spec@, let's add this code
<pre class="brush:ruby">
before(:each) do
- @person = Person.new(:first_name => "John",
- :last_name => "Doe")
+ @person = Person.new(first_name: "John", last_name: "Doe")
end
</pre>
@@ -391,8 +390,7 @@ The @before(:each)@ clause we wrote will make writing test examples a lot easier
<pre class="brush:ruby">
it "should be valid" do
- person = Person.new(:first_name => "Sample",
- :last_name => "Person")
+ person = Person.new(first_name: "Sample", last_name: "Person")
person.should be_valid
end
</pre>
@@ -488,7 +486,7 @@ Try it out yourself by going into the console via @rails console@ and adding a p
<pre class="console">
p = Person.first
-p.phone_numbers.create(:number => '2024605555')
+p.phone_numbers.create(number: '2024605555')
</pre>
h4. Validating Phone Numbers
@@ -549,8 +547,8 @@ Still have one test failing? Look carefully at *which* test is failing. It's now
<pre class="brush:ruby">
before(:each) do
- @person = Person.create(:first_name => "Sample", :last_name => "Name")
- @phone_number = @person.phone_numbers.create(:number => "2024605555")
+ @person = Person.create(first_name: "Sample", last_name: "Name")
+ @phone_number = @person.phone_numbers.create(number: "2024605555")
end
</pre>
@@ -619,8 +617,8 @@ Now, inside the inner @describe@ block, let's write an example. Name it @outputs
<pre class="brush:ruby">
describe "print_numbers" do
it "should output a comma-separated list of phone numbers" do
- number_a = PhoneNumber.new(:number => "1234567")
- number_b = PhoneNumber.new(:number => "7654321")
+ number_a = PhoneNumber.new(number: "1234567")
+ number_b = PhoneNumber.new(number: "7654321")
phone_numbers = [number_a, number_b]
print_numbers(phone_numbers).should == "1234567, 7654321"
end
@@ -710,7 +708,7 @@ When you look at the form you'll see the *Person* text field, expecting the user
When you write a path like @new_phone_number_path()@ you can pass in extra data. Anything you put into the parentheses will be sent as GET-style parameters in the URL. Back on the person's @show@ page, let's change the link to it includes the person's ID:
<pre class="brush:ruby">
-<%= link_to "Add a New Phone Number", new_phone_number_path(:person_id => @person.id ) %>
+<%= link_to "Add a New Phone Number", new_phone_number_path(person_id: @person.id ) %>
</pre>
Go back to the show page in your browser, refresh, and click the link. See how the @person_id@ is now embedded in the URL? We're part way there, but the value isn't in the "Person" text box yet.
@@ -721,7 +719,7 @@ To make this work, we need to open @app/controllers/phone_numbers_controller.rb@
<pre class="brush:ruby">
def new
- @phone_number = PhoneNumber.new(:person_id => params[:person_id])
+ @phone_number = PhoneNumber.new(person_id: params[:person_id])
end
</pre>
@@ -775,11 +773,11 @@ Create a new folder named @/spec/integration/@. In that folder let's make a file
require 'spec_helper'
require 'capybara/rspec'
- describe "the views for people", :type => :request do
+ describe "the views for people", type: :request do
before(:all) do
- @person = Person.create(:first_name => "John", :last_name => "Doe")
- number_a = @person.phone_numbers.create(:number => "1234567")
- number_b = @person.phone_numbers.create(:number => "7654321")
+ @person = Person.create(first_name: "John", last_name: "Doe")
+ number_a = @person.phone_numbers.create(number: "1234567")
+ number_b = @person.phone_numbers.create(number: "7654321")
end
describe "when looking at a single person" do
@@ -789,7 +787,7 @@ Create a new folder named @/spec/integration/@. In that folder let's make a file
it "should have edit links for each phone number" do
@person.phone_numbers.each do |phone_number|
- page.should have_link("edit", :href => edit_phone_number_path(phone_number))
+ page.should have_link("edit", href: edit_phone_number_path(phone_number))
end
end
end
@@ -809,7 +807,7 @@ Open the @/views/people/show.html.erb@ template and replace...
With a call to @render@ and a partial...
<pre class="brush:ruby">
- <%= render :partial => 'phone_numbers' %>
+ <%= render partial: 'phone_numbers' %>
</pre>
If you refresh your browser it'll crash because there is no partial named "phone_numbers".
@@ -835,7 +833,7 @@ Open the index page in the browser and boom, it'll crash. The partial is expecti
Instead we need to pass in the phone numbers, just like we did with the helper. Here's the Rails 3 way to do it:
<pre class="brush:ruby">
- <%= render :partial => 'phone_numbers', :object => person.phone_numbers %>
+ <%= render partial: 'phone_numbers', object: person.phone_numbers %>
</pre>
Whatever you pass in as the @object@ argument will get assigned to the local variable with the same name as the partial itself. Then in the partial change the iteration line to use that local like this...
@@ -963,7 +961,7 @@ Before you play with displaying addresses, create a few of them manually in the
* Open the @people_views_spec.rb@
* Within the single person context, write a test named @"should display each of the email addresses"@ that looks for a UL with LIs for each address. Try using this:
<pre class="brush:ruby">
- page.should have_selector('li', :text => email_address.address)
+ page.should have_selector('li', text: email_address.address)
</pre>
* Make sure the test *fails*. If it passes unexpectedly, make sure that your person has one or more email addresses.
* Add a paragraph to the person's @show@ template that renders a partial named @email_addresses@ which, like @phone_numbers@, renders a UL with LIs for each @EmailAddress@
@@ -1101,7 +1099,7 @@ It should feel like something's not right here. Let's write a new spec that bett
<pre class="brush:ruby">
it "should respond with its phone numbers after they're created" do
- phone_number = @company.phone_numbers.build(:number => "2223334444")
+ phone_number = @company.phone_numbers.build(number: "2223334444")
@company.phone_numbers.should include(phone_number)
end
</pre>
@@ -1141,7 +1139,7 @@ Let's start with the @Person@ model, since that had passing tests before the mig
We just need to tell the relationship which "polymorphic interface" to use:
<pre class="brush:ruby">
- has_many :phone_numbers, :as => :contact
+ has_many :phone_numbers, as: :contact
</pre>
The tests aren't any better. We need to tell the @PhoneNumber@ about the polymorphism too. Change these:
@@ -1154,7 +1152,7 @@ The tests aren't any better. We need to tell the @PhoneNumber@ about the polymor
To this:
<pre class="brush:ruby">
- belongs_to :contact, :polymorphic => true
+ belongs_to :contact, polymorphic: true
</pre>
Now the models are properly associated, but my tests still look terrible. Maybe they need some revision.
@@ -1188,13 +1186,13 @@ I have one integration test failing when it tries to exercise the delete functio
Open up the controller and I find it's the redirect that's crashing. I currently have this:
<pre class="brush:ruby">
- redirect_to @phone_number.person, :notice => "Successfully destroyed phone number."
+ redirect_to @phone_number.person, notice: "Successfully destroyed phone number."
</pre>
This kind of issue is *why we do TDD*. A human tester is unlikely to have caught this crash, but the automated tests save our butts. It's a simple fix, thanks to Rails' built in redirect intelligence:
<pre class="brush:ruby">
- redirect_to @phone_number.contact, :notice => "Successfully destroyed phone number."
+ redirect_to @phone_number.contact, notice: "Successfully destroyed phone number."
</pre>
Rails will _automatically_ figure out what class type @contact@ is and go to the appropriate @show@ page for that object.
@@ -1382,13 +1380,13 @@ We want this before filter to only run for certain actions. Go back to the top o
...to run only for the listed actions...
<pre class="brush:ruby">
- before_filter :lookup_phone_number, :only => [:edit, :update, :destroy]
+ before_filter :lookup_phone_number, only: [:edit, :update, :destroy]
</pre>
Or, you can even use the reverse logic:
<pre class="brush:ruby">
- before_filter :lookup_phone_number, :except => [:new, :create]
+ before_filter :lookup_phone_number, except: [:new, :create]
</pre>
Run your tests and they should be *passing*.
@@ -1443,8 +1441,8 @@ h3. Removing Model Duplication
If you look at the @Person@ and @Company@ models you'll see there are two lines exactly duplicated in each:
<pre class="brush:ruby">
- has_many :phone_numbers, :as => :contact
- has_many :email_addresses, :as => :contact
+ has_many :phone_numbers, as: :contact
+ has_many :email_addresses, as: :contact
</pre>
Essentially each of these models shares the concept of a "contact," but we decided not to go down the dark road of STI. Instead, we should abstract their common code into a module. Right now it's only two lines, but over time the common code will likely increase. The module will be the place for common code to live.
@@ -1508,13 +1506,13 @@ Here's how to remove the duplication:
* Open both the @views/companies/index.html.erb@ and @views/companies/show.html.erb@. Each of them renders the partial. You just need to change this:
<pre class="brush:ruby">
- <%= render :partial => "phone_numbers", :object => company.phone_numbers %>
+ <%= render partial: "phone_numbers", object: company.phone_numbers %>
</pre>
To have the folder in the partial name like this:
<pre class="brush:ruby">
- <%= render :partial => "phone_numbers/phone_numbers", :object => company.phone_numbers %>
+ <%= render partial: "phone_numbers/phone_numbers", object: company.phone_numbers %>
</pre>
That should bring you back to green. Then...
@@ -1632,7 +1630,7 @@ Let's write a quick integration test. In the @email_addresses_views_spec@ we hav
<pre class="brush:ruby">
it "should show the contact's name in the title" do
- page.should have_selector("h1", :text => "#{@person.last_name}, #{@person.first_name}")
+ page.should have_selector("h1", text: "#{@person.last_name}, #{@person.first_name}")
end
</pre>
@@ -1683,12 +1681,12 @@ My ERB template looks like this:
<% @companies.each do |company| %>
<div class="company">
<h4><%= company.name %></h4>
- <%= render :partial => 'email_addresses/email_addresses', :object => company.email_addresses %>
- <%= render :partial => 'phone_numbers/phone_numbers', :object => company.phone_numbers %>
+ <%= render partial: 'email_addresses/email_addresses', object: company.email_addresses %>
+ <%= render partial: 'phone_numbers/phone_numbers', object: company.phone_numbers %>
<ul class="actions">
<%= link_to "Show", company %>
<%= link_to "Edit", edit_company_path(company) %>
- <%= link_to "Destroy", company, :confirm => 'Are you sure?', :method => :delete %>
+ <%= link_to "Destroy", company, confirm: 'Are you sure?', method: :delete %>
</ul>
</div>
<% end %>
@@ -1719,12 +1717,12 @@ Here's my completed @index.html.haml@ for reference.
- @companies.each do |company|
.company
%h4= company.name
- = render :partial => 'email_addresses/email_addresses', :object => company.email_addresses
- = render :partial => 'phone_numbers/phone_numbers', :object => company.phone_numbers
+ = render partial: 'email_addresses/email_addresses', object: company.email_addresses
+ = render partial: 'phone_numbers/phone_numbers', object: company.phone_numbers
%ul.actions
= link_to "Show", company
= link_to "Edit", edit_company_path(company)
- = link_to "Destroy", company, :confirm => 'Are you sure?', :method => :delete
+ = link_to "Destroy", company, confirm: 'Are you sure?', method: :delete
%p= link_to "New Company", new_company_path
</pre>
@@ -1804,7 +1802,7 @@ The way this authentication works is that your app redirects to the third party
Open @/app/config/routes.rb@ and add this line:
<pre class="brush:ruby">
- match '/auth/:provider/callback', :to => 'sessions#create'
+ match '/auth/:provider/callback', to: 'sessions#create'
</pre>
Re-visit @http://localhost:8080/auth/twitter@, it will process your already-existing Twitter login, then redirect back to your application and give you *Uninitialized Constant SessionsController*. Our router is attempting to call the @create@ action of the @SessionsController@, but that controller doesn't exist yet.
@@ -1822,7 +1820,7 @@ Then open up that controller file and add code so it looks like this:
<pre class="brush:ruby">
class SessionsController < ApplicationController
def create
- render :text => debug request.env["omniauth.auth"]
+ render text: debug request.env["omniauth.auth"]
debugger
end
end
@@ -1883,7 +1881,7 @@ Now, back to @SessionsController@, let's add a redirect action to send them to t
<pre class="brush:ruby">
def create
@user = User.find_or_create_by_auth(request.env["omniauth.auth"])
- redirect_to companies_path, :notice => "Logged in as #{@user.name}"
+ redirect_to companies_path, notice: "Logged in as #{@user.name}"
end
</pre>
@@ -1899,9 +1897,9 @@ Open @/app/views/layouts/application.html.erb@ and you'll see the framing for al
<div id="account">
<% if current_user %>
<span>Welcome, <%= current_user.name %></span>
- <%= link_to "logout", logout_path, :id => "login" %>
+ <%= link_to "logout", logout_path, id: "login" %>
<% else %>
- <%= link_to "login", login_path, :id => "logout" %>
+ <%= link_to "login", login_path, id: "logout" %>
<% end %>
</div>
</pre>
@@ -1933,8 +1931,8 @@ Just because we're following the REST convention doesn't mean we can't also crea
Open @/config/routes.rb@ and add two custom routes:
<pre class="brush:ruby">
- match "/login" => redirect("/auth/twitter"), :as => :login
- match "/logout" => "sessions#destroy", :as => :logout
+ match "/login" => redirect("/auth/twitter"), as: :login
+ match "/logout" => "sessions#destroy", as: :logout
</pre>
The first line creates a path named @login@ which just redirects to the static address @/auth/twitter@ which will be intercepted by the OmniAuth middleware. The second line creates a @logout@ path which will call the destroy action of our @SessionsController@.
@@ -1949,7 +1947,7 @@ Our login works great, but we can't logout! When you click the logout link it's
* Add a @destroy@ method
* In the method, erase the session by setting @session[:user_id] = nil@
* Redirect them to the @root_path@ with the notice @"Goodbye!"@
-* Define a @root_path@ in your router like this: @root :to => "companies#index"@
+* Define a @root_path@ in your router like this: @root to: "companies#index"@
Now try logging out and you'll probably end up looking at the Rails "Welcome Aboard" page. Why isn't your @root_path@ taking affect?
@@ -2001,7 +1999,7 @@ We can also change the behavior of Rails generators to create fabrication patter
<pre class="brush:ruby">
config.generators do |g|
- g.test_framework :rspec, :fixture => true
+ g.test_framework :rspec, fixture: true
g.fixture_replacement :fabrication
end
</pre>
@@ -2234,9 +2232,9 @@ We're working towards a refactoring of the integration tests. Let's build up som
user!
end
- Fabricator(:person_with_details, :from => :person) do
- email_addresses!(:count => 2){|person, i| Fabricate(:email_address, :address => "sample_#{i}@sample.com", :contact => person)}
- phone_numbers!(:count => 2){|person, i| Fabricate(:phone_number, :number => "#{i.to_s*10}", :contact => person)}
+ Fabricator(:person_with_details, from: :person) do
+ email_addresses!(count: 2){|person, i| Fabricate(:email_address, address: "sample_#{i}@sample.com", contact: person)}
+ phone_numbers!(count: 2){|person, i| Fabricate(:phone_number, number: "#{i.to_s*10}", contact: person)}
end
</pre>
@@ -2249,12 +2247,12 @@ We're working towards a refactoring of the integration tests. Let's build up som
uid {Fabricate.sequence(:uid)}
end
- Fabricator(:user_with_people, :from => :user) do
- people!(:count => 3){|user, i| Fabricate(:person, :first_name => "Sample", :last_name => "Person #{i}", :user => user) }
+ Fabricator(:user_with_people, from: :user) do
+ people!(count: 3){|user, i| Fabricate(:person, first_name: "Sample", last_name: "Person #{i}", user: user) }
end
- Fabricator(:user_with_people_with_details, :from => :user) do
- people!(:count => 3){|user, i| Fabricate(:person_with_details, :first_name => "Sample", :last_name => "Person #{i}", :user => user) }
+ Fabricator(:user_with_people_with_details, from: :user) do
+ people!(count: 3){|user, i| Fabricate(:person_with_details, first_name: "Sample", last_name: "Person #{i}", user: user) }
end
</pre>
@@ -2266,7 +2264,7 @@ Now that we want to scope down to just people attached to the current user we'll
require 'spec_helper'
require 'capybara/rspec'
- describe "the views for people", :type => :request do
+ describe "the views for people", type: :request do
describe "when logged in as a user" do
before(:all) do
@user = Fabricate(:user_with_people_with_details)
View
72 source/projects/jsmerchant.textile
@@ -105,7 +105,7 @@ This method of modifying the database was one of the big new ideas in Rails. It
We need to add extra options to our @price@ column. Inside the @self.up@, modify the @price@ line so it looks like this:
<pre class="brush:ruby">
- t.decimal :price, :precision => 8, :scale => 2
+ t.decimal :price, precision: 8, scale: 2
</pre>
We want a column named @price@ with type @decimal@. We give it two additional options: the @precision@ controls how many digits the number can have in total. The @scale@ controls how many digits come after the decimal. So this column will have a maximum value of 999999.99, which would be some expensive groceries.
@@ -182,7 +182,7 @@ Let's take a peek at how this is all working. Browse your project files and look
<td><%= product.image_url %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
- <td><%= link_to 'Destroy', product, :confirm => 'Are you sure?', :method => :delete %></td>
+ <td><%= link_to 'Destroy', product, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
@@ -246,7 +246,7 @@ Let's open the @/app/views/products/index.html.erb@ view template so we can make
* The link at the bottom is currently "New product" -- let's change it to "Create a New Product" like this:
<pre class="brush:ruby">
- <p><%= link_to "Create a New Product", new_product_path, :id => "new_product" %></p>
+ <p><%= link_to "Create a New Product", new_product_path, id: "new_product" %></p>
</pre>
* Then let's restructure the table.<br/> See the line that says @<% for product in @products %>@? That means "for each of the things in the variable @@products@, take them one at a time, call them @product@, then do everything in between this line and the one that reads @<% end %>@"<br/>So for each @product@, the existing template creates one TD for the @title@, one for the @price@, one for the @description@ and so on. Let's simplify the products like this:
@@ -388,7 +388,7 @@ rails generate migration add_stock_to_products
After it generates, open the migration (look in @/db/migrate@) and in the @change@ add the line below.
<pre class="brush:ruby">
-add_column :products, :stock, :integer, :default => 0
+add_column :products, :stock, :integer, default: 0
</pre>
Run the migration with @rake db:migrate@ then the column exists in your database.
@@ -445,7 +445,7 @@ Your validation probably isn't working, right? Your form isn't changing the val
Take a look in the @Product@ model again. Unless you anticipated this problem and fixed it already, @stock@ will not be in your @attr_accessible@ list, and that would stop you from being able to include an adjustment to @stock@ in any mass assignment. Here's an example of what a mass assignment would look like in your application:
<pre class="brush:ruby">
- p = Product.new(:title => "Apples", :price => "0.49", :description => "They're apples.")
+ p = Product.new(title: "Apples", price: "0.49", description: "They're apples.")
</pre>
Typically applications use mass-assignment when processing form data in a @create@ or @update@ action. When you use @attr_accessible@, *only* the listed attributes can be set using this style. Our issue is that @stock@ isn't listed, so it's being ignored during the mass-assignment.
@@ -536,7 +536,7 @@ Let's open the @index@ view for our @products@ (@/app/views/products/index.html.
First we'll create the "Add to Cart" link. In the @<th>@ lines near the top of the index add @<th>Buy</th>@. Then in the TDs, underneath the stock line, let's add a new cell:
<pre class="brush:ruby">
-<td><%= link_to "Add to Cart", new_order_item_path(:product_id => product.id) %></td>
+<td><%= link_to "Add to Cart", new_order_item_path(product_id: product.id) %></td>
</pre>
This says "create a link with the text 'Add to Cart' which links to the new @order_item@ path and sends in a parameter named @product.id@ with the value of the ID for this @product@.
@@ -567,7 +567,7 @@ Open your @/app/controllers/products_controller.rb@ file. This controller is wha
begin
@order = Order.find(session[:order_id])
rescue ActiveRecord::RecordNotFound
- @order = Order.create(:status => "unsubmitted")
+ @order = Order.create(status: "unsubmitted")
session[:order_id] = @order.id
end
end
@@ -606,7 +606,7 @@ This object will not yet have been saved to the database. If we wanted to build
<pre class="brush:ruby">
def load_order
- @order = Order.find_or_initialize_by_id(session[:order_id], :status => "unsubmitted")
+ @order = Order.find_or_initialize_by_id(session[:order_id], status: "unsubmitted")
if @order.new_record?
@order.save!
session[:order_id] = @order.id
@@ -614,7 +614,7 @@ This object will not yet have been saved to the database. If we wanted to build
end
</pre>
-Note that the @:status => "unsubmitted"@ will only set the @status@ if it is initializing a new object, it will not change the value of records found in the database.
+Note that the @status: "unsubmitted"@ will only set the @status@ if it is initializing a new object, it will not change the value of records found in the database.
From there we look to see if it is a @new_record?@, which is true when the record has not yet been stored to the DB. If it is new, save it to the DB so it gets an ID, the store that ID into the user's @session@.
@@ -631,7 +631,7 @@ So let's get rid of the @new@ action from the controller. While we're cutting co
We need the products index to trigger the @create@ action. Look at the routes table (by running @rake routes@ from the terminal) and see that we need a @POST@ request to @order_items_path@. To generate a @POST@ we have to use a form, but our product listing uses links for the "Add to Cart". Open the index template and change the @link_to@ to a @button_to@ like this:
<pre class="brush:ruby">
- <td><%= button_to "Add to Cart", order_items_path(:product_id => product.id) %></td>
+ <td><%= button_to "Add to Cart", order_items_path(product_id: product.id) %></td>
</pre>
Refresh your browser, click an "Add to Cart" button, and you should see a page complaining about validation errors.
@@ -644,9 +644,9 @@ Look at the server log for the last request. You should see "Started POST" then
def create
@order_item = OrderItem.new(params[:order_item])
if @order_item.save
- redirect_to @order_item, :notice => "Successfully created order item."
+ redirect_to @order_item, notice: "Successfully created order item."
else
- render :action => 'new'
+ render action: 'new'
end
end
</pre>
@@ -667,11 +667,11 @@ Now that we have access to @@order@, we can build the @order_item@ through the r
<pre class="brush:ruby">
def create
- @order_item = @order.order_items.new(:quantity => 1, :product_id => params[:product_id])
+ @order_item = @order.order_items.new(quantity: 1, product_id: params[:product_id])
if @order_item.save
- redirect_to @order, :notice => "Successfully created order item."
+ redirect_to @order, notice: "Successfully created order item."
else
- render :action => 'new'
+ render action: 'new'
end
end
</pre>
@@ -807,7 +807,7 @@ I like easy, so let's pick #2!
On the @show@ view for your @Order@, add a link like this:
<pre class="brush:ruby">
- <%= link_to "Empty Cart", @order, :confirm => 'Are you sure?', :method => :delete %>
+ <%= link_to "Empty Cart", @order, confirm: 'Are you sure?', method: :delete %>
</pre>
Hop into the @destroy@ action of @OrdersController@ and change the redirect so it sends you back to @products_path@.
@@ -827,7 +827,7 @@ Refresh the @OrderItem@ listing and...they're all still there? If an @Order@ get
Go into @Order@ model. Change the @has_many :order_items@ line to this:
<pre class="brush:ruby">
- has_many :order_items, :dependent => :destroy
+ has_many :order_items, dependent: :destroy
</pre>
Now, when an @Order@ is destroyed all the associated order items will get destroyed too. This does *not* remove the @OrderItem@ objects that are already orphaned in the database. Kill those through the console:
@@ -874,7 +874,7 @@ We set the default value in the database, and to change the database we'll need
Then open that migration and in the @up@ method add this line:
<pre class="brush:ruby">
- change_column :order_items, :quantity, :integer, :default => 0
+ change_column :order_items, :quantity, :integer, default: 0
</pre>
No @down@ is necessary for this little tweak. Run the migration with @rake db:migrate@. If you'd like to see the results, create a new @OrderItem@ from your console and you'll see it starts with the quantity 0.
@@ -1052,7 +1052,7 @@ The way this authentication works is that your app redirects to the third party
Open @/app/config/routes.rb@ and add this line:
<pre class="brush:ruby">
- match '/auth/:provider/callback', :to => 'sessions#create'
+ match '/auth/:provider/callback', to: 'sessions#create'
</pre>
Re-visit @http://localhost:3000/auth/twitter@, it will process your already-existing Twitter login, then redirect back to your application and give you *Uninitialized Constant SessionsController*. Our router is attempting to call the @create@ action of the @SessionsController@, but that controller doesn't exist yet.
@@ -1070,7 +1070,7 @@ Then open up that controller and add code so it looks like this:
<pre class="brush:ruby">
class SessionsController < ApplicationController
def create
- render :text => request.env["omniauth.auth"]
+ render text: request.env["omniauth.auth"]
end
end
</pre>
@@ -1139,7 +1139,7 @@ Thankfully @find_or_create_by@ has a solution. We can add a hash of parameters t
<pre class="brush:ruby">
def self.find_or_create_by_auth(auth_data)
find_or_create_by_provider_and_uid(auth_data["provider"], auth_data["uid"],
- :name => auth_data["info"]["name"])
+ name: auth_data["info"]["name"])
end
</pre>
@@ -1153,7 +1153,7 @@ Now, back to @SessionsController@, let's add a redirect action to send them to t
def create
@user = User.find_or_create_by_auth(request.env["omniauth.auth"])
session[:user_id] = @user.id
- redirect_to products_path, :notice => "Logged in as #{@user.name}"
+ redirect_to products_path, notice: "Logged in as #{@user.name}"
end
</pre>
@@ -1169,9 +1169,9 @@ Open @/app/views/layouts/application.html.erb@ and you'll see the framing for al
<div id="account">
<% if current_user %>
<span>Welcome, <%= current_user.name %></span>
- <%= link_to "logout", logout_path, :id => "login" %>
+ <%= link_to "logout", logout_path, id: "login" %>
<% else %>
- <%= link_to "login", login_path, :id => "logout" %>
+ <%= link_to "login", login_path, id: "logout" %>
<% end %>
</div>
</pre>
@@ -1203,8 +1203,8 @@ Just because we're following the REST convention doesn't mean we can't also crea
Open @/config/routes.rb@ and add two custom routes:
<pre class="brush:ruby">
- match "/login" => redirect("/auth/twitter"), :as => :login
- match "/logout" => "sessions#destroy", :as => :logout
+ match "/login" => redirect("/auth/twitter"), as: :login
+ match "/logout" => "sessions#destroy", as: :logout
</pre>
The first line creates a path named @login@ which just redirects to the static address @/auth/twitter@ which will be intercepted by the OmniAuth middleware. The second line creates a @logout@ path which will call the destroy action of our @SessionsController@.
@@ -1219,7 +1219,7 @@ Our login works great, but we can't logout! When you click the logout link it's
* Add a @destroy@ method
* In the method, erase the session marker by setting @session[:user_id] = nil@
* Redirect them to the @root_path@ with the notice @"Goodbye!"@
-* Define a @root_path@ in your router like this: @root :to => "products#index"@
+* Define a @root_path@ in your router like this: @root to: "products#index"@
Now try logging out and you'll probably end up looking at the Rails "Welcome Aboard" page. Why isn't your @root_path@ taking affect?
@@ -1236,7 +1236,7 @@ h4. Connecting the Order to a User
Open the @Order@ model and add a new @belongs_to@ line:
<pre class="brush:ruby">
- belongs_to :user, :foreign_key => :customer_id
+ belongs_to :user, foreign_key: :customer_id
</pre>
Note the extra @foreign_key@ parameter. In the database that's the name of the column, though our associated model is named @User@. This extra piece of information tells Rails how to connect them. That means we also need to modify the @attr_accessible@ line like this:
@@ -1274,9 +1274,9 @@ Our orders are created in the @load_order@ method in @ApplicationController@. Le
@order = Order.find(session[:order_id])
rescue ActiveRecord::RecordNotFound
if current_user
- @order = current_user.orders.create(:status => "unsubmitted")
+ @order = current_user.orders.create(status: "unsubmitted")
else
- @order = Order.create(:status => "unsubmitted")
+ @order = Order.create(status: "unsubmitted")
end
session[:order_id] = @order.id
end
@@ -1292,8 +1292,8 @@ Open up the @SessionsController@. The @create@ action is what logs them in. Once
@user = User.find_or_create_by_auth(request.env["omniauth.auth"])
session[:user_id] = @user.id
load_order
- @order.update_attributes(:user => @user)
- redirect_to products_path, :notice => "Logged in as #{@user.name}"
+ @order.update_attributes(user: @user)
+ redirect_to products_path, notice: "Logged in as #{@user.name}"
end
</pre>
@@ -1404,9 +1404,9 @@ h4. Building Addresses in the Console
Let's create two sample addresses for your current user in the console. Here's how you might do that:
<pre class="brush:ruby">
- a = User.last.addresses.build(:line1 => "123 First Street", :line2 => "Suite B", :city => "Washington", :state => "DC", :zip => "20011")
+ a = User.last.addresses.build(line1: "123 First Street", line2: "Suite B", city: "Washington", state: "DC", zip: "20011")
a.save
- b = User.last.addresses.build(:line1 => "321 Second Street", :city => "Arlington", :state => "VA", :zip => "22182")
+ b = User.last.addresses.build(line1: "321 Second Street", city: "Arlington", state: "VA", zip: "22182")
b.save
</pre>
@@ -1496,7 +1496,7 @@ Open your @routes.rb@ file and change the @resources :orders@ to this:
That tells the router that orders will have a custom "member" action -- an action that happens to a single order. The action will use a PUT verb and the name "purchase." If you run @rake routes@ in your terminal, you'll see the new listing like this:
<pre class="brush:ruby">
- purchase_order PUT /orders/:id/purchase(.:format) {:action=>"purchase", :controller=>"orders"}
+ purchase_order PUT /orders/:id/purchase(.:format) {action:"purchase", controller:"orders"}
</pre>
We chose the PUT verb here because the operation we're performing is similar to an edit/update. Since @update@ uses PUT, our @purchase@ will too.
@@ -1506,7 +1506,7 @@ h4. Using the Route
In the order's @show.html.erb@ we need to modify the @form_for@ line. To control the submission address and verb, we add the @:url@ and @:method@ parameters like this:
<pre class="brush:ruby">
- <%= form_for @order, :url => purchase_order_path(@order), :method => :put do |f| %>
+ <%= form_for @order, url: purchase_order_path(@order), method: :put do |f| %>
</pre>
Now refresh your order in the browser and click the submit button.
View
12 source/projects/sales_engine.markdown
@@ -168,20 +168,20 @@ _NOTE_: All revenues should be reported as a `BigDecimal` object with two decima
Given a hash of inputs, you can create new invoices on the fly using this syntax:
```
-invoice = Invoice.create(:customer => customer, :merchant => merchant, :status => "shipped",
- :items => [item1, item2, item3])
+invoice = Invoice.create(customer: customer, merchant: merchant, status: "shipped",
+ items: [item1, item2, item3])
```
Assuming that `customer`, `merchant`, and `item1`/`item2`/`item3` are instances of their respective classes.
You should determine the quantity bought for each item by how many times the item is in the `:items` array.
-So, for `:items => [item1, item1, item2]`, the quantity bought will be 2 for `item1` and 1 for `item2`.
+So, for `items: [item1, item1, item2]`, the quantity bought will be 2 for `item1` and 1 for `item2`.
Then, on such an invoice you can call:
```ruby
-invoice.charge(:credit_card_number => "4444333322221111",
- :credit_card_expiration => "10/13", :result => "success")
+invoice.charge(credit_card_number: "4444333322221111",
+ credit_card_expiration: "10/13", result: "success")
```
The objects created through this process would then affect calculations, finds, etc.
@@ -258,4 +258,4 @@ We decided that the performance grading was not effective. Instead, we're going
Find the data files at https://github.com/JumpstartLab/sales_engine
-Measure your final product using the test harness at https://github.com/JumpstartLab/sales_engine_spec_harness
+Measure your final product using the test harness at https://github.com/JumpstartLab/sales_engine_spec_harness
View
4 source/projects/store_engine.markdown
@@ -282,8 +282,8 @@ This is all tested in Ruby 1.9.3 which is the expected platform for your project
In your project's Gemfile, you must add these two dependencies:
```
- gem 'reek', :git => "git://github.com/mvz/reek.git", :branch => "ripper_ruby_parser-2"
- gem 'cane', :git => "git://github.com/square/cane.git"
+ gem 'reek', git: "git://github.com/mvz/reek.git", branch: "ripper_ruby_parser-2"
+ gem 'cane', git: "git://github.com/square/cane.git"
```
#### Running Reek
Something went wrong with that request. Please try again.