Best ruby-on-rails questions in February 2011

Does Ruby on Rails affect how a web page looks?

32 votes

Most of the time, whenever I hit a website that looks "bubbly" in nature, and all prettified in those pastel-like colors, I think to myself, "This was probably done with Rails." And, lo and behold, after some digging into the site's information pages I discover this is actually true. So, I pose the question, not knowing much about Rails but enough about Django to understand how the database stuff works:

Does RoR have any display-specific qualities that affect how a web page looks? Or do all RoR devs naturally use the same Adobe tools to make everything look so ubiquitous?

Ruby on Rails is a server side technology, so it doesn't lend any specific quality to the user visible design. That said, it is a "trendy" technology so people who are likely to write their back-end code with RoR are likely to choose a particular "Web 2.0" style for their views.

It's kind of like saying "I notice that douches tend to wear backwards baseball caps and wear really baggy jeans. Does wearing a backwards baseball cap affect the tightness of one's jeans?" And the answer would be, no, however, a douche is likely to choose both of these clothing items.

Groovy/Grails :: Ruby/Rails :: 2011 State of the framework

10 votes

Hey All.

Yes, several similar threads exist, but we're now in 2011, and much has changed.

Grails 1.3.6 has improved hugely compared to v1.3 when I initially tried to learn the framework (and gave up to slow compile times and other groan inducing events).

Having spent a couple months with the latest release, I am impressed, protyping an app is an absolute breeze (GORM is great!). In development mode one no longer needs to restart, barring changes to domain classes. Groovy.lang is fantastic (bare in mind, this is compared to my day job life in PHP).

Now, on the flip side there is Ruby/Rails, which I have little experience with beyond perusing Ruby docs and exploring Active Record (to compare to GORM). Coming from PHP/Jquery, groovy syntax is cake, ruby not so much, although accessible.

Ruby/Rails is all the rage, while Groovy/Grails seems to be picking up speed in its own right.

I'd like to hear what both camps have to say (flame inducing lang war welcome) re: pros/cons of both langs/frameworks now in 2011. When choosing a framework it's important to know what you're getting into, so have at it, newbies will benefit, and experts can vent ;--)

Rails and Grails are both excellent frameworks with their current releases. You really can't go wrong with either. Here are some things I find interesting about them though:

Rails

  • Rails (Ruby) does not scale as well as Grails (Groovy). You will need more horsepower to run your application. This isn't a big deal at all with PaaS options like EngineYard (and hopefully a AWS BeanStalk Rails option in the future), but it might just cost a little more to run a Rails app vs a Grails app (obviously JRuby is also an option to though).
  • Rails is slightly better with NoSQL alternatives currently, but Grails is catching up quickly
  • Rails has many more plugins, but this can lead to trouble if you use some that aren't maintained (a lot of them don't currently work with Rails 3 yet either).
  • Rails is more mature and has more features at this point in time because it's been around longer
  • Rails REST support is amazing
  • There are many more "big" Rails websites than Grails
  • Ruby is much more popular than Groovy - TIOBE
  • No dependence on Oracle, ha! (Grails obviously needs the JVM)

Grails

  • Grails integrates with the JVM better than JRuby
  • Grails GORM is better than ActiveRecord (IMHO), although Rails 3 opened the door a little bit for other persistence options, but all the books, tutorials, etc all use ActiveRecord
  • Grails View taglibs are better than <=%...%> in view
  • Grails plugins are well documented and clearly state whether they are supported by SpringSource or not
  • SpringSource is investing heavily in Grails
  • There will be many more corporate jobs for Grails than Rails in the future, but more startups use Rails (where do you want to work?)

My perspective

  • I used Rails a couple years ago, I'm working on a Grails project now
  • I like them both better than Django (Python) or Zend Framework (PHP)
  • I plan to learn Lift (Scala) next

