I got a sample how you could test some controllers..
In my setup I use; factorygirl and RSpec.
Ruby
require 'spec_helper'moduleApimoduleV1
describe UserSessionsControllerdo
render_views
describe "authenticate"do
it "authenticates correctly"do
user = FactoryGirl.create(:user)
post :create, :email => user.email, :password => user.password, :format => "json"
user.reload
response.cookies['user_token'].should eq(user.user_token)
response.should be_success
body = JSON.parse(response.body)
body['id'].should eq(user.id)
body['email'].should eq(user.email)
body['user_token'].should eq(user.user_token)
body['password'].should equal nil
body['profile'].should_not be nilend
it "should return a json user"
user = FactoryGirl.create(:user) #this user@request.cookies['user_token'] = user.user_token # if you need an auth cookie..
get :show, :id => user.id, :format => "json"
response.should be_success
body = JSON.parse(response.body)
body.should have(1).user #test if only one root object is returned (sometimes you dont want to have a json root..)
body[0].should have_key("user") #test root key...
body[0]['user'].should have_key("id")
body[0]['user'].should have_key("email")
body[0]['user'].should have_key("friends")
body[0]['user'].should have_key("profile") #test if the user has an associated profile
body[0]['user'].should have_key("updated_at")
body[0]['user']['profile'].should have(1).profile # test that the user returns only 1 profile.
body[0]['user']['friends'].should have(3).friends #test that the user has 3 friendsendendendendend
Hey Zolzaya,
I did some research myself. I think i will try to split my controller and response tests with Capibara gem. What I test in my controllers are the controller logic. I still need to get started with testing on my json responses. Ill give you a update...
Ruby
require 'spec_helper'moduleApimoduleV1
describe UserSessionsControllerdo
describe "authenticate"do
it "authenticates correctly"do
user = FactoryGirl.create(:user)
post :create, :login => user.email, :password => user.password, :format => "json"
response.should be_success
end
describe "fail authentication"doend
describe "logout"doendendendend
One thing i have to use :format => "json" to get json responses, it would be great if it went automatically.
One more thing check RABL git how to test your RABL responses.
I dont know how about you guys but i cant seem to get my tests to work.
How do you guys write these tests if your controller is nested inside the modules?
ruby
require 'spec_helper'
namespace :apido
namespace :v1do
describe ProductsControllerdo
describe "GET 'index'"do
it "returns http success"do
get 'index'
response.should be_success
endendendendend
console
Failures:
1) ProductsControllerGET'index' returns http success
Failure/Error: get 'index'ActionController::RoutingError:
No route matches {:controller=>"products"}
# ./spec/controllers/api/v1/products_controller_spec.rb:10:in `block (5 levels) in <top (required)>'
Obviously because the correct route should be: {:action=>"index", :controller=>"api/v1/products"}
Hi Ryan, lately I've seen a lots of development railscasts for rails API's. What are the best practices to test API's and versions? Because you don't want to break anything down if you implement new features, change the json format later on. What i would like to know is how you guys test your json api's input and output and even with versioning. Maybe this would be a good idea for a railscast.
Nice advice to put it in a initializer.
I also came across this solution a time ago. This works for some cases.
When you have a large website 10 or more locales its not handy to define a fallback for each locale. The point is you have to define the fallbacks static.
I am using an Article to explain my problem but a more suitable case is when you have an Festival. An Festival is held in a Country and has a language that is the base language for the Festival. The Festival is held in England so the organisation enters the data in the English language. The organisation decides also to translate the translate the website in the WK language. Now a German guys enters the website, what i dont want is that the website shows the Festival in the next best fallback language but the language its originally created with. Because a Festival can also be entered in the WK language(original) and English language (translation) then a German user needs to see the Festival information in WK.
I was having a great challenge with Globalize3 regarding translating models on a website. Globalize3 relies on models created by a base locale set by I18n.locale or config.i18n.default_locale. Now lets have this situation when video above has three locales, WK, DE and EN (EN set as default). I have my fallback set to the en locale.
When I enter articles in english all goes fine, all the entries are now English for all locales. But for example when i try to make an article in WK language only, Globalize wont fall back to that language when the user browses the English or German language. For example when I view the page in German it still falls back to the English locale which is not set. Any suggestions how to fall back to the locale in which the Model is originally created when other locales are not set?
So my goal was; when a Article is created in a locale (WK) other then the default_locale (EN), the application needs to show that locale (WK) in the article as fallback locale. Even when i enter a translation for the default locale (EN) and the user requests the page in German (DE) the article is shown in the (WK) locale.
What i did is create an base_locale attribute to the Article model and tried overriding the read_attributes globalize uses. Here is some code
ruby
classLanguage < ActiveRecord::Base
attr_accessible :locale, :nameendclassArticle < ActiveRecord::Base
translates :title, :description, :fallbacks_for_empty_translations => true
attr_accessible :title, :description:base_locale_sym
belongs_to :base_locale, :class_name => "Language", :foreign_key => "base_locale_id"
before_save :set_base_locale_cachedefset_base_locale_cacheifself.base_locale_id_changed?
unlessself.base_locale.blank?
#sets the base locale cache for the created Article#i dont want to query Article.base_locale each time...self.base_locale_sym = Language.find(self.base_locale_id).locale
elseself.base_locale_sym = ""endendenddefread_attribute(name, options = {})
#when the translated_locales does not include the i18n.locale try to show the model in the locale in which the Article was first created.unlessself.translated_locales.include? I18n.locale.to_sym
#merge the options hash
options.merge(:locale => self.base_locale_sym)
endsuper(name,options)
endend
This idea worked quite fine, but i had really issues with updating and generating models. Maybe someone got a better idea?
I couldn't figure out this puzzle so i stopped it 3 months ago. Since this railscast is about globalize, I thought maybe we can solve it..
Anyone experienced an issue when running rvmsudo, that the script hangs at a password prompt that can not be entered?
ruby
Lets say this task:
task :export, :roles => :appdo
run "cd #{release_path} && rvmsudo bundle exec foreman export upstart"end
Then rvmsudo will hang at [sudo] password for, you wont be able to enter a password.
I solved this issue by executing a random sudo command in front of the rvmsudo command.. For example sudo "whoami". But i wonder if there is a clean solution.
Also anyone experienced an issue that they can not restart their services trough rvmsudo? For example rvmsudo restart #{application}" throws /usr/bin/env: restart: No such file or directory
I'm wondering, what would be a good meganism to ensure the user received the message? Im sure in some cases its important that the application is aware that the user received the message.
Ryan what is the advantage of Private_pub compared to adding a key/ pass combination to model channels like this?
( And you have to listen to a channel like "/chatroom/new/room_key/room_pass/" )
How would you add search for category name with a text_field instead of id ?
products = Product.include(:category).order......
products = products.where("categories.name like ?", "%bla bla bla%")
Something like this? I know i can make category name an auto complete text search Railscasts #102 Auto-Complete Association (revised) like and just pass the category id.. Just looking for alternative ways..
I prefere Earle Clubbs method. Besides turn off cache classes when you are using spork with guard.
http://www.avenue80.com/tiny-tip-spork-not-reloading-classes/
pengpenglin's method didnt work quite well with model validations and cache counters.
In my previous post, forget about Capibara.
I got a sample how you could test some controllers..
In my setup I use; factorygirl and RSpec.
I hope this helps you..
Hey Zolzaya,
I did some research myself. I think i will try to split my controller and response tests with Capibara gem. What I test in my controllers are the controller logic. I still need to get started with testing on my json responses. Ill give you a update...
One thing i have to use :format => "json" to get json responses, it would be great if it went automatically.
One more thing check RABL git how to test your RABL responses.
https://github.com/nesquena/rabl/wiki/Testing-with-rspec
Here you go mate ;)
Ok I figured it out after a weekend relaxing :p
You can put in your rspec:
This will perfectly work. In my other attempts before the weekend i placed
do
behind V1 and Api, that will just not work. :)By the way API::V1::ProductsController will not just work.
I dont know how about you guys but i cant seem to get my tests to work.
How do you guys write these tests if your controller is nested inside the modules?
Obviously because the correct route should be:
{:action=>"index", :controller=>"api/v1/products"}
Hi Ryan, lately I've seen a lots of development railscasts for rails API's. What are the best practices to test API's and versions? Because you don't want to break anything down if you implement new features, change the json format later on. What i would like to know is how you guys test your json api's input and output and even with versioning. Maybe this would be a good idea for a railscast.
Thanks
Nice advice to put it in a initializer.
I also came across this solution a time ago. This works for some cases.
When you have a large website 10 or more locales its not handy to define a fallback for each locale. The point is you have to define the fallbacks static.
I am using an Article to explain my problem but a more suitable case is when you have an Festival. An Festival is held in a Country and has a language that is the base language for the Festival. The Festival is held in England so the organisation enters the data in the English language. The organisation decides also to translate the translate the website in the WK language. Now a German guys enters the website, what i dont want is that the website shows the Festival in the next best fallback language but the language its originally created with. Because a Festival can also be entered in the WK language(original) and English language (translation) then a German user needs to see the Festival information in WK.
Then static fallbacks wont help me..
Hello guys and Ryan,
I was having a great challenge with Globalize3 regarding translating models on a website. Globalize3 relies on models created by a base locale set by I18n.locale or config.i18n.default_locale. Now lets have this situation when video above has three locales, WK, DE and EN (EN set as default). I have my fallback set to the en locale.
When I enter articles in english all goes fine, all the entries are now English for all locales. But for example when i try to make an article in WK language only, Globalize wont fall back to that language when the user browses the English or German language. For example when I view the page in German it still falls back to the English locale which is not set. Any suggestions how to fall back to the locale in which the Model is originally created when other locales are not set?
So my goal was; when a Article is created in a locale (WK) other then the default_locale (EN), the application needs to show that locale (WK) in the article as fallback locale. Even when i enter a translation for the default locale (EN) and the user requests the page in German (DE) the article is shown in the (WK) locale.
What i did is create an base_locale attribute to the Article model and tried overriding the read_attributes globalize uses. Here is some code
This idea worked quite fine, but i had really issues with updating and generating models. Maybe someone got a better idea?
I couldn't figure out this puzzle so i stopped it 3 months ago. Since this railscast is about globalize, I thought maybe we can solve it..
Anyone experienced an issue when running rvmsudo, that the script hangs at a password prompt that can not be entered?
Then rvmsudo will hang at
[sudo] password for
, you wont be able to enter a password.I solved this issue by executing a random sudo command in front of the rvmsudo command.. For example
sudo "whoami"
. But i wonder if there is a clean solution.Also anyone experienced an issue that they can not restart their services trough rvmsudo? For example
rvmsudo restart #{application}"
throws /usr/bin/env: restart: No such file or directoryI'm wondering, what would be a good meganism to ensure the user received the message? Im sure in some cases its important that the application is aware that the user received the message.
Probably not with a hidden form or something.
Ryan what is the advantage of Private_pub compared to adding a key/ pass combination to model channels like this?
( And you have to listen to a channel like "/chatroom/new/room_key/room_pass/" )
I figured it out... I believe this is more of a hack but it could be usefull for others.
You can't render two views. So what i did was....
Now both the javascript will get rendered (empty string) and json will be rendered properly..
Is there a more elegant solution?
How would you force the rendering of the create.js file as well on receiving a JSON message ( Among a JSON messge)?
How would you add search for category name with a text_field instead of id ?
products = Product.include(:category).order......
products = products.where("categories.name like ?", "%bla bla bla%")
Something like this? I know i can make category name an auto complete text search Railscasts #102 Auto-Complete Association (revised) like and just pass the category id.. Just looking for alternative ways..
Oops i ment target.class.name
You can also use this following line to make the error messages more personal..
And if you are unhappy with your model name you can always add an i18n translation to the model name!