I am following Michael Hartl's tutorial, and trying to implement the reply twitter-like functionality, ie. "@122-john-smith: hello there" should be a reply to user 122.
I first tried filtering the "@XXX-AAA-AAA" part using a before_filter, but I decided to try it first in the very same Micropost#create action. So far I've got this MicropostController:
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: [:destroy]
#before_filter :reply_to_user, only: [:create]
def index
end
def create
@micropost=current_user.microposts.build(params[:micropost])
#Rails.logger.info "hoooola"
regex=/\A@(\d)+(\w|\-|\.)+/i
[email protected]
isResponse=message.match(regex)[0].match(/\d+/)[0]
@micropost.response=isResponse
if @micropost.save
flash[:success]="Micropost created!"
redirect_to root_path
else
@feed_items=[]
render 'static_pages/home'
end
end
def destroy
@micropost.destroy
redirect_to root_path
end
private
def correct_user
@micropost = current_user.microposts.find_by_id(params[:id])
redirect_to root_path if @micropost.nil?
end
def reply_to_user
regex=/\A@(\d)+(\w|\-|\.)+/i
#I use [0] cause the output of match is a MatchData class with lots of bs
mtch=params[:micropost][:content].match(regex)[0]
#puts mtch
#@micropost=current_user.microposts.build(params[:micropost])
if mtch != nil
user_id=mtch.match(/\d+/)[0]
@replied_user=User.find(user_id)
@micropost.response=user_id unless @replied_user.nil?
end
end
end
And this is the snippet test I'm trying to pass:
require 'spec_helper'
describe "MicropostPages" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
before { valid_signin user }
describe "micropost creation" do
before { visit root_path }
describe "with invalid information" do
it "should not create a micropost" do
expect { click_button "Post" }.should_not change(Micropost,
:count)
end
describe "error messages" do
before { click_button "Post" }
it { should have_content('error') }
end
end
describe "with valid information" do
before { fill_in 'micropost_content', with: "Lorem ipsum" }
it "should create a micropost" do
expect { click_button "Post" }.should change(Micropost,
:count).by(1)
end
end
end
...
end
If I run these tests I get the follwing error:
Failures:
1) MicropostPages micropost creation with invalid information should not create a micropost
Failure/Error: expect { click_button "Post" }.should_not change(Micropost, :count)
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/microposts_controller.rb:14:in `create'
# (eval):2:in `click_button'
# ./spec/requests/micropost_pages_spec.rb:11:in `block (5 levels) in <top (required)>'
# ./spec/requests/micropost_pages_spec.rb:11:in `block (4 levels) in <top (required)>'
2) MicropostPages micropost creation with invalid information error messages
Failure/Error: before { click_button "Post" }
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/microposts_controller.rb:14:in `create'
# (eval):2:in `click_button'
# ./spec/requests/micropost_pages_spec.rb:14:in `block (5 levels) in <top (required)>'
However if I modify the tests and comment out all the @XXX filtering in the Micropost#create action:
def create
@micropost=current_user.microposts.build(params[:micropost])
#Rails.logger.info "hoooola"
#regex=/\A@(\d)+(\w|\-|\.)+/i
#[email protected]
#isResponse=message.match(regex)[0].match(/\d+/)[0]
#@micropost.response=isResponse
if @micropost.save
flash[:success]="Micropost created!"
redirect_to root_path
else
@feed_items=[]
render 'static_pages/home'
end
end
The tests pass just fine and the new Micropost is not a Nil object.
It can't seem to find an explanation here.
match(regex)[0].match(/\d+/)[0]that causes the issue...irband It returned the desired ID. Besides, shouldn't it in the worst case just writeNilin the@micropost.responsefield?[0]this will throw the exact same error if the regex doesn't match.