Blog

Aug
03

Comatose, Authlogic and FCKEditor

Ok so we are using comatose and Authlogic for an app we are building for a client. We also wanted to use FCKEditor for comatose to give it a little more buzz.

Firstly you need to install Comatose. Go to your project root directory in terminal and type the following.

./script/plugin source http://mattmccray.com/svn/rails/plugins
./script/plugin install comatose
./script/generate comatose_migration
rake migrate

Then you need to install fckEditor. To do so go to the root of your app in terminal and type the following

ruby script/plugin install svn://rubyforge.org//var/svn/fckeditorp/trunk/fckeditor

In the Comatose _form.html.erb page you need to change

<%= f.text_area :body, :rows=>20, :tabindex=>2 %>

to this so that the fckeditor appears when creating and editing pages.

<%= fckeditor_textarea('page', 'body', :width => '100%', :height => '500px') %>

Once you have Comatose and FCKEditor installed and running the final step is to get it all working with Authlogic.

So in your environment.rb file you need to add the following.

Comatose.configure do |config|
  #Custom class we wrote to handle current_user etc
  config.admin_includes << :user_methodss
  # Calls :login_required as a before_filter
    config.admin_authorization = :require_user
end

This will force comatose to have require a user to be logged in to use the system. The :user_methodss class is a class we wrote to handle the login methods of Autlogic. You can replace this with your own if you want ill include the class we created below.

module UserMethods
  module ClassMethods
    def permission_required(permission_name,actions, notice=nil)
      notice ||= "You don't have access to that part of the site."
      actions = [actions].flatten
      before_filter(:only => actions) { |controller| require_or_redirect(permission_name, controller, notice) }
    end

    def require_or_redirect(permission_name, controller, notice)
      user = controller.send(:current_user)

      if !user.can?(permission_name)
        # @permission_missing is used for should_require_permission test
        controller.instance_variable_set("@permission_missing", true)
        controller.send(:redirect_back_or_to, "/", notice)
      end
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end

  protected 

  # Redirects back or if that fails, redirects to the supplied path
  # Also accepts a notice if you want to flash something
  def redirect_back_or_to(path, notice=nil)
    flash[:notice] = notice unless notice.blank?
    begin
      redirect_to :back
    rescue ActionController::RedirectBackError
      redirect_to path
    end
  end

  # Returns the param to use in a find command for objects with a
  # possible cross-db sort
  def cross_database_order(order, direction, sort_methods_allowed)
    return "#{ order } #{ direction }" if !cross_database_sort?(order, sort_methods_allowed)
  end

  # Returns true if the given order looks like a cross db sort
  # Allowed_methods should be an array of association objects to
  # methods allowed to be called on them.
  def cross_database_sort?(order, allowed_methods)
    return allowed_methods.include?(order)
  end

  # Performs a sort on the given objects by calling methods rather than
  # using a db lookup.
  def cross_database_sort(objects_to_sort, order, direction, sort_methods_allowed)
    if cross_database_sort?(order, sort_methods_allowed)
      methods = order.split(".")
      association_name, method = order.split(".")
      objects_to_sort = objects_to_sort.sort_by do |object|
        methods.each do |meth|
          next if object.nil?
          object = object.send(meth)
        end
        "#{ object }"
      end
      objects_to_sort.reverse! if direction == "desc"
    end

    return objects_to_sort
  end

  private

  # ActionMailer views don't have access to the request, so we need
  # to set these variables manually.
  def setup_host_for_mail
    ActionMailer::Base.default_url_options[:host] = request.host_with_port
  end

  def logout
    current_user_session.destroy if current_user_session
  end

  def current_user_session
    return @current_user_session if defined?(@current_user_session)
    @current_user_session = UserSession.find
  end

  def current_user
    return @current_user if defined?(@current_user)
    @current_user = current_user_session && current_user_session.user
  end

  def require_user
    unless current_user
      store_location
      flash[:notice] = "You must be logged in to access this page"
      redirect_to new_user_session_url
      return false
    end
  end

  def require_no_user
    if current_user
      store_location
      flash[:notice] = "You must be logged out to access this page"
      redirect_to "/"
      return false
    end
  end

  def store_location
    session[:return_to] = request.request_uri
  end

  def redirect_back_or_default(default)
    redirect_to(session[:return_to] || default)
    session[:return_to] = nil
  end
