RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Thank you Andrew, for this good information.

Avatar

The only real benefit over cancan is that rollout allows you to specify % of users that are allowed to use a feature.

Avatar

Does FriendlyId work with nested resources?

Avatar

Ryan can correct me if I'm wrong, but CanCan is designed to give permissions to different user groups in your app, where Rollout is to help you slowly roll out features, so at some point 100% of the intended users will be using the feature.

Here is an example
Lets say that GitHub had a cool feature they want to release on the homepage.
Think how many millions of developers are on GitHub and would use the new feature on a homepage right away, and if that feature had a bug, you have millions of issues to fix (caused by this 1 bug).
However, if you rolled out the feature to only 1 persent of the millions of users, you'd limit the bug and any issues that are raised from the bug to only 1 person of millions!.
Also, they could then open the feature to 25% of the users and see how the new feature effects performance. Once they are sure that 25% of traffic has stable performance, they can bump the feature to 50% of the users, and so on.

Avatar

How would you handle having different configurations? Let's say a User logs into the system. Under their Account Settings, they can put in their pop/smtp settings and then use ActionMailer and MailMan with those settings vs having one configured for global use. One of the reasons why I ask is because the SendMail app within linux keeps getting flagged as spam and/or never reaches it's destination. However, this doesn't happen when using a SMTP server. I know that this is a bit off topic in general.

Avatar

I figured it out... I believe this is more of a hack but it could be usefull for others.
You can't render two views. So what i did was....

ruby
respond_to do |format|
format.js 
format.json  { 
     render_to_string "message/create.js.erb", :layout => false
     render :json => @chatmessage, :status => :created 
}
end

Now both the javascript will get rendered (empty string) and json will be rendered properly..
Is there a more elegant solution?

Avatar

I'm using this too, but I wonder:

What's the best way to prevent clobbering your production database with the db:populate task?

Avatar

How would you force the rendering of the create.js file as well on receiving a JSON message ( Among a JSON messge)?

Avatar

Hey Adam, I just ran into this as well. Were you able to find the reason or a solution? Thanks.

Avatar

I was watching this and a question came to mind. Is there no need ever to put authentication to the model level, that even people using console will need to be authenticated? From what I know, at production technical person with access to app directory can access all data through console with a little know knowledge of the models. Is that right? If there is a need, is it possible?

Avatar

It's not a problem, it's how paypal works. If you create a recurring profile, you'll get a recurring payment sometime during the start day of that profile.

If you request an initial amount too, you'll receive the initial payment sometime during the day that you create the profile AND a recurring profile payment during the day that the profile actually starts (if you create it with the start date set as today, the customer will be billed twice during today)

The request_payment called before creating a recurring payment charges the customer instantly, and has nothing to do with the recurring profile itself (it's a totally separated payment)

Having these in mind, a couple of ways of doing this would sound like this:

1) Create a request payment, and if it passes, create a recurring profile, starting today+30.days (not sure it's very cool, n'or consistent)

2) Create a recurring profile starting today, and process the billing in your application by using an IPN listener when paypal sends it (maybe give the user a period of I dunno, 24-48 hours for the "Complete" IPN answer to come from paypal, in which he could use your app)

Avatar

Thanks for that Mike, works a treat :)

Avatar

Nevermind - just realized my issue had to do with something else. I'd delete my comment above but I don't have the ability

Avatar

Tried to follow this tutorial off a scaffold using rspec

ruby
# GET /articles/1
# GET /articles/1.json
def show
  @article = Article.find(params[:id])
  if request.path != article_path(@article)
    redirect_to @article, status: :moved_permanently
  end

  respond_to do |format|
    format.html # show.html.erb
    format.json { render json: @article }
  end
end

Threw the following failure:

ruby
1) ArticlesController GET show assigns the requested article as @article
   Failure/Error: get :show, {:id => article.to_param}, valid_session
   AbstractController::DoubleRenderError:
     Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
   # ./app/controllers/articles_controller.rb:21:in `show'
   # ./spec/controllers/articles_controller_spec.rb:55:in `block (3 levels) in <top (required)>'

Quick fix I'm using... but if there is a more eloquent way I'd love to know...

ruby
# GET /articles/1
# GET /articles/1.json
def show
  @article = Article.find(params[:id])
  if request.path != article_path(@article)
    redirect_to @article, status: :moved_permanently
  else
    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @article }
    end
  end
end
Avatar

It's actually new in version 4.0, previously it was enabled by default.

Avatar

Try restarting your Rails server.

Avatar

Yup, you can pass friendly_id a method

ruby
  friendly_id :full_name, :use => :slugged
  def full_name
    "#{fname} #{lname}"
  end
Avatar

SOLUTION:

If you're using port forwarding, you can reference your "host" machine by it's regular network address (for example, 192.168.1.111). Incidentally, this is the requesting IP that is used when trying to connect to mySQL, so be sure to allow it in your "host" mySQL configuration.

If you're using Host-Only networking, your "host" is at x.x.x.1. for example, if you follow the default and set vagrant to use 33.33.33.10, then your "host" machine is at 33.33.33.1. You'll need to ensure that connections from the vagrant box IP are allowed for the user you're using.

Avatar

Instead of replicating my database in the VM, I'd prefer to connect to MySQL on my "host". I've been reading through the documentation, and while I see how to forward ports from "host" to "guest", I don't see how to do it in the other direction?

I read about the Host-only Networking, but I don't see where/how to set the host's IP?

Is this possible?

Avatar