My Recommendation

  • If you have never done Java development and are working on a side project for a small to medium website, go with Rails
  • If you are working at a big company that uses Java, try pitching Grails to your management as the "next Java framework" they should invest in
  • If you are working on "the next twitter or foursquare," well then you are smart enough to answer this question yourself! :)

Rails - how can I make a request that doesn't hit the database at all?

9 votes

In order to trace some performance issues, I'm trying to create a page that is rendered through the Rails (2.3.8) framework but makes no calls whatsoever to the database.

I want the request to go through the typical middleware (routes.rb > controller > view), as opposed to rendering a simple static page (like 404.html), and in it should work when the db server is turned off (web server still running). The actual rendered page is a simple html page displaying the currency time using erb. Right now I get error when I turn off the database, and I can see 2 queries that are still made:

SQL (0.1ms)   SET NAMES 'utf8'
SQL (0.1ms)   SET SQL_AUTO_IS_NULL=0

Any idea how to override the db completely while making that request? thanks.

The only way to get around it is to override the configure_connection function in ActiveRecord. To do this I would recommend making an ApplicationController function named skip_sql? to test whether you want to skip the configure_connection function for some controller#action combinations:

class ApplicationController
  def skip_sql?
    params[:controller] == "..." && params[:action] == "..."
  end
end

Then make this function available to your classes and models:

module SkipSql
  module Controller
    def self.included(base)
      base.prepend_before_filter :assign_skip_sql_to_models
    end

    def assign_skip_sql_to_models
      ActiveRecord::Base.skip_sql_proc = proc {send(:skip_sql?)}
    end
  end
  module Model
    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      attr_accessor :skip_sql_proc

      def skip_sql?
        ActiveRecord::Base.skip_sql_proc.call if ActiveRecord::Base.skip_sql_proc
      end

    end

    def skip_sql?
      self.class.skip_sql?
    end
  end
end

Object.send :include, SkipSql::Model::ClassMethods
ActionController::Base.class_eval {include SkipSql::Controller}

Then skip sql only on the controller#action combinations you have set:

class ActiveRecord::ConnectionAdapters::MysqlAdapter
  def configure_connection
    unless skip_sql?
      encoding = @config[:encoding]
      execute("SET NAMES '#{encoding}'", :skip_logging) if encoding

      execute("SET SQL_AUTO_IS_NULL=0", :skip_logging)
    end
  end
end

If the configure_connection one doesn't work I would try the connect method like this:

class ActiveRecord::ConnectionAdapters::MysqlAdapter
  alias :old_connect :connect

  def connect
    old_connect unless skip_sql?
  end

  alias :old_active? :active?

  def active?
    skip_sql? ? false : old_active?
  end
end

I believe the connect method gets called before the configure connection method, so it should help with the socket issue.

Playframework vs Ruby On Rails

9 votes

Yet another LanguageX vs LanguageY question....

Currently I have a bunch of apps built on playframework. For the most part I love it. Moving from PHP a few years ago was almost a religious experience -- an actual functional orm, much less boiler plate code, stuff just worked, etc.

I still have a website running on a a shared hosting service thats built with PHP+CodeIgniter. Recently I've been adding some features to this site and have been thinking about porting it to either Ruby on Rails or Playframework.

So far though, nothing about rails has really blown me away. It seems like it has pretty much the same featureset as playframework. I like ruby's terseness, and things like blocks, but again for the most part there's been nothing about the language itself that has made me go "oh wow this is 1000x better than java/php/c/whatever!" In fact, some parts actually kind of rub me the wrong way -- I prefer strongly-typed languages for example.

My question is, am I likely to find anything in the framework or language that's really going to differentiate it from java+play for me, or are they pretty much the same and primarily just differentiated by things like personal preference about syntax and developer community?

Play framework is gracious enough to acknowledge RoR's inspiration. (Unlike some people who copied an entire platform and give absolutely no credit to the original)