end

Worth noting the “ss” in user_methodss is not a mistake. Because of the way Comatose handles the string/symbol you pass in it wouldn’t render :user_methods but instead looked for :users_methods which was incorrect so this was our little hack to get around that.

Jul
29

Lowpro + prototype and Firefox 3.5

Posted by Michael Cindric in development, javascript, lowpro, open source | No Comments »

So it turns out lowpro is broken in the latest Firefox. Anyways DanWebb has released a fix for this which you can read more about here.

Now this didn’t solve my issues all together. I ran into an issue as the JavaScript was loading before the page was completely loading and thus the behaviours were not been added.

So the solution is to add the following

Event.observe(window, 'load', function() {
  Event.addBehavior({
    // assign behaviors
  });
}

That way the behaviours don’t get added until after the DOM has fully loaded.

May
29

Getting JQuery and Prototype to place nice

Posted by Michael Cindric in development, javascript, jquery | No Comments »

If you want to use JQuery in your rails application but still want prototype working as well there is a simple way to make sure they play nice and work side by side. All you have to do after you include your JQuery includes code is have the following

  <script>
   var $j = jQuery.noConflict();
  </script>

Now all you have to do to use jquery is use “$j” instead of just “$” and your good to go. To use just the standard prototype library is still just “$”. Simple isn’t it

May
08

Application templates in Ruby on Rails

Posted by Michael Cindric in development, javascript, jquery, ruby on rails | 4 Comments »

Here is the latest application template we have put together. It removes all the usual items and adds the base gems that we use for all our applications. It also creates the files needed for deployment and runs “Capify” on the project, plus a few other things such as sass etc.

# Remove unnecessary Rails files
run 'rm README'
run 'rm public/index.html'
run 'rm public/favicon.ico'
run 'rm public/images/rails.png'
run 'rm -f public/javascripts/*'

# Download JQuery
run "curl -s -L http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js > public/javascripts/jquery.js"
run "curl -s -L http://jqueryjs.googlecode.com/svn/trunk/plugins/form/jquery.form.js > public/javascripts/jquery.form.js"

#Configure required gems
gem "haml", :version => "2.0.4"
gem 'thoughtbot-shoulda', :lib => 'shoulda', :source => 'http://gems.github.com'
gem "thoughtbot-factory_girl", :lib => "factory_girl", :source => "http://gems.github.com"

#Create Sass directory
run 'mkdir public/stylesheets/sass'

#Capify and create production environment.rb
run 'mkdir config/deploy'
run 'touch config/deploy/production.rb'

#Add UAT environment and settings
file 'config/environments/uat.rb', <<-CODE
# Settings specified here will take precedence over those in config/environment.rb

# Code is not reloaded between requests. Server needs to be restarted.
config.cache_classes = true

# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true

# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching             = true
config.action_view.cache_template_loading            = true

# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
CODE

#Create gitignore file and setup base ignores
run "touch tmp/.gitignore log/.gitignore vendor/.gitignore"
file '.gitignore', <<-FILE
.DS_Store
log/*.log
tmp/**/*
db/*.sqlite3
public/stylesheets/*.css
FILE

# Set up git repository
git :init
git :add => '.'
git :commit => "-a -m 'Initial commit'"

# Success!
puts "SUCCESS!"
Mar
17

Ajax.Updater and javascript

Posted by Michael Cindric in javascript, ruby on rails | 2 Comments »

Ran into a little problem today which made me think for a second. I have a Javascript function that runs once a calendar control is closed. It just passes a parameter to a action which renders a view nothing fancy.

So my onClose function looks like so

function onClose(cal) {
	var p = cal.params;
	new Ajax.Updater('overlapping', '/visits/new', {
	  parameters: { start_date:  p.inputField.value; },
	  evalScripts: true
	});
	cal.hide();
};

This will fire once the calendar is closed. ‘Overlapping’ is the ID of the Div ill be updating and ‘/visits/new’ is the path of the action in your controller. This will then pass the start date param to the action which can then be used in the view. The problem l had is that l had some javascript on the partial that was not executing. Had to think for a minute and then it turned out that evalScripts is false by default thus the javascript was not executing.

So its as simple as having the following as a param in your Ajax.updater

 evalScripts: true

Once you have done that your good to go.