RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Hi Ryan, I have watched all your railscasts and I think you are doing a great job of helping people like me who are new to Rails.

I followed your tutorial and it works great. But, when I try to to the same thing for namespace routes I keep getting errors.

How do I create the same app within a namespace?

I have routes as:
namespace :admin do
resources :blogs do
resources :comments
end
end

and in the Show.html.erb I have:
New Comments
<%= form_for [:admin, @blog, Comment.new] do |f| %>
<%= f.label :body %> <%= f.text_field :body %>
<%= f.submit %>
<% end %>

Avatar

You can search across multiple indices (= model indices, eg. "articles" and "comments") with the Tire lower-level DSL. You can extract that into a separate class, search across the models and merge results manually by score, etc.

No built-in multimodel search a la ThinkingSphinx, at the moment...

You can see a discussion about this topic at https://github.com/karmi/tire/pull/131

Avatar

No problem @Dom. Ryan gives a nice overview in the screencast but there are some awesome features that aren't covered like date histogram facets and percolate queries that are worth looking into. The date histogram facet can group a field's total by month, week, day etc. For example, if you have a website with items and they belong to users, you can group the user's items by month with the date histogram facet. And, from ES's website, percolate queries...

Think of it as the reverse operation of indexing and then searching. Instead of sending docs, indexing them, and then running queries. One sends queries, registers them, and then sends docs and finds out which queries match that doc.

As an example, a user can register an interest (a query) on all tweets that contain the word “elasticsearch”. For every tweet, one can percolate the tweet against all registered user queries, and find out which ones matched."

Also, the documentation for the tire gem is somewhat lacking/confusing in my opinion so I had to do some extra research to find out how to add date boosting for queries and use different stemmers like KStem (KStem is less agressive than snowball and the other stemmers if you need stemming). It's really easy to customize your index settings to optimize for faster queries or faster indexing, setting up custom analyzers and changing your index schema.

Avatar

There are some "ES as service" providers, but no Heroku addon, yet.

However, the latency issues are not particularly interesting here, since Heroku runs on AWS, so you should get a very small latency when you set up your ES nodes at AWS.

Avatar

@Thomas

Not that I know of. Maybe the WebSolr guys would be interested in providing an ElasticSearch solution?

Avatar

I'm also interested in getting this to work on Heroku. Let me know if you manage to get it up and running!

Avatar

Thanks for summarizing for us @Daniel, I was going to ask the same question. I've been struggling with which engine to use for a production app. I watched this screencast with a bit of an attitude - oh crap another search engine. But after reading your reasoning I think I might give ES a go now, rather than the others. You've managed to turn me around.

Avatar

Tiago, your gist is not available. Can you share it again?

Avatar

Important remark for everyone who's missing the webrat_steps.rb or the web_steps.rb -they've been removed to avoid that people continue building up (poor) tests based on these "training wheels" ... see http://aslakhellesoy.com/post/11055981222/the-training-wheels-came-off

Avatar

@Daniel: How about using ElasticSearch with Heroku?

For something like Sunspot and Solr, you can use the WebSolr add-on, but is there any hosted ElasticSearch solutions out there, that works nicely with Heroku?

Avatar

So, can ElasticSearch be hosted on Heroku? Or do you need to host it on say AWS and then live with latency issues? (thinking about a <1k set of fairly small records...)

Avatar

@Thomas: I've used Sphinx, Solr and ElasticSearch in production and my favorite is ElasticSearch for a few reasons:

  1. Sphinx and Solr both index documents periodically (with a large delay or manual re-index by default) so it's more difficult to index documents near real time. ElasticSearch has a default delay of one second.
  2. ElasticSearch has built-in cluster support for High Availability solutions. This is possible in Sphinx/Solr as well but again more difficult to set up.
  3. ElasticSearch and Solr both have built in "More Like This" queries, which is the main reason I had to stop using Sphinx. Sphinx doesn't have a built in solution for providing "similar" documents.
  4. ElasticSearch is the easiest to set up and get running for development AND production. Sphinx comes close because you only have to edit one configuration file. Solr is the hardest because you need to optimize it for production (and not use the built in Solr package provided with Sunspot, for example). There are lots of configuration files with Solr and usually you would want to use Tomcat to serve the search engine in production, which requires a lot of configuration by itself. It's also extremely simple to set up multiple indexes (or version your indexes) in ElasticSearch.
  5. The ElasticSearch API is JSON-based, so you can integrate the search engine easily with any application. You don't NEED a wrapper library to get up and running fast.

After working with different search engines for a while now, most of them require lots of time tweaking and configuring to fit your needs. The biggest advantage for ElasticSearch is the built-in functionality that usually requires lots of configuration. Less configuring means fewer opportunities to break and more time to spend concentrating on more important things like building your website! Also check out ElasticSearch's percolate queries...another cool feature that you may find useful.

Avatar

@rbates:

Any tips for testing with these gems?