Hi, Sorry Noobee! <8-( In-Line Editing not working! Followed in tutorial to the letter but for Rails 3.0.11 ruby 1.9.2.

On Clicking the text field appears but on pressing tab or enter the data is not edited.

Also I was wandering if this could apply to the index page i.e any other page within the controller for that matter!

Ryan Love Your Casts! You Rock!

Avatar

Is there any way i could use a combination of two fields to use the Slug?

for instance I have

ruby
friendly_id :lname, :use => :slugged

and would like to add the first name of the user field - :fname to make it more unique.

Avatar

Hello Ryan,
Murat has a good question above. I have the same question.
Can you please explain when and why would you choose this Gem over a CanCan driven soltuion?
Thanks.
Bharat

Avatar

thanks for the information.. i just got knew little bit about rails.. thanks

Avatar

[10:35] You could try using Ryan's source to implement it from scratch. It looks pretty strait forward and will not require the Redis backend.

Avatar

I've a Rails3 App with MySQL DB. I set vagrant and I arrange all gems for running my Rails3 app on vagrant but I faced with this error message when I want to run server,

/usr/lib/ruby/1.8/rubygems/dependency.rb:52:in `initialize': Valid types are [:development, :runtime], not nil (ArgumentError)

Do you know the solution of this?

Avatar

great screencast but i also had issues with plural names like statuses would read statu ... but thanks to @Adam for correction of classify to titleize . Cheers !

Avatar

While I like how the #delay method looks in the code, automatically serializing/deserializing objects, it does feel somewhat dirty. I recall it being fairly slow when working with large objects, and in most cases I think providing a hash of options along with the model's id would be faster. But, please do correct me if I'm wrong about that. I think that the less data you store in the database, faster the retrieval and serialization/deserialization will be when just using Struct classes, but it does mean you need to write a bit more code for everything you want to queue up. And, if you're going to do that then you might want to consider using Resque instead. I've used both a few times, and they both have their pros and cons. Note: I haven't tried out the new Delayed Job 3 that was recently released.

Avatar

thankyou, I've actually been using this gem since the early days of development but did not know about History module until today. It's a neat feature.

Avatar

Wonderful cast! Thanks for the help

Avatar

Yes. History is taken into account for validating unique slugs. This can also create a problem if users can change titles or names. They could theoretically reserve various usernames.

Avatar

You could use their free Redis To Go Addon.

Avatar

Sure it will. It is crucial for SEO to include search terms in the URL. So if you want to sell a product and you include the title in the URL instead of the id, it is much more likely that people will find this page when they google the product name.

Clemens
rails-trouble.com

Avatar

I have a question regarding the history module.

Let's say that I create a post titled "Hello" and get the url site.com/post/hello but I decide to update the title to "Hello World" and I now have an updated URL site.com/post/hello-world.

I use the history module to redirect from the old url to the updated one.

What happens if I try to create a new post with the old title? (Imagine that I have validates :title, :uniqueness=> true)

Will ActiveRecord take friendly_id's historic slugs into consideration when validating future user inputs?

Avatar

Is there any way of making this work on Heroku without having to pay for their Redis instances?

Avatar

Hello Ryan,

I want to ask a question about rollout gem. I use cancan gem in my app and it is very successful.
Is this gem like the cancan gem? I don`t really understand rollout gem.

Avatar

Is friendly_id SEO friendly?

I read link about rails-sexy-url for SEO.

http://www.bingocardcreator.com/articles/rails-seo-tips.htm#sexy-urls

Will friendly_id help us about SEO?

Avatar

Ryan,

You forgot to add

gem install friendly_id in the web notes

Avatar

I often use FriendlyId in combination with a UUID column. This way, the guessing of further resources is much harder (cp. /foo/1 → /foo/2 with random, 32-digit identifiers). Of course you will still need a authorization mechanism...

Avatar

Somebody knows if this is also compatible with CouchRest Model? (Couchdb)

Avatar

If you don't use slugs, then yes. This is precisely the "user name or email" example that you mention. Otherwise if you use slugs, you can use a value that's not necessarily unique like a title or name, and FriendlyId will automatically append numbers at the end of the slug when necessary to keep it unique.

Avatar

Seems like this problem is specific to ruby1.8

try this in your irb session

YourActiveRecordModel
YAML.load YourActiveRecordModel.to_yaml
=> YourActiveRecordModel

If you dont get your AR model back, there is a problem. I'm getting Class returned on ruby 1.8.7 and the correct result on ruby 1.9.3-p0

Just FYI

YourActiveRecordModel.to_yaml
=> "--- !ruby/class:YouActiveRecordModel {}\n"
This will WORK (this is what i see returned in ruby 1.9.3)

YourActiveRecordModel.to_yaml
=> "--- !ruby/class YourActiveRecordModel\n"
This will NOT WORK (this is what is see returned in ruby 1.8.7)

Avatar

Very interesting idea. I can see this being useful on user models with an email address or user name. Does friendly_id assume the name column is unique?

Avatar

Thanks Ryan, I'm about to do exactly this on a project and I've only been coding for in Ruby for three months. This cast is a massive help, thanks so much.

I'll be figuring out cancelled subs and failed transactions myself in the next few days, but still, + 1 for a part 2!

: )

Avatar

+1 I believe it is supposed to be based on the LINUX nice values

Avatar

How would you add search for category name with a text_field instead of id ?

products = Product.include(:category).order......
products = products.where("categories.name like ?", "%bla bla bla%")

Something like this? I know i can make category name an auto complete text search Railscasts #102 Auto-Complete Association (revised) like and just pass the category id.. Just looking for alternative ways..

Avatar

I set up template, but it's only on first page, can you help me?

ruby
def initialize(....)
super(:template => filename,:bottom_margin => 120)