*Thank you* for exploring this, even if it is literally a couple of years too late for me -- I could have used this back in 2007 and 2008! But it helps show how to avoid and/or clean up some of the egregious code I perpetrated back then, in my ignorance...
I kind of get the whole 'mvc violation' thing, but I still like your solution. Like you said it could use some refactoring but it's really not that bad. The whole skinny controller thing is a bit ridiculous and people go a bid overboard IMHO.
I've often wondered how I would achieve this, but have never tried it because I too like the 'one form' approach. I tend to ask for as little information is required to complete the transaction, then ask for more when you need later, it appears to be less invasive to one's privacy.
I don't think the JS only solution is a good one. The wizard should be able to fall-back to Rails; when JS is not available. And doing validations in JS could mean crappy data being stored if JS was turned off.
You could simplify the model code by using my grouped_validations plugin to break up the validation into step groups http://github.com/adzap/grouped_validations
You can then just define
validation_group :shipping do
validates_presence_of :shipping_name
end
I've finally caught up on Railscasts! These are awesome. I just wanted to let you know that the recent videos haven't been showing up very well using VLC on Ubuntu. I don't know what you are doing differently but it started around ep. 212.
I agree with @Marc since there are a few MVC "violations" here. In particular there is a lot of controller-specific functionality imbedded in the model which would make it very difficult to re-use the model with a different controller/view e.g. taking an order via a webservice. But as a practical solution it works.
Keep it up, I look forward to my Monday coffee break.
Nice for a "first attempt", but it really needs refactoring or separation of concerns. I don't like how both the model and controller are essentially providing view functionality.
I think this could be quite easily plugin/gem-ified with a Module which alters the common use case of if/else on #save. That is, an alias_method_chain on #save which is altered to return false if there are outstanding steps (where steps are defined via methods made available through said module).
It's a good way of accomplishing that kind of situation. However, I'd rather suggest what you mentioned first: split the various fields into fieldsets and use Javascript; sounds much easier, the same visual process is achieved and the Rails code is kept clean.
In either way, you wanted to present a 100% Rails way of accomplishing it and you did. Nice!
Never mind, worked out how to do this with a named_scope that takes the current record as a parameter to a lambda expression. This is then passed into the conditions expression to exclude the specified record.
I can't get this to work, it always gives 401 unauthorized and never asks for a username/password. If I use curl and give it a username and password though it works, can anybody help me out?
A stylistic question: might it be preferable to create
views/questions/_form.html.erb
views/answers/_form.html.erb
in lieu of
views/surveys/_question_fields.html.erb
views/surveys/_answer_fields.html.erb
? As a developer, those would be the places I'd look if I wanted to change the layout or add fields to the questions and answers.
Ryan, I love your screencasts, and they have helped me enormously in getting to grips with Rails more quickly than I otherwise would.
However, I can't help feeling that Rails 3 is still (at least) months away from being a version that can be properly utilised by serious developers. I know your railscasts are meant to be at the forefront of what is best in the ROR community, but clearly (to me) the number of necessary workarounds indicated by your vids - and many others on the same subject (upgrading to Rails 3) - leave me with a no-brainer decision on whether to upgrade production systems to Rails 3 - NFW.
So ryan is there a way to do multiple scenarios like for example ....try green image or try blue image or try red image and see which one provides the best conversions....
Hi I've been working through the 'Creating a weblog in 15 minutes with Rails 2' from http://rubyonrails.org/screencasts.
I then worked through your screencast (changing names as required) that when really well except for the form resetting. I think it's because my form is <% remote_form_for [@contact, Comment.new] do |f| %> and not <% form_for Review.new(:product => @product) do |f| %>.
Wanting to use table_builder for a new Rails3 project, I took a cut at updating the block helpers and string security handlers to conform to the new idioms.
The old test suite was based on the old mechanics, so I was unable to make his tests work. It certainly worked for the application with which I was experimenting. I suppose I will need to revise the suite to work with the new mechanisms as well.
But a quick survey of the table and calendar functionalities appear to work. I will consider polishing this a bit and reworking it as a gem, if people are interested.
Fantastic, thanks. Have spent all day trying to work out how I could reconcile the fact that my apps have very large files and my shared hosting account has very small processor allocation. git seems to be a hungry beast and before total despair I found this railscast. hope this will resolve the issue!! thanks so much.
this is the most helpful thing i have come across for understanding capistrano. 8 mins instead of rereading the capistrano site and whatever else I could find 100 times.
When i try to run the migration i just get a MYSQL error. Can't create table. I'm guessing it has to do with foreign keys to a non exiting table (commentable) ?
Ryan, your consistency at producing these quality screencasts is both amazing and inspiring. I remember watching them when they first started and thinking they were excellent but also thinking you would probably stop after about ten episodes. I went away from web programming for a long time but now am back. In that time, holy cow, you have built an empire! An empire of goodness. Still trying to catch up.
Question about datepicker. After reviewing the screencast, I think the subtle problem is actually happening there too.
The date that comes out of the database is in the form YYYY-MM-DD and jQuery datepicker doesn't know how to interpret it and isn't able to mark the date. (In the screencast the current date and the selected date are the same so it is not obvious.) Once the date is selected it is formatted MM/DD/YYYY. Fortunately rails knows how to parse this so it goes back into the database correctly.
Wondering what the best way to make rails produce dates like MM/DD/YYYY or alternatively make jQuery understand YYYY-MM-DD so it marks the date correctly. Anyone have any thoughts on making ActiveRecord and jQuery agree on date formats?
My previous fix contained a bug. It makes sense, but it escaped me, of course you have to crop *before* you resize! Now the javascript ratio adapt is required as well, so ignore that in my previous comment.
Here's the updated fix for the cropper.rb: http://pastie.org/988870
Nice screencast! I wonder why you never use haml instead of erb. I switched a long time ago and don't regret it at all. It's so much nicer and cleaner to use haml instead of erb. In the latest version of the gem you can even do multiline commands which was a bit awkward to achieve before. Sorry if this is a bit off topic, it just popped into my mind... ;-)
@Dale I had the same problem. It seems like paperclip has changed the way it handles processor command line arguments. They used to use a String for that, but now they're using an Array. This is why you get an error on super.sub, because it's trying to remove the -crop attributes using regular expressions which don't work on an array.
Below is my modified cropper.rb. That seems to be working. It's quickly hacked together, there may be a cleaner way to do it so anyone feel free to suggest a different approach.
http://pastie.org/988870
On another note I encountered some weird behavior. I don't seem to have to do the ratio adjustment. In fact when I do the ratio adjustment in the javascript code to the crop_x and crop_y etc, the thumbnail becomes extremely small (not visible anymore in fact). When I leave out the ratio factor, everything works great and I don't have a problem with the crop not being centered. I'm puzzled.
Thirdly, I haven't really researched this, but wouldn't it be a good idea to restrict those crop_x, crop_y etc attributes to be integers only? I think they get passed through unsanitized to cropper.rb and could therefore be used to execute commands. After all crop_x, crop_y etc can be set to any value by a malicious user.
Ryan, you're the man! Great job on the Railscasts. Keep it up!
Yes, it was a bug. When you required rails/generators in config/application.rb, it was being required too early and then Rails::Generators could not copy part of the configuration set in your application.
This was fixed and the guide updated. However, as David Trasbo pointed above, the best solution is to use config.generators.fallbacks. You usually don't want to require "rails/generators" because it would force generators to be loaded in production (for instance).
This is working great for me! My only problem is that I'm using the :page_links => false. It's working correctly by taking out the numbered links and only displaying Prev and Next for the links.
But those two links are on separate lines. Prev is on one and Next is on the next line in the browser. I tried using :style => 'display: inline' so that they would be on the same line, but it's not working.
I'm sure I'm messing this up somewhere. Anyone else having the same issue?
Thanks Ryan, the tutorial worked great, but I have a question.
How can I have an app so multiple users can login but have their own account. For instance, if a new user sings up, a new (blank) instance of my app will be displayed to him.
Can devise help me do that?
I know it's a newbie question but I'm just starting with rails... thanks.
*Thank you* for exploring this, even if it is literally a couple of years too late for me -- I could have used this back in 2007 and 2008! But it helps show how to avoid and/or clean up some of the egregious code I perpetrated back then, in my ignorance...
Indeed a little refactorization would be great.
Thanks this is the kind of episodes that I learn a lot of how Rails works.
what about wizardly (http://github.com/jeffp/wizardly) and actsaswizard (http://github.com/adkron/actsaswizard) ?
@Chris That's a much cleaner way to do this. Thanks!
Nice epsiode.
I kind of get the whole 'mvc violation' thing, but I still like your solution. Like you said it could use some refactoring but it's really not that bad. The whole skinny controller thing is a bit ridiculous and people go a bid overboard IMHO.
I've often wondered how I would achieve this, but have never tried it because I too like the 'one form' approach. I tend to ask for as little information is required to complete the transaction, then ask for more when you need later, it appears to be less invasive to one's privacy.
I don't think the JS only solution is a good one. The wizard should be able to fall-back to Rails; when JS is not available. And doing validations in JS could mean crappy data being stored if JS was turned off.
You could simplify the model code by using my grouped_validations plugin to break up the validation into step groups http://github.com/adzap/grouped_validations
You can then just define
validation_group :shipping do
validates_presence_of :shipping_name
end
and in the controller
@order.group_valid?(session[:order_step].to_sym)
Yeah... I don't know...
Store form fields in session and keep view states in model is weird.
Anyway, it works.
i would love to see an episode about refactoring these actions, i always keep ending up with very long actions.. :/
Hey Ryan,
I've finally caught up on Railscasts! These are awesome. I just wanted to let you know that the recent videos haven't been showing up very well using VLC on Ubuntu. I don't know what you are doing differently but it started around ep. 212.
recently I had to do the exact same thing, only I tackled it slightly differently
instead of using :if on the validations I just check to see if a model is valid based on select attributes
the code is here if anyone is interested in the approach
http://gist.github.com/429048
and yes, most of that controller code should be pushed into the model
Nevermind: my mistake -- your ruby-Fu is > Mine :-)
Type-O in your final method: 'all?' Should be 'each'
@Michael @Dale @Ryan
I also encountered the Paperclip array returned in the transformation_command super method.
I simply joined the array returned from super, performed the substitution Ryan used in his screencast, then split it back into an array.
http://pastie.org/995357
I agree with @Marc since there are a few MVC "violations" here. In particular there is a lot of controller-specific functionality imbedded in the model which would make it very difficult to re-use the model with a different controller/view e.g. taking an order via a webservice. But as a practical solution it works.
Keep it up, I look forward to my Monday coffee break.
great episode Ryan! Another alternative to this would be to use the Acts As State Machine
@Artur: Sure you can, it is called AJAX :-)
Therefore in the "real world" I'd go for the JS-based solution, no need to complicate the server side.
thanks
Nice for a "first attempt", but it really needs refactoring or separation of concerns. I don't like how both the model and controller are essentially providing view functionality.
I think this could be quite easily plugin/gem-ified with a Module which alters the common use case of if/else on #save. That is, an alias_method_chain on #save which is altered to return false if there are outstanding steps (where steps are defined via methods made available through said module).
Great Episode. I'd suggest using with_options when having multiple validations on different steps. This would look like this http://pastie.org/994652
First time in 217 episodes that you are too late for me :)
Thanks for the awesome episode. Really a smart way for handeling this. Much cleaner than i did :)
Thanks!
It's a good way of accomplishing that kind of situation. However, I'd rather suggest what you mentioned first: split the various fields into fieldsets and use Javascript; sounds much easier, the same visual process is achieved and the Rails code is kept clean.
In either way, you wanted to present a 100% Rails way of accomplishing it and you did. Nice!
Hey Ryan, I know you did this tutorial a long time ago but I'm wondering what are the changes to do this with Rails 3.
(I hope you read this comment!)
Never mind, worked out how to do this with a named_scope that takes the current record as a parameter to a lambda expression. This is then passed into the conditions expression to exclude the specified record.
Thanks for a great screencast!
How do you prevent a user from befriending himself? For example, RyanB can friend RyanB in your video.
I can't get this to work, it always gives 401 unauthorized and never asks for a username/password. If I use curl and give it a username and password though it works, can anybody help me out?
Thanks
This inspired me to write a blog post on getting Rails 3, RSpec, and Cucumber all set up and working together:
http://blog.notahat.com/posts/43
Great episode! Arigato Ryan :)
Wonderfully helpful as always.
A stylistic question: might it be preferable to create
views/questions/_form.html.erb
views/answers/_form.html.erb
in lieu of
views/surveys/_question_fields.html.erb
views/surveys/_answer_fields.html.erb
? As a developer, those would be the places I'd look if I wanted to change the layout or add fields to the questions and answers.
- ff
Ryan, I love your screencasts, and they have helped me enormously in getting to grips with Rails more quickly than I otherwise would.
However, I can't help feeling that Rails 3 is still (at least) months away from being a version that can be properly utilised by serious developers. I know your railscasts are meant to be at the forefront of what is best in the ROR community, but clearly (to me) the number of necessary workarounds indicated by your vids - and many others on the same subject (upgrading to Rails 3) - leave me with a no-brainer decision on whether to upgrade production systems to Rails 3 - NFW.
Hello :) bye
So ryan is there a way to do multiple scenarios like for example ....try green image or try blue image or try red image and see which one provides the best conversions....
Hi I've been working through the 'Creating a weblog in 15 minutes with Rails 2' from http://rubyonrails.org/screencasts.
I then worked through your screencast (changing names as required) that when really well except for the form resetting. I think it's because my form is <% remote_form_for [@contact, Comment.new] do |f| %> and not <% form_for Review.new(:product => @product) do |f| %>.
any tips?
thx for this tutorial!
But I would appreciate it if you make a cast for including a oauth login with devise (e.g. a twitter login)
thx!
Thank you How do you automatically add new files? What is the point of adding a directory if the directory isn't monitored for new files?
Wanting to use table_builder for a new Rails3 project, I took a cut at updating the block helpers and string security handlers to conform to the new idioms.
The old test suite was based on the old mechanics, so I was unable to make his tests work. It certainly worked for the application with which I was experimenting. I suppose I will need to revise the suite to work with the new mechanisms as well.
But a quick survey of the table and calendar functionalities appear to work. I will consider polishing this a bit and reworking it as a gem, if people are interested.
http://github.com/wizardwerdna/table_builder
Jeweler supports releasing to both Gemcutter and Rubyforge. The default is Github
Also, Episode #32 shows how to make your model cooperate with the default format jQuery wants.
Fantastic, thanks. Have spent all day trying to work out how I could reconcile the fact that my apps have very large files and my shared hosting account has very small processor allocation. git seems to be a hungry beast and before total despair I found this railscast. hope this will resolve the issue!! thanks so much.
this is the most helpful thing i have come across for understanding capistrano. 8 mins instead of rereading the capistrano site and whatever else I could find 100 times.
When i try to run the migration i just get a MYSQL error. Can't create table. I'm guessing it has to do with foreign keys to a non exiting table (commentable) ?
One solution to #52 is to change jQuery datepicker's format:
$("#article_published_on").datepicker({dateFormat: 'yy-mm-dd'});
Ryan, your consistency at producing these quality screencasts is both amazing and inspiring. I remember watching them when they first started and thinking they were excellent but also thinking you would probably stop after about ten episodes. I went away from web programming for a long time but now am back. In that time, holy cow, you have built an empire! An empire of goodness. Still trying to catch up.
Question about datepicker. After reviewing the screencast, I think the subtle problem is actually happening there too.
The date that comes out of the database is in the form YYYY-MM-DD and jQuery datepicker doesn't know how to interpret it and isn't able to mark the date. (In the screencast the current date and the selected date are the same so it is not obvious.) Once the date is selected it is formatted MM/DD/YYYY. Fortunately rails knows how to parse this so it goes back into the database correctly.
Wondering what the best way to make rails produce dates like MM/DD/YYYY or alternatively make jQuery understand YYYY-MM-DD so it marks the date correctly. Anyone have any thoughts on making ActiveRecord and jQuery agree on date formats?
My previous fix contained a bug. It makes sense, but it escaped me, of course you have to crop *before* you resize! Now the javascript ratio adapt is required as well, so ignore that in my previous comment.
Here's the updated fix for the cropper.rb: http://pastie.org/988870
Nice screencast! I wonder why you never use haml instead of erb. I switched a long time ago and don't regret it at all. It's so much nicer and cleaner to use haml instead of erb. In the latest version of the gem you can even do multiline commands which was a bit awkward to achieve before. Sorry if this is a bit off topic, it just popped into my mind... ;-)
@Dale I had the same problem. It seems like paperclip has changed the way it handles processor command line arguments. They used to use a String for that, but now they're using an Array. This is why you get an error on super.sub, because it's trying to remove the -crop attributes using regular expressions which don't work on an array.
Below is my modified cropper.rb. That seems to be working. It's quickly hacked together, there may be a cleaner way to do it so anyone feel free to suggest a different approach.
http://pastie.org/988870
On another note I encountered some weird behavior. I don't seem to have to do the ratio adjustment. In fact when I do the ratio adjustment in the javascript code to the crop_x and crop_y etc, the thumbnail becomes extremely small (not visible anymore in fact). When I leave out the ratio factor, everything works great and I don't have a problem with the crop not being centered. I'm puzzled.
Thirdly, I haven't really researched this, but wouldn't it be a good idea to restrict those crop_x, crop_y etc attributes to be integers only? I think they get passed through unsanitized to cropper.rb and could therefore be used to execute commands. After all crop_x, crop_y etc can be set to any value by a malicious user.
Ryan, you're the man! Great job on the Railscasts. Keep it up!
Hey Ryan,
Yes, it was a bug. When you required rails/generators in config/application.rb, it was being required too early and then Rails::Generators could not copy part of the configuration set in your application.
This was fixed and the guide updated. However, as David Trasbo pointed above, the best solution is to use config.generators.fallbacks. You usually don't want to require "rails/generators" because it would force generators to be loaded in production (for instance).
Sorry for the issue! :)
hi
i have tried the same code ..when i am tried to add a new task its showing
RJS error:
TypeError: Element.insert is not a function
I have added the <%= javascript_include_tag :defaults %> in layout
files also
can you guys help on this ...
Although Rails does allow you to edit time attributes with text fields, it's not very flexible.
This is working great for me! My only problem is that I'm using the :page_links => false. It's working correctly by taking out the numbered links and only displaying Prev and Next for the links.
But those two links are on separate lines. Prev is on one and Next is on the next line in the browser. I tried using :style => 'display: inline' so that they would be on the same line, but it's not working.
I'm sure I'm messing this up somewhere. Anyone else having the same issue?
Thanks Ryan, the tutorial worked great, but I have a question.
How can I have an app so multiple users can login but have their own account. For instance, if a new user sings up, a new (blank) instance of my app will be displayed to him.
Can devise help me do that?
I know it's a newbie question but I'm just starting with rails... thanks.
Alfredo Ribeiro, I have tried the route lib/generators/erb/scaffold/templates/index.html.erb
for erb and it didn't work.