Avatar

Second this request- I like the look and feel of MetaWhere for rails 3, but 3.1 I get conflicts.

Avatar

The "mercury:saved" trigger doesn't seem to exist anymore.

Avatar

Do we need to set updating_password back to false to avoid future updates from invoking the validation? If not, why not?

Avatar

@rbates:
I loved it, this is amazing in quality and timing. the last few pro screencasts have proven themselves to be very useful in my current work.

A question, could you give an example as how to use fuzzy search? and how to apply "phonetic token filter"?

Although I'm googling around, but I would appreciate any hint, since this what's stoping me now from jumping into elasticsearch/tire to replace sphinx/thining_sphinx.

Again, many thanks!

Avatar

Thanks Ryan, it is possible to release the second part next week,to have the entire series?

Avatar

@tfl:

You can commit different documents to the same index. ES will store the type in a special key named _type.

@rbates:

Awesome screencast and with great timing too. My company is switching from Solr to ES just as I type. =)

Avatar

Thomas:

ElasticSearch is (near) real time and has built-in sharding and clustering support.

Ryan:

Thanks a lot for those screencasts. =D

Avatar

What are the advantages of using this over Sunspot and Solr?

Avatar

I just refactored my helper as the previous code was a 'quick and dirty' test of my approach.

ruby
module ApplicationHelper
  def markdown(text, *renderer)      
    case renderer[0]
    when :authored
      rndr = HTMLwithAlbino.new(:hard_wrap => true, :gh_blockcode => true, 
          :filter_html => false, :safe_links_only => true)
    when :featured
      rndr = HTMLwithAlbino.new(:hard_wrap => true, :gh_blockcode => true, 
          :filter_html => true, :safe_links_only => true)
    else
      rndr = HTMLwithAlbino.new(:hard_wrap => true, :gh_blockcode => true, 
          :filter_html => true, :no_images => true, :no_styles => true,
          :safe_links_only => true)
    end
    redcarpet = Redcarpet::Markdown.new(rndr, :space_after_headers => true,
      :fenced_code_blocks => true, :autolink => true, :no_intra_emphasis => true,
      :strikethrough => true, :superscripts => true)
    redcarpet.render(text).html_safe
  end
end

If no valid renderer is specified (as the first method argument) it will assume unsafe content and do the utmost to strip and filter HTML etc.

Avatar

Do you recommend anything like this that could be used for larger forms?
Something that doesn't send a request every time, but rather when you save the page?

Avatar

That's just CSS. It's a background-image that floats in from the left using CSS3 Transitions!

Avatar

thanks again for a great railscast.

One thing I am still missing and that is how to full text search over multiple models. I know that there is the gem ultrasphinx but maybe you know other ways to do this

Avatar

This doesnt work anymore at least on twitter.

http://localhost:3000/auth/failure?message=invalid_response

and no solutions...

Avatar

Here's my solution for upgrading to Redcarpet 2

ruby
module ApplicationHelper
  def markdown(text)
    rndr = HTMLwithAlbino.new(:hard_wrap => true, :gh_blockcode => true, 
        :filter_html => false, :safe_links_only => true)
    
    redcarpet = Redcarpet::Markdown.new(rndr, :space_after_headers => true,
      :fenced_code_blocks => true, :autolink => true, :no_intra_emphasis => true,
      :strikethrough => true, :superscripts => true)
    
    redcarpet.render(text).html_safe
  end

  def markdown_unsafe(text)
    rndr = HTMLwithAlbino.new(:hard_wrap => true, :gh_blockcode => true, 
        :filter_html => true, :no_images => true, :no_styles => true,
        :safe_links_only => true)
    
    redcarpet = Redcarpet::Markdown.new(rndr, :space_after_headers => true,
      :fenced_code_blocks => true, :autolink => true, :no_intra_emphasis => true,
      :strikethrough => true, :superscripts => true)
    
    redcarpet.render(text).html_safe
  end
  
end

# create a custom renderer that allows highlighting of code blocks
class HTMLwithAlbino < Redcarpet::Render::HTML      
  def block_code(code, language)
    Albino.colorize(code, language)
  end
end

I'm calling markdown_unsafe for publicly created comments, hence, it filters out as much as possible; still doing Albino.colorize() instead of Albino.safe_colorize() as I haven't upgraded it yet.

Avatar

I'm exploring this plugin for our company website so that the sales team can easily update content. So far I'm loving it, but the image uploading is a little bit mysterious to me. Maybe someone can explain the steps I'm missing to use the images feature. I tried dragging and dropping in an image and I'm receiving this error: "Unable to process response: TypeError: Cannot read property 'url' of undefined." I noticed in the server logs that the image was processed successfully with paperclip but it saves the image to public/system/images. Is there a way to configure where the images get saved? How would I go about customizing the image model?

Avatar

Maybe I'm crazy but the above snippet only worked for me when I camel cased the field type tags. As in:

