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.
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.
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?
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)
Tried to follow this tutorial off a scaffold using rspec
ruby
# GET /articles/1# GET /articles/1.jsondefshow@article = Article.find(params[:id])
if request.path != article_path(@article)
redirect_to @article, status::moved_permanentlyend
respond_to do |format|
format.html # show.html.erb
format.json { render json:@article }
endend
Threw the following failure:
ruby
1) ArticlesControllerGET show assigns the requested article as @articleFailure/Error: get :show, {:id => article.to_param}, valid_session
AbstractController::DoubleRenderError:
Renderand/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.jsondefshow@article = Article.find(params[:id])
if request.path != article_path(@article)
redirect_to @article, status::moved_permanentlyelse
respond_to do |format|
format.html # show.html.erb
format.json { render json:@article }
endendend
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.
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?
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
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)
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 !
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.
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.
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.
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.
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?
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.
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...
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.
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?
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!
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..
Thank you Andrew, for this good information.
CodeRay has built-in support for RedCloth: http://stackoverflow.com/a/8850113/132257
The only real benefit over cancan is that rollout allows you to specify % of users that are allowed to use a feature.
Does FriendlyId work with nested resources?
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.
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.
I wrote a small module for that:
https://gist.github.com/1601872
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....
Now both the javascript will get rendered (empty string) and json will be rendered properly..
Is there a more elegant solution?
I'm using this too, but I wonder:
What's the best way to prevent clobbering your production database with the db:populate task?
How would you force the rendering of the create.js file as well on receiving a JSON message ( Among a JSON messge)?
Hey Adam, I just ran into this as well. Were you able to find the reason or a solution? Thanks.
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?
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)
Thanks for that Mike, works a treat :)
Me too!
Nevermind - just realized my issue had to do with something else. I'd delete my comment above but I don't have the ability
Tried to follow this tutorial off a scaffold using rspec
Threw the following failure:
Quick fix I'm using... but if there is a more eloquent way I'd love to know...
It's actually new in version 4.0, previously it was enabled by default.
Try restarting your Rails server.
Yup, you can pass friendly_id a method
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.
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?
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!
Is there any way i could use a combination of two fields to use the Slug?
for instance I have
and would like to add the first name of the user field -
:fname
to make it more unique.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
thanks for the information.. i just got knew little bit about rails.. thanks
[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.
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?
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 !
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.
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.
Wonderful cast! Thanks for the help
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.
You could use their free Redis To Go Addon.
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
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 URLsite.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?
Is there any way of making this work on Heroku without having to pay for their Redis instances?
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.
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?
No, only Active Record.
Ryan,
You forgot to add
gem install friendly_id in the web notes
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...
Somebody knows if this is also compatible with CouchRest Model? (Couchdb)
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.
Seems like this problem is specific to ruby1.8
try this in your irb session
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
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?
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!
: )
+1 I believe it is supposed to be based on the LINUX nice values
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..
I set up template, but it's only on first page, can you help me?