If Play team have done a good job, it's no wonder that a person is not impressed by RoR if he learned Play first. So if you find Play quite comfortable, there's no compelling reason to go RoR.

Client Server API pattern in REST (unreliable network use case)

7 votes

Let's assume we have a client/server interaction happening over unreliable network (packet drop). A client is calling server's RESTful api (over http over tcp):

  • issuing a POST to http://server.com/products
  • server is creating an object of "product" resource (persists it to a database, etc)
  • server is returning 201 Created with a Location header of "http://server.com/products/12345"
  • ! TCP packet containing an http response gets dropped and eventually this leads to a tcp connection reset

I see the following problem: the client will never get an ID of a newly created resource yet the server will have a resource created.

Questions: Is this application level behavior or should framework take care of that? How should a web framework (and Rails in particular) handle a situation like that? Are there any articles/whitepapers on REST for this topic?

If it isn't reasonable for duplicate resources to be created (e.g. products with identical titles, descriptions, etc.), then unique identifiers can be generated on the server which can be tracked against created resources to prevent duplicate requests from being processed. Unlike Darrel's suggestion of generating unique IDs on the client, this would also prevent separate users from creating duplicate resources (which you may or may not find desirable). Clients will be able to distinguish between "created" responses and "duplicate" responses by their response codes (201 and 303 respectively, in my example below).

Pseudocode for generating such an identifier — in this case, a hash of a canonical representation of the request:

func product_POST
    // the canonical representation need not contain every field in
    // the request, just those which contribute to its "identity"
    tags = join sorted request.tags
    canonical = join [request.name, request.maker, tags, request.desc]
    id = hash canonical

    if id in products
        http303 products[id]
    else
        products[id] = create_product_from request
        http201 products[id]
    end
end

This ID may or may not be part of the created resources' URIs. Personally, I'd be inclined to track them separately — at the cost of an extra lookup table — if the URIs were going to be exposed to users, as hashes tend to be ugly and difficult for humans to remember.

In many cases, it also makes sense to "expire" these unique hashes after some time. For example, if you were to make a money transfer API, a user transferring the same amount of money to the same person a few minutes apart probably indicates that the client never received the "success" response. If a user transfers the same amount of money to the same person once a month, on the other hand, they're probably paying their rent. ;-)

Rails not reloading session on ajax post

7 votes

Hello,

I'm experiencing a very strange problem with Rails and ajax using jQuery (although I don't think it's specific to jQuery).

My Rails application uses the cookie session store, and I have a very simple login that sets the user id in the session. If the user_id isn't set in the session, it redirects to a login page. This works with no problems. JQuery GET requests work fine too. The problem is when I do a jQuery POST - the browser sends the session cookie ok (I confirmed this with Firebug and dumping request.cookies to the log) but the session is blank, i.e. session is {}.

I'm doing this in my application.js:

$(document).ajaxSend(function(e, xhr, options) {
  var token = $("meta[name='csrf-token']").attr('content');
  xhr.setRequestHeader('X-CSRF-Token', token);
});

and here is my sample post:

$.post('/test/1', { _method: 'delete' }, null, 'json');

which should get to this controller method (_method: delete):

def destroy
  respond_to do |format|
    format.json { render :json => { :destroyed => 'ok' }.to_json }
  end
end

Looking at the log and using Firebug I can confirm that the correct cookie value is sent in the request header when the ajax post occurs, but it seems that at some point Rails loses this value and therefore loses the session, so it redirects to the login page and never gets to the method.

I've tried everything I can think of to debug this but I'm coming around to the idea that this might be a bug in Rails. I'm using Rails 3.0.4 and jQuery 1.5 if that helps. I find it very strange that regular (i.e. non-ajax) get and post requests work, and ajax get requests work with no problems, it's just the ajax posts that don't.

Any help in trying to fix this would be greatly appreciated!

Many thanks,
Dave

I'm going to answer my own question as I've managed to work out what was going on. I'll post it here in case it's useful to anyone else!