fieldType

rather than:

fieldtype
Avatar

How do you handle sections that require session info in your integration test? I have pages that call on current_user, should this be stubbed out somehow or is there a better way?

Avatar

Hey Ryan, I was trying this with rails 3.1.3

ruby
has_many :friendships
has_many :friends, :through => :friendships

and it says to set source =>

can you help how we can control join table on condition

SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
  User Load (0.2ms)  SELECT `users`.id FROM `users` INNER JOIN `friendships` ON `users`.`id` = `friendships`.`user_id` WHERE `friendships`.`friend_id` = 2

any guess how i can change this to

friendships` ON `users`.`id` = `friendships`.`friend_id` 

Thanks :-)

Avatar

Has anyone been able to get Tokeninput working with nested forms? I'm using a standard fields_for, but I can't get the form to pass the attributes of the nested model. Any thoughts would be appreciated.

Thanks!

Avatar

In case it helps anyone else, here is a jQuery version of endless_page.js The jQuery version fixes the compatibility problem with IE as well.

var currentPage = 1

function checkScroll() {
  if (nearBottomOfPage()) {
    currentPage ++;
    $.ajax(window.location.pathname + '.js?page=' + currentPage )
  } else {
    setTimeout("checkScroll()", 250);
  }
}

function nearBottomOfPage() {
  return scrollDistanceFromBottom() < 150;
}

function scrollDistanceFromBottom(argument) {
  return $(document).height() - ($(window).height() + $(window).scrollTop());
}
Avatar

This is why we are saving them into a separate variable

javascript
states = $('#person_state_id').html()
Avatar

I just ran into the same problem, using Redcarpet 2 on a Rails 3.1.3 app. Took me a little bit to figure out what was going on, but I updated the helper method to be:

ruby
def markdown(text)
  markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
          :autolink => true, :space_after_headers => true)
  return markdown.render(text)
end

So, in your view you would have:

ruby
<%= raw markdown(@policies.introduction) %>

I've instantiate a Redcarpet object and call its 'render" method both inside the 'markdown' helper method. That value will be return to the view, but since it will be escaped you'll need to pass it through the 'raw' method so that it comes out as actual html.

Avatar

I know this might sound like asking why not use Devise? But how would you implement email sending and verification when a user signs up? Am working on it, but having some troubles with testing.

Avatar

Thanks, using bootstrap on a project of my own and was looking for something like this.

Avatar

Hi thanks for the screencast. I would also add a few things to the discussion.

The sphinx field_weights option sounds really nice in theory but will always return poor results. Google can be more explicit than my self, but it basically always returns the records with the most occurrences.

I'm also pretty sure that with a delta index (set_property :delta => true) the index is being updated on the fly. A standard reindex is still required however as such records have certain quirks (eg. can't be sorted properly).

Avatar

I was just thinking....

What about elasticsearch and tire....

we use it, but not sure if the query is in right form and we would really appreciate your point of view :P

just my brainstorming, thanx for the great episode :P

Avatar

Does anyone know how is the red pen implemented?

Avatar

What version of Firefox? Mine is v9 and playing ok so far.

Avatar

How would you apply a :remember_me strategy?

ruby
Rails.application.config.middleware.use Warden::Manager do |manager|
  manager.default_strategies :password, :remember_me
  manager.failure_app = lambda { |env| SessionsController.action(:new).call(env) }
end

...

Warden::Strategies.add(:password) do
  def valid?
    params['email'] && params['password'] || :remember_me
  end

...

end

Any Ideas?

Avatar

Thanks again Ryan, not sure what the rails community would do without you. Great Episode

Avatar

To everyone needing to implement Solr in production mode, I have a couple of hints and warnings:

1) Use the official Apache guide to setting up Tomcat/Solr. It was by far the easiest for me to get working. It is found here: http://wiki.apache.org/solr/SolrTomcat

2) Remember to set the path: in your sunspot.yml. In the case of the example from the guide, this is: path: /solr-example

3) If you're going to search for special characters, such as æ ø å (Danish characters), you need to add UTF-8 encoding to your tomcat config file, as described here: http://e-mats.org/2008/04/solving-utf-8-problems-with-solr-and-tomcat/
and here: http://wiki.apache.org/solr/SolrTomcat#URI_Charset_Config

Avatar

I sometimes wonder if Ryan has a way to check the most searched google queries related to Rails (does Google provide such a feature?) or that he simply checks the search queries on his site. It's way too often that I've seen Ryan releasing tutorials that I or at least a few viewers where actually looking for in the past weeks.

Anyway, can't complain either way!

Avatar

I found the problem was rspec-rails (2.6.1) wouldn't include RSpec::Rails::RailsExampleGroup in a custom example group for you. So putting config.include RSpec::Rails::RailsExampleGroup, example_group: {file_path: %r{spec/presenters}} before include ActionView::TestCase::Behavior will work. I must be using a different version of rspec-rails.