March 21, 2011
Posted by roadburn
Debugging script/runner
If you need to debug script/runner
1 2 | $ sudo gem install ruby-debug $ rdebug script/runner script.rb |
References
http://cheat.errtheblog.com/s/rdebug/
March 21, 2011
Posted by roadburn
If you need to debug script/runner
1 2 | $ sudo gem install ruby-debug $ rdebug script/runner script.rb |
References
http://cheat.errtheblog.com/s/rdebug/
Posted Under Rails
September 4, 2010
Posted by roadburn
Copy this from the spree root folder into your app
1 2 3 | spree-0.11.0/features to yourapp/features |
Edit features/support/env.rb
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | ENV["RAILS_ENV"] ||= "cucumber" require 'rubygems' require 'spork' Spork.prefork do require File.expand_path(File.dirname(__FILE__) + '/../../config/environment') require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support require 'cucumber/rails/world' require 'cucumber/rails/active_record' require 'cucumber/web/tableish' require 'capybara/rails' require 'capybara/cucumber' require 'capybara/session' require 'cucumber/rails/capybara_javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In # order to ease the transition to Capybara we set the default here. If you'd # prefer to use XPath just remove this line and adjust any selectors in your # steps to use the XPath syntax. Capybara.default_selector = :css Dir.glob(SPREE_ROOT + '/db/default/*.{yml,csv,rb}').each do |file| Fixtures.create_fixtures(SPREE_ROOT + '/db/default', File.basename(file, '.*')) end Dir.glob(SPREE_ROOT + '/test/fixtures/*.{yml,csv,rb}').each do |file| Fixtures.create_fixtures(SPREE_ROOT + '/test/fixtures', File.basename(file, '.*')) end require 'faker' require 'factory_girl' [ File.join(SPREE_ROOT, 'test', 'factories', '*.rb'), File.join(RAILS_ROOT, 'vendor', 'extensions', '*', '{test,spec}', 'factories', '*.rb') ].each do |path| Dir.glob(path).each { |factory| require factory } end require 'factory_girl/step_definitions' Zone.class_eval do def self.global find_by_name("GlobalZone") || Factory(:global_zone) end end Product.class_eval do def taxon=(taxon_name) taxonomy = Taxonomy.find_or_create_by_name("Category") taxon = Taxon.find_or_create_by_name_and_taxonomy_id(taxon_name, taxonomy) self.taxons << taxon end end ShippingMethod.create(:name => "UPS Ground", :zone => Zone.global, :calculator => Calculator::FlatRate.new) coupon = Coupon.create(:code => "SPREE", :description => "$5 off any order", :combine => false, :calculator => Calculator::FlatRate.new) coupon.calculator.update_attribute(:preferred_amount, 5) end Spork.each_run do # If you set this to false, any error raised from within your app will bubble # up to your step definition and out to cucumber unless you catch it somewhere # on the way. You can make Rails rescue errors and render error pages on a # per-scenario basis by tagging a scenario or feature with the @allow-rescue tag. # # If you set this to true, Rails will rescue all errors and render error # pages, more or less in the same way your application would behave in the # default production environment. It's not recommended to do this for all # of your scenarios, as this makes it hard to discover errors in your application. ActionController::Base.allow_rescue = false # If you set this to true, each scenario will run in a database transaction. # You can still turn off transactions on a per-scenario basis, simply tagging # a feature or scenario with the @no-txn tag. If you are using Capybara, # tagging with @culerity or @javascript will also turn transactions off. # # If you set this to false, transactions will be off for all scenarios, # regardless of whether you use @no-txn or not. # # Beware that turning transactions off will leave data in your database # after each scenario, which can lead to hard-to-debug failures in # subsequent scenarios. If you do this, we recommend you create a Before # block that will explicitly put your database in a known state. Cucumber::Rails::World.use_transactional_fixtures = true # How to clean your database when transactions are turned off. See # http://github.com/bmabey/database_cleaner for more info. require 'database_cleaner' DatabaseCleaner.strategy = :truncation end |
config/cucumber.yml
1 2 3 4 5 6 7 8 9 | <% rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" rerun_opts = rerun.to_s.strip.empty? ? "--format progress features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" std_opts = "#{rerun_opts} --format rerun --out rerun.txt --strict --tags ~@wip" %> default: --drb <%= std_opts %> wip: --drb --tags @wip:3 --wip features autotest: --drb features --guess --format 'pretty' --color autotest-all: --drb features --guess --format 'progress' --color |
config/environments/cucumber.rb
1 2 | ENV['AUTOFEATURE'] = "true" ENV['RSPEC'] = "true" |
config/database.yml
1 2 | cucumber: <<: *test |
Run your tests!
1 2 | $ spork cuc $ autotest |
http://groups.google.com/group/spree-user/browse_thread/thread/81b006af48d3166d
Posted Under Coding Tips Rails
August 31, 2010
Posted by roadburn
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 | Setup rails app with mysql $ rails appname -d mysql Start server with debugging enabled $ script/server --debugger Start server with debugging enabled - specify environment $ script/server --debugger RAILS_ENV=production Install required gems $ sudo rake gems:install Run gem server for rdocs $ gem server View routes $ rake routes Update Rails $ rake rails:update Enter the console with specified environment $ script/console $ script/console development $ script/console test $ script/console production Clear logfiles $ rake log:clear |
1 2 3 4 5 6 7 8 9 10 11 | Create database $ rake db:create Run database migrations $ rake db:migrate Drop database $ rake db:drop Rollback database migration $ rake db:rollback |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Clone database for testing $ rake db:test:clone Bootstrap Rspec $ script/generate rspec Bootstrap Cucumber $ script/generate cucumber --rspec --capybara --spork Bootstrap Pickle $ script/generate pickle Generate Rspec model $ script/generate rspec_model singularmodelname Generate Rspec controller $ script/generate rspec_controller pluralmodelname Start spork for cucumber $ spork cuc Run autotest $ autotest |
1 2 3 4 5 6 7 8 9 10 11 | Install gems $ sudo gem install gemname Uninstall gems $ sudo gem uninstall gemname Reinstall gems $ sudo gem pristine --all Remove old gems $ sudo gem clean |
1 2 | Generate migration
$ script/generate migration the_migration_name |
1 2 | Push to Git $ git push heroku |
Posted Under Coding Tips Rails
Download Uploadify from
http://www.uploadify.com/
copy the uploadify files into the following directories
1 2 3 4 5 6 7 | public/javascripts/uploadify/jquery.uploadify-2.1.0.min.js public/javascripts/uploadify/uploadify.swf public/javascripts/uploadify/swfobject.js public/images/cancel.png public/stylesheets/uploadify.css |
Create this file
app/middleware/flash_session_cookie_middleware.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | require 'rack/utils' class FlashSessionCookieMiddleware def initialize(app, session_key = '_session_id') @app = app @session_key = session_key end def call(env) if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/ req = Rack::Request.new(env) env['HTTP_COOKIE'] = "#{@session_key}=#{req.params[@session_key]}".freeze unless req.params[@session_key].nil? end @app.call(env) end end |
Add this line to
config/initializers/session_store.rb
1 | ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key]) |
Make sure your environment.rb file has this
config/environment.rb
1 2 3 4 5 6 7 8 9 | Rails::Initializer.run do |config| config.gem 'mime-types', :lib => 'mime/types' config.gem 'paperclip' %w(middleware).each do |dir| config.load_paths << "#{RAILS_ROOT}/app/#{dir}" end end |
Let’s assume you want to create a photo album with many photos.
Create your photo model with the following:
db/migrate/create_photos.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class CreatePhotos < ActiveRecord::Migration def self.up create_table :photos do |t| t.integer :attachable_id t.string :description t.string :data_file_name t.string :data_content_type t.integer :data_file_size t.datetime :data_updated_at t.string :parent end end def self.down drop_table :images end end |
In your album model:
app/model/album.rb
1 | has_many :photos, :dependent => :destroy, :foreign_key => :attachable_id |
In your photo model:
app/model/photo.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 | belongs_to :album, :foreign_key => :attachable_id has_attached_file :data, :url => "/assets/images/:id/:style/:basename.:extension", :path => ":rails_root/public/assets/images/:id/:style/:basename.:extension", :styles => { :large => "800x800>", :medium => "300x300>", :thumb => "100x100#"} validates_attachment_presence :data validates_attachment_size :data, :less_than => 2.megabytes validates_attachment_content_type :data, :content_type => ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'] |
app/controllers/photos_controller.rb
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 | class PhotosController < ApplicationController def create newparams = coerce(params) @photo = Photo.new(newparams[:upload]) // so this photo can belong to other models other than album @parent = @photo.parent.constantize.find(@photo.attachable_id) if @photo.save flash[:notice] = "Successfully uploaded photo." respond_to do |format| format.html {redirect_to @parent} format.json { render :json => { :result => 'success', :upload => photo_path(@photo) } } end else flash[:notice] = "Only gif, jpg or png files allowed" respond_to do |format| format.html {redirect_to @parent} format.json { render :json => { :result => 'failed'} } end end end def show @photo = Photo.find(params[:id]) end def coerce(params) if params[:upload].nil? h = Hash.new h[:upload] = Hash.new h[:upload][:attachable_id] = params[:attachable_id] h[:upload][:parent] = params[:parent] h[:upload][:data] = params[:Filedata] h[:upload][:data].content_type = MIME::Types.type_for(h[:upload][:data].original_filename).to_s h else params end end end |
app/views/albums/show.html.erb
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 48 | <%= stylesheet_link_tag "uploadify" %> <%= javascript_include_tag "uploadify/swfobject", "uploadify/jquery.uploadify.v2.1.0.min.js" %> <%- session_key_name = ActionController::Base.session_options[:key] -%> <script type="text/javascript" charset="utf-8"> jQuery.noConflict(); jQuery().ready(function() { jQuery('#photo_upload').click(function(event){ event.preventDefault(); }); jQuery('#photo_upload').uploadify({ 'uploader' : '/javascripts/uploadify/uploadify.swf', 'script' : '/cms/photos', 'multi' : true, 'cancelImg' : '/photos/cancel.png', onComplete : function(event, queueID, fileObj, response, data) { var dat = eval('(' + response + ')'); if (dat.result=='success'){ jQuery.getScript(dat.upload); }else{ alert("Only .jpg, .gif, .png files under 2MB allowed. ") } }, 'scriptData' : { 'format' : 'json', '<%= session_key_name %>' : encodeURIComponent('<%= u cookies[session_key_name] %>'), 'authenticity_token' : encodeURIComponent('<%= u form_authenticity_token if protect_against_forgery? %>'), 'attachable_id' : '<%= @album.id %>', 'parent' : 'Album'} }); jQuery('#photo_submit').click(function(event){ event.preventDefault(); jQuery('#photo_upload').uploadifyUpload(); }); }); </script> <% form_for Image.new(:attachable_id => @deal.id), :html => { :multipart => true } do |f| %> <div class="image-uploader"> <%= f.file_field :data, :id => 'image_upload' %> <%= f.submit "Upload Images", :id => 'image_submit'%> </div> <% end %> |
Many thanks to the following articles that helped me figure out how to get this working
Please follow the links for more detailed explanations
http://fencore.posterous.com/uploadify-with-paperclip-on-rails-tutorial
http://timmyc.posterous.com/uploadify-on-rails-with-paperclip
http://www.practicalecommerce.com/blogs/post/432-Multiple-Attachments-in-Rails
http://www.utoronto.ca/web/htmldocs/book/book-3ed/appb/mimetype.html
http://en.wikipedia.org/wiki/Internet_media_type
Posted Under Coding Tips Rails
July 25, 2010
Posted by roadburn
Here’s a useful tip I found from http://ariejan.net/2007/03/27/rails-tip-snippet-create-a-comma-seperate-list/
To get ‘Tom, Dick, Harry’
1 | @users.collect{|u| u.name}.join(', ') |
To get ‘Tom, Dick and Harry’
1 | @users.collect(&:name).to_sentence |
Posted Under Rails
July 23, 2010
Posted by roadburn
Another reason to love rails, it’s so easy!
Just install the acts_as_tree plugin
1 | $ script/plugin install git://github.com/rails/acts_as_tree.git |
and in your model, eg. app/models/category.rb, just add
1 | acts_as_tree :order => 'name' |
And here’s the plugin’s readme on how to use it
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | acts_as_tree ============ Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children association. This requires that you have a foreign key column, which by default is called +parent_id+. class Category < ActiveRecord::Base acts_as_tree :order => "name" end Example: root \_ child1 \_ subchild1 \_ subchild2 root = Category.create("name" => "root") child1 = root.children.create("name" => "child1") subchild1 = child1.children.create("name" => "subchild1") root.parent # => nil child1.parent # => root root.children # => [child1] root.children.first.children.first # => subchild1 |
Resources
Posted Under Rails
Dan Weinand and Luke Francl have written a nice plugin which simplifies the task of retrieving emails. Kudos to them!
So basically what you need to do is install the plugin, create the Action Mailer receiver, and then use cron to schedule the script to run
Here are the steps:
First install the fetcher plugin from http://github.com/look/fetcher/ and SystemTimer gem it requires
$ script/plugin install git://github.com/look/fetcher.git $ sudo gem install SystemTimer
Create your ruby script eg. script/mail_fetcher
#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../config/environment.rb' require 'system_timer' require 'yaml' require 'fetcher' begin puts "Start checking email" Lockfile.new('cron_mail_fetcher.lock', :retries => 0) do config = YAML.load_file("#{RAILS_ROOT}/config/mail.yml") config = config[RAILS_ENV].to_options fetcher = Fetcher.create({:receiver => EnquiryMailer}.merge(config)) fetcher.fetch end rescue Lockfile::MaxTriesLockError => e puts "Another fetcher is already running. Exiting." end
Create the config/mail.yml file
defaults: &defaults # Settings for gmail type: imap # pop OR imap server: imap.gmail.com # server hostname port: 993 # 993 for IMAPs ssl: true # Remove if not using SSL username: user@gmail.com # Username password: xxx # Password use_login: true # Required for GMAIL processed_folder: processed error_folder: error # settings for bluehost type: imap # pop OR imap server: boxXXX.bluehost.com # server hostname port: 993 # 993 for IMAPs ssl: true # Remove if not using SSL username: user@domain.com # Username password: xxx # Password use_login: true processed_folder: INBOX.processed error_folder: INBOX.error development: <<: *defaults # Override other values here test: <<: *defaults # Override other values here production: <<: *defaults # Override other values here
Create your Action Mailer
$ script/generate mailer EnquiryMailerAdd the receiver in app/models/enquiry_mailer.rb
class EnquiryMailer < ActionMailer::Base def receive(email) # do whatever you want with the email here # you can use: # email.subject, email.from, email.body end end
Run the script
$ script/runner script/mail_fetcher
Then follow Ryan Bate’s screencast on how to use Cron in Ruby
Resources
July 21, 2010
Posted by roadburn
I was getting this error when trying to create a mailbox using create(mailbox) from Net::IMAP
1 | /opt/local/lib/ruby/1.8/net/imap.rb:981:in `pick_up_tagged_response': Unknown namespace. (Net::IMAP::NoResponseError) |
Realised that the processed and error mailboxes names had to be appended to “INBOX.”
1 2 3 4 5 6 7 8 9 | type: imap server: boxXXX.bluehost.com port: 993 ssl: true username: username@domain.com password: xxx use_login: true processed_folder: INBOX.processed error_folder: INBOX.error |
Posted Under Rails
February 18, 2009
Posted by roadburn
1 2 3 4 5 6 7 | sudo aptitude install memcached sudo aptitude install libmemcache-dev sudo gem install RubyInline sudo gem install memcache-client |
in application.rb
Uncomment the protect_from_forgery
in environment.rb
1 2 3 4 5 6 7 8 9 | CACHE = MemCache.new 'localhost:11211', :namespace => 'your_app' config.action_controller.session = { :session_key => '_your_app_session', :secret => 'yoursecrectkey', :cache => CACHE, :expires=> 900 } config.action_controller.session_store = :mem_cache_store |
Posted Under Rails
December 25, 2008
Posted by roadburn
View the railscast on using thoughtbot’s paperclip
http://railscasts.com/episodes/134-paperclip
or
attach multiple images to a model using polymorphic paperclip
http://burm.net/2008/10/17/ruby-on-rails-polymorphic-paperclip-plugin-tutorial/
Posted Under Rails