After investigating further, I worked out that the code that was supposed to be setting the request header with the CSRF token, wasn't. This was the original code:

$(document).ajaxSend(function(e, xhr, options) {
  var token = $("meta[name='csrf-token']").attr('content');
  xhr.setRequestHeader('X-CSRF-Token', token);
});

What was happening was that this code wasn't setting the header, Rails was receiving an Ajax request, the token didn't match and it was resetting the session. This used to raise an ActionController::InvalidAuthenticityToken error (I suppose I would have caught this earlier if an error was raised... oh well), but since Rails 3.0.4 it now just quietly resets the session.

So to send the token in the header, you have to do this (many thanks to this marvellous blog post):

$.ajaxSetup({
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
  }
}); 

And now it all works as it should. Which is nice.

How to add tagging with autocomplete to an existing model in Rails?

6 votes

I'm trying to add "tags" to an Article model in a Rails 3 application.

I'm wondering if there is a gem or plugin that has adds both the "tagging" functionality in the model and also the auto-complete helpers for the views.

I've found acts_as_taggable but I'm not sure if that's what I should be using. Is there something newer? I'm getting results from 2007 when I google acts_as_taggable

acts_as_taggable_on and rails3-jquery-autocomplete work nicely together to make a SO like tagging system see example below. I don't think a suitable all in one option exists yet for rails.

Follow these steps to get this all installed:

1 . Backup your rails app!

2 . Install jquery-rails

Note: You can install jQuery UI with jquery-rails but I chose not to.

3 . Download and install jQuery UI

Choose a theme that will compliment your web design (be sure to test the autocomplete demo with the theme you choose, the default theme did not work for me). Download the custom zip and place the [zipfile]/js/jquery-ui-#.#.#.custom.min.js file into your app's /public/javascript/ folder. place the [zipfile]/css/custom-theme/ folder and all files into your app's public/stylesheets/custom-theme/ folder.

4 . Add the following to your Gemfile and then run "bundle install"

gem 'acts-as-taggable-on'
gem 'rails3-jquery-autocomplete'

5 . From the console run the following commands:

rails generate acts_as_taggable_on:migration
rake db:migrate
rails generate autocomplete

Make these changes in your app

Include the necessary javascript and css files in your application layout:

<%= stylesheet_link_tag "application", "custom-theme/jquery-ui-1.8.9.custom" %>  
<%= javascript_include_tag :defaults, "jquery-ui-#.#.#.custom.min", "autocomplete-rails" %>

Controller Example

class ArticlesController < Admin::BaseController      
  autocomplete :tag, :name
end

Model Example

class Article < ActiveRecord::Base
   acts_as_taggable_on :tags
end

Route.rb

resources :articles do
  get :autocomplete_tag_name, :on => :collection    
end

View Example

<%= form_for(@article) do |f| %>
  <%= f.autocomplete_field :tag_list, autocomplete_tag_name_articles_path, :"data-delimiter" => ', ' %> 
  # note tag_list above is a virtual column created by acts_as_taggable_on
<% end %> 

Note: This example assumes that you are only tagging one model in your entire app and you are only using the default tag type :tags. Basically the code above will search all tags and not limit them to "Article" tags.

Rails and partials, is there a more efficent way of writing this...?

6 votes

I've got a partial in a loop like so...

<% things.each do |thing| %><%= render :partial => "thingy", :locals => { :something  => something, :thing  => thing } %><% end %>

This just doesn't seem very railsy, I was wondering if there more efficient way of putting partials in a loop.

Rename your partial from 'thingy' to 'thing' and do this:

<%= render things, :locals => { :something => :goatse } %>

I couldn't think of anything more Railsy.

how to cross direct user with google analytics

6 votes

After a user fills in my "new" user form on "example-one.com", the "create" controller creates the record in the db. Then it does a redirect_to to an external site "payment-checkout.com". I have setup the Google Analytics code on both sites.

