You can get mongomapper, will paginate and draper to work together like the demos on (https://github.com/mislav/will_paginate) if you access the models in the controller like below
@models = ModelDecorator.
decorate(Model.paginate(:page => params[:page]))
An insight into the mind of tekkies: techie, techy [ˈtɛkɪ] Informal n pl techies a person(s) who is skilled in the use of technological devices, such as computers adj of, relating to, or skilled in the use of technological devices, such as computers
Showing posts with label Rails. Show all posts
Showing posts with label Rails. Show all posts
Tuesday, 15 November 2011
Friday, 14 October 2011
Continuous Integration - Headless JS on CentOS
This was a bit of a pain to get working so I thought I would layout the steps to get Continuous Integration (CI) working on CentOS 5.5 with cruise control, rspec and cucumber when you have javascript scenarios you want to run without a real browser.
Before Cruise Control is set up:
1) Clone the latest version of CC from: http://cruisecontrolrb.thoughtworks.com/documentation to your server. (read the guide, update your database.yml etc...)
2) CC can run standalone so start the server. and add your project(s)
3) If you have apache running you will have to set up a virtual host and set it to run as a proxy to the CI e.g. my configuration is:
ServerAdmin EMAIL_ADDRESS
ServerName DOMAIN_NAME
ErrorLog PATH_TO_ERROR_LOG
CustomLog PATH_TO_CUSTOM_LOG
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
Thanks TomJ.
4) vim lib/tasks/custom_cc.rake
desc 'Custom curise task for RSpec'
task :cruise do
ENV['RAILS_ENV'] = 'test'
if File.exists?(Dir.pwd + "/config/database.yml")
if Dir[Dir.pwd + "/db/migrate/*.rb"].empty?
raise "No migration scripts found in db/migrate/ but database.yml exists, " +
"CruiseControl won't be able to build the latest test database. Build aborted."
end
# perform standard Rails database cleanup/preparation tasks if they are defined in project
# this is necessary because there is no up-to-date development database on a continuous integration box
if Rake.application.lookup('db:test:purge')
CruiseControl::invoke_rake_task 'db:test:purge'
end
if Rake.application.lookup('db:migrate')
CruiseControl::reconnect
CruiseControl::invoke_rake_task 'db:migrate'
end
end
CruiseControl::invoke_rake_task 'spec'
CruiseControl::invoke_rake_task 'cucumber:ok'
end
After Cruise Control is set up
If all is going well then you should be able to start the builder for that project and it should be running the rspec and cucumber tests suite. Now you hit the requirement of writing the scenarios that require javascript and these are currently failing (not unexpected since we don't have a X11 system or browser installed). There are a couple of ways to get these tests running the method I chose was:
1. Add capybara-webkit and headless to the Gemfile:
group :test, :cucumber do
....
gem 'headless'
gem 'capybara-webkit'
....
end
2. Update the features/support/env.rb. Require headless and start it. Also set the capybara js driver to webkit.
require 'cucumber/rails'
require 'headless'
headless = Headless.new
headless.start
Capybara.javascript_driver = :webkit
Capybara.default_selector = :css
Capybara.server_boot_timeout = 50
ActionController::Base.allow_rescue = false
begin
DatabaseCleaner.strategy = :transaction
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end
3. Now on the CI server we need to install some packages for the capybara-webkit gem (I hope you have permission)
sudo yum install -y Xvfb
sudo yum install -y qt4 qt4-devel
4. Almost there. Start the screen or capybara will give you an error like "webkit_server: cannot connect to X server"
Xvfb :1 -screen 0 1024x768x16 -nolisten inet6 &
It should now be running in the background, you can check ps or jobs
5. Kill the builder and reboot the CI app and then push the earlier changes. When you start the builder again all the tests should now run and if you're lucky they may even pass.
Before Cruise Control is set up:
1) Clone the latest version of CC from: http://cruisecontrolrb.thoughtworks.com/documentation to your server. (read the guide, update your database.yml etc...)
2) CC can run standalone so start the server. and add your project(s)
3) If you have apache running you will have to set up a virtual host and set it to run as a proxy to the CI e.g. my configuration is:
ServerAdmin EMAIL_ADDRESS
ServerName DOMAIN_NAME
ErrorLog PATH_TO_ERROR_LOG
CustomLog PATH_TO_CUSTOM_LOG
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
Thanks TomJ.
4) vim lib/tasks/custom_cc.rake
desc 'Custom curise task for RSpec'
task :cruise do
ENV['RAILS_ENV'] = 'test'
if File.exists?(Dir.pwd + "/config/database.yml")
if Dir[Dir.pwd + "/db/migrate/*.rb"].empty?
raise "No migration scripts found in db/migrate/ but database.yml exists, " +
"CruiseControl won't be able to build the latest test database. Build aborted."
end
# perform standard Rails database cleanup/preparation tasks if they are defined in project
# this is necessary because there is no up-to-date development database on a continuous integration box
if Rake.application.lookup('db:test:purge')
CruiseControl::invoke_rake_task 'db:test:purge'
end
if Rake.application.lookup('db:migrate')
CruiseControl::reconnect
CruiseControl::invoke_rake_task 'db:migrate'
end
end
CruiseControl::invoke_rake_task 'spec'
CruiseControl::invoke_rake_task 'cucumber:ok'
end
After Cruise Control is set up
If all is going well then you should be able to start the builder for that project and it should be running the rspec and cucumber tests suite. Now you hit the requirement of writing the scenarios that require javascript and these are currently failing (not unexpected since we don't have a X11 system or browser installed). There are a couple of ways to get these tests running the method I chose was:
1. Add capybara-webkit and headless to the Gemfile:
group :test, :cucumber do
....
gem 'headless'
gem 'capybara-webkit'
....
end
2. Update the features/support/env.rb. Require headless and start it. Also set the capybara js driver to webkit.
require 'cucumber/rails'
require 'headless'
headless = Headless.new
headless.start
Capybara.javascript_driver = :webkit
Capybara.default_selector = :css
Capybara.server_boot_timeout = 50
ActionController::Base.allow_rescue = false
begin
DatabaseCleaner.strategy = :transaction
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end
3. Now on the CI server we need to install some packages for the capybara-webkit gem (I hope you have permission)
sudo yum install -y Xvfb
sudo yum install -y qt4 qt4-devel
4. Almost there. Start the screen or capybara will give you an error like "webkit_server: cannot connect to X server"
Xvfb :1 -screen 0 1024x768x16 -nolisten inet6 &
It should now be running in the background, you can check ps or jobs
5. Kill the builder and reboot the CI app and then push the earlier changes. When you start the builder again all the tests should now run and if you're lucky they may even pass.
Thursday, 19 May 2011
Using virtual attributes in ruby model.to_xml
If you have virtual attributes that you want to include in your to_xml call then you can override the to_xml on the model and pass the virtual attributes as methods. For example
115true
115trueAn Example from another model
class ModelName < ActiveRecord::Base
has_one :model_name_2
# real attributes a, b
attr_accessor :c, :d
delegate e, :to => :model_name_2
end
Now an instance (mn) of type ModelName calling to_xml will output
mn.to_xml
Now to override the to_xml to include attributes c, d and e.
class ModelName < ActiveRecord::Base
has_one :model_name_2
class ModelName < ActiveRecord::Base
has_one :model_name_2
# real attributes a, b
attr_accessor :c, :d
delegate e, :to => :model_name_2
def to_xml
super(:methods => [:c, :d, e])
end
end
Now when to_xml is called on the model c, d and e will also be included.
mn.to_xml
more to_xml goodness at http://apidock.com/rails/ActiveRecord/Serialization/to_xml
Wednesday, 18 May 2011
5 useful Rails Migrations commands
So we all know Rails migrations are extremely powerful, they allow you to write exactly how you want to structure your data, without getting down to the SQL. It's also really convenient to have a database schema checked into your revision control. It's ridiculously straight forward.. until you start moving data around your database (assuming your not some kind of terminator sent from the future with enough hindsight to never need to refactor your database).
As a general rule of thumb, we should not be moving data around in the migration structure. Here's why:
- Its hard to write migrations and remember the order that you removed tables
- Its really hard to read
- If a migration breaks half way because of the data then we have run half a migration and it fails when we try it again.
- If we have models we need to keep them and mark them deprecated until the data can be moved, we may remove a model and break our migrations
Therefore its essential to take a database dump of your data. With large data sets this does not seem practical to move around which is why we need to write and up and down data migration scripts. These can easily be placed in rake tasks.
Anyway here are 5 useful commands to get you out of trouble if your migrations go wrong:
rake db:migrate VERSION=20080901210000
rake db:rollback
rake db:rollback STEP=3
rake db:migrate:redo STEP=3
rake db:migrate:down VERSION=20080906120000
Sinatra/ActiveRecord Delegate Method Missing Error
I was doing delegation through multiple models earlier
class Model1 < ActiveRecord::Base
#model relationships
delegate :name, :to => :model2, :prefix => true
end
class Model2 < ActiveRecord::Base
#model relationships
delegate :name, :to => :model3, :prefix => false
end
class Model3 < ActiveRecord::Base
#model relationships
#where we want to access the attribute
end
Sinatra was throwing an error unknown method 'name' for Model2. This is strange since I had already told it to delegate this method to Model3. The problem was that even setting the :prefix to false in Model2 was causing method missing to be thrown. To fix all that was required was to remove the middle prefix making Model2
class Model2 < ActiveRecord::Base
#model relationships
delegate :name, :to => :model3
end
This then fixed the problem. When :prefix is assigned true it will prepend the model name to the accessor, you can specify a different prefix though using a different symbol.
class Model1 < ActiveRecord::Base
#model relationships
delegate :name, :to => :model2, :prefix => :user
end
This will allow you to access the name attribute of Model3 through model1.user_name
Subscribe to:
Posts (Atom)