Google provides two functions _link and _linkByPost for use to use in any links or forms that go to your external domains. The problem is the user is being redirected by the controller action outside of the view and I cant use those two javascript functions to pass on the relevent G.A. info - what do i do?

Can anyone help?

The way _link works is by passing the Google Analytics cookies from your first domain via a query string to your second domain. The second domain, if configured correctly, will accept those URL parameters and apply them as cookie values for the purposes of tracking.

So, it shouldn't be difficult for you to apply your own version of the _link function.

Specifically, the _link function passes the following cookies:

__utma, __utmb, __utmc, __utmx, __utmz, __utmv and __utmk

Into a query string as such: ?__utma=87278922.614105561.1288923931.1294376393.1298325957.6&__utmb=87278922.1.10.1298325957&__utmc=87278922&__utmx=-&__utmz=87278922.1288923931.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)&__utmv=-&__utmk=72493274

So, all you need to do to replicate the _link function is, before you apply the server side redirect, grab the cookie values, and apply them as a query string on the URL you're redirecting to.

Now, that's not the only thing you'll need to do to get this working. The Google Analytics configuration on the payment site will need to be configured with _setAllowLinker set to true, as well as potentially disabling the domain hash and setting a particular domain name for the tracking cookies; it depends on your configuration. You can find out more about that in Google Analytics Cross Domain Tracking Guide.

Would MongoDB be a good idea for a social network site (developed in Ruby on Rails)?

6 votes

Hello,

my project (in Ruby on Rails 3) is to develop a "social network" site with the following features:

  • Users can be friends. It's mutual friendships; not asymetric like Twitter.
  • Users can publish links, to share them. Friends of a user can see what this user has shared.
  • Friends can comment on those shared links.

So basically we have Users, Links, and Comments, and all that is connected. An interesting thing in social networks is that the User table has kind of a many-to-many relation with itself.

I think I can handle that level of complexity with SQL and RoR.

My question is: would it be a good idea to use MongoDB (or CouchDB) for such a site?

To be honest, I think the answer is no. MongoDB doesn't seem to fit really well with many-to-many relationships. I can't think of a good MongoDB way to implement the friendship relationships. And I've read that Diaspora started with MongoDB but then switched back to classic SQL.

But some articles on the web defend MongoDB for social networks, and above all I want to make a well-informed decision, and not miss a really cool aspect of MongoDB that would change my life.

Also, I've heard about graph DB, which are probably great, but they really seem too young to me, and I don't know how they'd fit with RoR (and not mentioning heroku).

So, am I missing something?

Thanks,

arthur

I like MongoDB and use it a lot, but I am of the opinion that if you are dealing with relational data, you should use the right tool for it. We have relational databases for that. Mongo and Couch are document stores.

Mongo has a serious disadvantage if you are going to be maintaining a lot of inter-document links. Writes are only guaranteed to be atomic for one document. So you could have inconsistent updates for relations if you are not careful with your schema.

The good thing about MongoDB is that it is very good at scaling. You can shard and create replica sets. Foursquare currently uses MongoDB and it has been working pretty well for them. MongoDB also does map-reduce and has decent geospatial integration. The team that develops MongoDB is excellent, and I live in NY where they are based and have met them. You probably are not going to have scaling issues though I would think starting out.

As far as Diaspora switching... I would not want to follow anything they are doing :)

Your comment about graph dbs is interesting though. I would probably not use a graph DB as my primary DB either, but when dealing with relationships, you can do amazing things with them. In fact usually the demo the guys from graph DB companies will give you is extracting relationship knowledge from a social network. However, there is nothing preventing you from playing with these in the future for network analysis.

In conclusion, when you are starting out here, you are not running into the problems of massive scale yet, and are probably limited on time and money. Keep in mind that even Facebook does not use just one technology, they have basically expanded to NoSQL for certain functionality (like Facebook messaging). There is nothing stopping you in the future from using say Mongo and gridFS for handling image uploads or geo-location etc. It is good to grow as your needs change. I think your gut feeling that you have an SQL app here is right, and the benefits gained with MongoDB would not be realized for a while.

6 votes

I am wondering what is the general consensus for uploading moderately large files. I have a web app, and every time a user uploads a file (typically larger than 5mb), the web server tends to hang until the file upload is finished.

The above seems normal, because a single upload can take up a single HTTP request handler. Do web devs take this into consideration and either:

a) Pay for more HTTP handlers

b) Use some other method to overcome this by using AJAX, or other approach

I've heard that it is quite normal for web apps to have a few HTTP request handlers to take care of this, which will cost quite a bit more. On the other, if cost is an issue, then some have suggested trying to upload directly to the web server or storage service (i.e. Amazon S3) directly via Flash + AJAX. The latter method takes a bit of scripting and is a bit messy.

My second concern:

By using ajax to upload files onto a server. Does this still take up a whole HTTP request handler? i.e. does the server hang until the upload is finished?

Even with flash, I would still need to specify a url to upload to. The url would be one of the actions on my controller. Which would mean that processing still takes place on the server side. Is this right so far?

I was thinking. If I were, in the other hand, to use one of the upload scripts (plupload, uploadify, swfupload, etc) to upload directly to Amazon S3, then the processing is handled on the S3 server instead of the local web server. Which wont hang the web app at all. Am I understanding this correctly?

Would like to hear your feedback.

Thanks for the responses so far.

Unfortunately, our host Heroku does not support non-blocking, evented servers. I've also tried flash + javascript based uploaders like SWFUpload, Uploadify. Some variations of the mentioned plugins worked, and some didn't. Spent countless hours of trial and error, but didnt like how the code was being integrated on my Rails app.

In the end, went with manually uploading the file to S3 directly following this link. Which also enables a response back from the S3 server to notify us that an upload was successful, giving us the path to the uploaded file so that we can then create a background job (via redis + resque) to process the file.

Initializing class instance variables in Ruby

5 votes

Hello everybody, I am working on a small rails app and have a problem with ruby's OOP model. I have the following simplified class structure.

class Foo
  protected
    @bar = []
    def self.add_bar(val)
      @bar += val
    end
    def self.get_bar
      @bar
    end
end

class Baz < Foo
  add_bar ["a", "b", "c"]
end

My problem is now, that when I call add_bar in the class definition of Baz, @bar is apparently not initialized and I get an error that the + Operator is not available for nil. Calling add_bar on Foo directly does not yield this problem. Why is that and how can I initialize @bar correctly?

To make clear what I want, I will point out the behavior I would expect from these classes.

Foo.add_bar ["a", "b"]
Baz.add_bar ["1", "2"]
Foo.get_bar # => ["a", "b"]
Baz.get_bar # => ["a", "b", "1", "2"]

How could I achieve this?

Short answer: instance variables don't get inherited by subclasses

Longer answer: the problem is that you wrote @bar = [] in the body of the class (outside any method). When you set an instance variable, it is stored on whatever is currently self. When you're in a class body, self is the class object Foo. So, in your example, @foo gets defined on the class object Foo.

Later, when you try to look up an instance variable, Ruby looks in whatever is currently self. When you call add_bar from Baz, self is Baz. Also self is STILL Baz in the body of add_bar (even though that method is in Foo). So, Ruby looks for @bar in Baz and can't find it (because you defined it in Foo).

Here's an example that might make this clearer

class Foo
  @bar = "I'm defined on the class object Foo. self is #{self}"

 def self.get_bar
    puts "In the class method. self is #{self}"    
    @bar
  end

  def get_bar
    puts "In the instance method. self is #{self} (can't see @bar!)"
    @bar
  end
end

>> Foo.get_bar
In the class method. self is Foo
=> "I'm defined on the class object Foo. self is Foo"

>> Foo.new.get_bar
In the instance method. self is #<Foo:0x1056eaea0> (can't see @bar!)
=> nil

This is admittedly a bit confusing, and a common stumbling point for people new to Ruby, so don't feel bad. This concept finally clicked for me when I read the 'Metaprogramming' chapter in Programming Ruby (aka "The Pickaxe").

How I'd solve your problem: Look at Rails' class_attribute method. It allows for the sort of thing you're trying to do (defining an attribute on a parent class that can get inherited (and overidden) in its subclasses).

How can I use Nokogiri to write a HUGE XML file?

5 votes

I have a Rails application that uses delayed_job in a reporting feature to run some very large reports. One of these generates a massive XML file and it can take literally days in the bad, old way the code is written. I thought that, having seen impressive benchmarks on the internet, Nokogiri could afford us some nontrivial performance gains.

However, the only examples I can find involve using the Nokogiri Builder to create an xml object, then using .to_xml to write the whole thing. But there isn't enough memory in my zip code to handle that for a file of this size.

So can I use Nokogiri to stream or write this data out to file?

Nokogiri is designed to build in memory because you build a DOM and it converts it to XML on the fly. It's easy to use, but there are trade-offs, and doing it in memory is one of them.

You might want to look into using Erubis to generate the XML. Rather than gather all the data before processing and keeping the logic in a controller, like we'd do with Rails, to save memory you can put your logic in the template and have it iterate over your data, which should help with the resource demands.

If you need the XML in a file you might need to do that using redirection:

erubis options templatefile.erb > xmlfile

This is a very simple example, but it shows you could easily define a template to generate XML:

<% 
asdf = (1..5).to_a 
%>
<xml>
  <element>
<% asdf.each do |i| %>
    <subelement><%= i %></subelement>
<% end %>
  </element>
</xml>

which, when I call erubis test.erb outputs:

<xml>
  <element>
    <subelement>1</subelement>
    <subelement>2</subelement>
    <subelement>3</subelement>
    <subelement>4</subelement>
    <subelement>5</subelement>
  </element>
</xml>

EDIT:

The string concatenation was taking forever...

Yes, it can simply because of garbage collection. You don't show any code example of how you're building your strings, but Ruby works better when you use << to append one string to another than when using +.

It also might work better to not try to keep everything in a string, but instead to write it immediately to disk, appending to an open file as you go.

Again, without code examples I'm shooting in the dark about what you might be doing or why things run slow.

In a Rails 3 view, how do I detect an URL in a display string and format it as a link to that URL?

5 votes

I have user generated comments on my site. If a user adds an URL in their comment, I'd like it to be formatted as a link and actually link to that URL. How do I do that?

Rails has an auto_link text helper.

auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com")
# => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
#     say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"

auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :urls)
# => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
#     or e-mail david@loudthinking.com"

Rails 3 application templates

5 votes

What Rails application templates show best practices for setting up a new Rails 3 application?

I'm interested in two things.

  1. Which application templates are designed well (modular and easily customized)?

  2. Which offer the best (or most popular) combination of components needed in a typical Rails app?

I'm asking about scripts that are used with the rails new app_name -m command to generate an application.


I've looked at some examples. What do you think of these?

greendog99/greendog-rails-template Devise, RSpec, Factory Girl, jQuery, Haml, Sass, Compass, Git, rvm, HTML5 Boilerplate, plus a layout. Uses subtemplates for easy customizing.

dcrec1/rails3_template Devise (with Cucumber steps), Cucumber, RSpec, Factory Girl, Haml, Compass, jQuery, Git, Formtastic, a layout, and more. Uses subtemplates for easy customizing.

aentos/rails3-templates Devise or Authlogic or OmniAuth, Cucumber, Capybara, RSpec, Factory Girl, Shoulda, jQuery, Haml, Compass, 960 grid or Blueprint, Capistrano or Heroku or Inploy, Git, plus a layout. Uses subtemplates for easy customizing.

rubyx/rails3_template PostgreSQL, Devise, Cucumber with Selenium and Capybara, RSpec with Machinist and Faker, JQuery, Simple Form, Haml, SASS, Git, rvm, Google analytics (optional), Hoptoad for issue tracking (optional), TellThemWhen for downtime notifications (optional). With a description of the recipe in the README.

perfectline/template-bucket Cucumber, RSpec, jQuery, Haml or Jammit, Capistrano, Git, rvm, plus a layout. Uses subtemplates for easy customizing.

leshill/rails3-app Cucumber, RSpec, Factory Girl or Fabrication, Haml, jQuery, Git, rvm.

These Rails 2.3 projects look like they were once popular but haven't been updated since 2009 or 2010:

jm/rails-templates

ffmike/BigOldRailsTemplate

After looking at everything I found, I decided to improve on the RailsWizard gem so I can easily create new starter apps using a mix-and-match set of popular gems.

I'm using the

rails3_devise_wizard

which is a version of the RailsWizard gem with custom recipes for a Devise starter app.

I've used it to create two application templates:

Rails 3 + Devise + RSpec + Cucumber Application Template

Rails 3 + Devise + RSpec + Cucumber + Mongoid Application Template

which generate the following example apps

Rails 3 + Devise + RSpec + Cucumber Example App

Rails 3 + Devise + RSpec + Cucumber + Mongoid Example App

and each has detailed tutorials showing how they're built:

Rails 3 + Devise + RSpec + Cucumber Tutorial

Rails 3 + Devise + RSpec + Cucumber + Mongoid Tutorial

Give a vote up if they are useful to you.

Devise Remember Me and Sessions

5 votes

I'm confused with the devise gem config settings:

  # The time the user will be remembered without asking for credentials again.
  config.remember_for = 2.weeks

  # The time you want to timeout the user session without activity. After this
  # time the user will be asked for credentials again.
  config.timeout_in = 10.minutes

I want to have a user select the "Remember Me" checkbox (i.e., keep me logged in), but the default session timeout is 10 minutes. After 10 minutes it asks me to log in again even though I have clicked "Remember me". If this is true then the remember_for is really meaningless. Obviously I'm missing something here.

The timeout_in will automatically log you out within 10 minutes of inactivity and is incompatible with the remember_me checkbox. You can have one, but not both.

Why use Ruby's attr_accessor, attr_reader and attr_writer?

5 votes

So Ruby has this handy and convenient way to "share" instance variables by using keys like

attr_accessor :var
attr_reader :var
attr_writer :var

And I use them quite often, but my question is: Why would I choose attr_reader or attr_writer if I could simply use attr_accessor? Is there something like, dunno, performance (which I doubt)?

I guess there is a reason, otherwise they wouldn't have made such keys, eh?

You may use the different accessors to communicate your intent to someone reading your code, and makes it easier to write classes which will work correctly no matter how their public API is called.

class Person
  attr_accessor :age
  ...
end

Here, I can see that I may both read and write the age.

class Person
  attr_reader :age
  ...
end

Here, I can see that I may only read the age. Presumably, it is set by the constructor of this class and remains constant. If there were a mutator (writer) for age and the class were written assuming that age, once set, does not change, then a bug could result from code calling that mutator.

But what is happening behind the scenes?

If you write:

attr_writer :age

That gets translated into:

def age=(value)
  @age = value
end

If you write:

attr_reader :age

That gets translated into:

def age
  @age
end

If you write:

attr_accessor :age

That gets translated into:

def age=(value)
  @age = value
end

def age
  @age
end

Knowing that, here's another way to think about it: If you did not have the attr_... helpers, and had to write the accessors yourself, would you write any more accessors than your class needed? For example, if age only needed to be read, would you also write a method allowing it to be written?