Have you tried out this technique in Rails 2.0 preview? The task_attributes= method doesn't seem to be getting called on @project.update_attributes.
However, the Task#update method is still getting called, so I wonder if this was another change in Rails 2.0, eliminating the need for the after_update filter on Project.
Great as always, but I have suggestion to all who care about W3C standards. If you use "project[task_attributes][]" in fields_for, you will get autogenerated id for tags with brackets which is not allowed as id. It is possible to assign own id by :id => "project_task_attributes" or something similar. Just remember --- id must be uniq.
I believe that you should delete :id from parameters before model going to save or you will get error like this: "Can't mass-assign these protected attributes: id".
Here is the code of method in the Project model that will fix that issue:
def task_attributes=(task_attributes)
task_attributes.each do |attributes|
unless id = attributes.delete(:id)
tasks.build(attributes)
else
task = tasks.detect { |t| t.id == id.to_i }
task.attributes = attributes
end
end
end
Thank you for the excellent casts. Executing script/generate authenticated user session as shown in the cast doesn't create the users_controller.
Env:
Windows xp
Ruby 1.8.6
Rails 1.2.3
How do you end up displaying the task info in the index.rhtml form? I have no idea how you do this? Your projects controller index method finds all projects, but in your tutorial, you are able to display the tasks with the project. What is the rhtml code that can display a task for a project? Anyone know how to help?
@Jose, hmm, it should work as long as that route is near the top of your routes.rb file. But, I haven't tested this very much, I usually use named routes. Here's an example of that:
@scott & TheCompWiz, there's some gotchas involved in getting the editing part to work. I'll explain everything in the next episode coming to you on Monday. :)
I wish I could get a sneak peek into the next episode... I've tried to implement the editing functionality... and got only so far before hitting a brick wall. HOW DO YOU MAKE EVERYTHING LOOK SO EASY!?!!?! The moment I watch a rails casts... I slap my forehead & say... why didn't I think about that?
Great stuff. I wrote a shell script that automates the initial svn import and sets the ignores for new projects. Check it out and please comment. http://randomutterings.com/articles/2007/09/19/subversion-script-for-rails-developers
You just use rails-svn to create your new apps and pass it the repo url and username after the new project name.
LOVE the casts...so helpful. I got this one working great but am having trouble getting the update to work since the model assumes the tasks are being "created". Any advice?
@Emmanuel, thanks for letting me know. I'll try to fix the ipod feed soon.
Regarding the root URL, I just have a home controller with this route:
map.home '', :controller => 'home'
I think what you're seeing is how Rails behaves. I'm guessing rubyonrails.org either isn't running on Rails or has the root index.html page cached and their web server is interpreting that.
@Yuval, I'm not sure I'll have time to get into the details of validation in the next episode, but I'll include it in the code sample online or something.
@Sintaxi, the next episode will show you how to handle editing the project with the tasks.
ok I fugured out how to do this. first I put the form in _form.rhtml and I am using it for both new and edit. then I updated the virtual attribute to chect to se if it is getting an array(as in new tasks) or a hash(updating the tasks).
def task_attributes=(task_attributes)
if task_attributes.class == Array
task_attributes.each do |attributes|
tasks.build(attributes)
end
else
task_attributes.each do |id, attributes|
task = Task.find(id)
task.update_attributes(attributes)
end
end
end
def markaby(&block)
Markaby::Rails::Builder.new({}, self, &block)
end
If you use Markaby::Builder you will get problems like "method not found _erbout" of "method not found length". if you use other rails helpers like form_tag, form_for, etc.
I took the alternative download and it worked fine. but if I take the ipod RSS/Itunes subscribe, I can see all the episode as a podcast but they are audio only. So I have to download manually all the movie rather than through itune (which is fine with me)
Also, I have a question for you, How do you deal with the root controller not showing the same page for 2 different urls
If I look at rubyonrails.org I can see the following urls rendering the same page which can be annoying (especially for search engine as they see it as a different url)
Great Railscast. However, I'm left curious to see how you will perform validation. In a current system I'm working on, I have a form for a user with an embedded address model. I post via ajax, validate the user fields then the address fields, and use RJS to highlight the specific form fields where an error occurred. Your technique promises to make that whole process much simpler. Can I request that you follow up in railscast 75? :)
Great screencasts, these are incredibly useful. How about a screencast that looks at adding roles/authorization, so admin can edit anything but users can only edit there stuff?
@Michael, this episode was just for the creation form, not for editing the project. I'll be addressing editing in the next screencast which will provide a solution to this problem.
I can't seem to get this to work whenever you go back and reload the page and try to add more and submit. When you go back and reload the tasks will load up correctly and will have input names of "project[task_attributes][5][name]". When when you submit this you get an error: "undefined method `stringify_keys!' for "5":String. What's worse, if you reload the page and then try and add more tasks, you get this error: "Conflicting types for parameter containers. Expected an instance of Array, but found an instance of Hash. This can be caused by passing Array and Hash based paramters qs[]=value&qs[key]=value." Any suggestions? Thanks.
@erv2, making them draggable is probably possible, but out of the scope of this tutorial. You may want to post on railsforum.com about it.
@Skyblaze, if you don't build any tasks in the "new" action of the controller it should start with zero and still work fine. I honestly haven't tested it yet though.
Amazing. I used the ajax version from the rayn's railsforum tutorial, but it really is a code mess :) This non-ajax variation is intuitive and clean. I will wait for the validation and edit tips.
Two other things...if i want to start with 0 tasks field on the view and let the user adds field as it wants how can i do that?
Is it possibile to download somewhere the episodes code?
@Corrigan, what I have done in the past is store the sreg parameters in a session and redirect to the registration page. This allows the user to complete the registration process and choose a different name if they need to. I'll see if I can put some code up somewhere and I'll add a link here for it.
@Erik, I posted a tutorial on railsforum.com a while back which uses a different technique. It's not nearly as clean but it may handle the file field better:
http://railsforum.com/viewtopic.php?id=1065
@emmanuel, hmm, the iPod version of the videos should work on the iPhone. Are you certain that's the one you are trying? I think others have gotten it to work so I'm not sure what could be the problem.
@Arthur, I want to remove a tag higher up than the "p" tag so it is easier to add more fields to the tack if need be.
For a future topic I'd like to see how to move seamlessly between a show and edit action. This is a pretty common in the real world - users browses though content and then goes into edit mode. Can you recycle a bunch of form elements for the show view and lock them somehow?
I am wondering a bit about how people are handling duplicate nick names. What pattern are you using in your app in order to prevent this from happening. I considered just letting validation fail the attempt to save the user object, but the problem is that some open ID providers (Verisign) allow you to implement a remember me functionality, essentially skipping over the login process on a subsequent login, and sending the same sreg information. This makes it difficult for a user to try a different nick name.
Hey Ryan, any reason why those video do not work on the iphone? I keep on downloading them and they either appear as audio only when getting the ipod version or the video is not compatible when using the itunes version. Any idea?
I'm trying to do this but with a file_field instead of a text_field but I wont get it to work. When a user input error occurs and the new-template is rendered again my file fields are gone⦠I understand that I will probably have to use some other kind of techinque here, but which? Any clues?
Great screencast Ryan!
But, is there way to build in memory say... tag, for article with :through => :tagged_article association.
Like:
def new
@article = Article.new
@article.tags.build
end
@morb, it isn't necessary to define the action in the controller. Rails will automatically look for a template with the name of the action (do_magic.rjs) and just render that. Nothing significant is in the controller.
Have you tried out this technique in Rails 2.0 preview? The task_attributes= method doesn't seem to be getting called on @project.update_attributes.
However, the Task#update method is still getting called, so I wonder if this was another change in Rails 2.0, eliminating the need for the after_update filter on Project.
Hello,
Great as always, but I have suggestion to all who care about W3C standards. If you use "project[task_attributes][]" in fields_for, you will get autogenerated id for tags with brackets which is not allowed as id. It is possible to assign own id by :id => "project_task_attributes" or something similar. Just remember --- id must be uniq.
That was probably the most intense Railscast yet. Unbelievable how much ground you covered.
Excellent stuff as always
+1 vote for a future episode on associated validations.
:)
I believe that you should delete :id from parameters before model going to save or you will get error like this: "Can't mass-assign these protected attributes: id".
Here is the code of method in the Project model that will fix that issue:
def task_attributes=(task_attributes)
task_attributes.each do |attributes|
unless id = attributes.delete(:id)
tasks.build(attributes)
else
task = tasks.detect { |t| t.id == id.to_i }
task.attributes = attributes
end
end
end
Why is it that all of the checkbox info on the net is for updating items that already exist. How can i do this for a new entry.
Thank you for the excellent casts. Executing script/generate authenticated user session as shown in the cast doesn't create the users_controller.
Env:
Windows xp
Ruby 1.8.6
Rails 1.2.3
Well I answered my own question.
in index.rhtml
<% for task in @project.tasks %>
Task: <%= task.name %>
<% end %>
How do you end up displaying the task info in the index.rhtml form? I have no idea how you do this? Your projects controller index method finds all projects, but in your tutorial, you are able to display the tasks with the project. What is the rhtml code that can display a task for a project? Anyone know how to help?
Thanks Ryan, I look forward to reading it.
@Chris, I'm not certain what you're asking. Which plugin are you referring to? And by validation do you mean the checking of the password?
@Jose, hmm, it should work as long as that route is near the top of your routes.rb file. But, I haven't tested this very much, I usually use named routes. Here's an example of that:
http://pastie.caboo.se/106752
I explain named routes more in this episode:
http://railscasts.com/episodes/34
@scott & TheCompWiz, there's some gotchas involved in getting the editing part to work. I'll explain everything in the next episode coming to you on Monday. :)
I wish I could get a sneak peek into the next episode... I've tried to implement the editing functionality... and got only so far before hitting a brick wall. HOW DO YOU MAKE EVERYTHING LOOK SO EASY!?!!?! The moment I watch a rails casts... I slap my forehead & say... why didn't I think about that?
Great stuff. I wrote a shell script that automates the initial svn import and sets the ignores for new projects. Check it out and please comment. http://randomutterings.com/articles/2007/09/19/subversion-script-for-rails-developers
You just use rails-svn to create your new apps and pass it the repo url and username after the new project name.
Is it possible to include the validation in the plugin with a dynamic validate method?
Thanks Ryan for your answer, but I have a problem, if I do:
link_to 'article', :controller => "articles", :year => '2007', :month => '10')
I get:
http://localhost:3000/articles?year=2007&month=10
Not:
http://localhost:3000/articles/2007/
10
And my route file is:
map.connect 'articles/:year/:month', :controller => 'articles',
:year => nil, :month => nil
Is this correct?
LOVE the casts...so helpful. I got this one working great but am having trouble getting the update to work since the model assumes the tasks are being "created". Any advice?
@Emmanuel, thanks for letting me know. I'll try to fix the ipod feed soon.
Regarding the root URL, I just have a home controller with this route:
map.home '', :controller => 'home'
I think what you're seeing is how Rails behaves. I'm guessing rubyonrails.org either isn't running on Rails or has the root index.html page cached and their web server is interpreting that.
@Jose, you can do a link by passing the parameters like this:
link_to "Article", :controller => 'articles', :year => 2007, :month => 10, :day => 12
@Yuval, I'm not sure I'll have time to get into the details of validation in the next episode, but I'll include it in the code sample online or something.
@Sintaxi, the next episode will show you how to handle editing the project with the tasks.
Hy Ryan,
please how can we do a link to an article like /articles/2007/10/12/id_of_article
Thanks a lot.
ok I fugured out how to do this. first I put the form in _form.rhtml and I am using it for both new and edit. then I updated the virtual attribute to chect to se if it is getting an array(as in new tasks) or a hash(updating the tasks).
def task_attributes=(task_attributes)
if task_attributes.class == Array
task_attributes.each do |attributes|
tasks.build(attributes)
end
else
task_attributes.each do |id, attributes|
task = Task.find(id)
task.update_attributes(attributes)
end
end
end
Its better to use a "markaby" helper like this.
def markaby(&block)
Markaby::Rails::Builder.new({}, self, &block)
end
If you use Markaby::Builder you will get problems like "method not found _erbout" of "method not found length". if you use other rails helpers like form_tag, form_for, etc.
how about updating the project/tasks? when creating, task_attributes is an array but when you update it is a hash.
@Ryan
I took the alternative download and it worked fine. but if I take the ipod RSS/Itunes subscribe, I can see all the episode as a podcast but they are audio only. So I have to download manually all the movie rather than through itune (which is fine with me)
Also, I have a question for you, How do you deal with the root controller not showing the same page for 2 different urls
If I look at rubyonrails.org I can see the following urls rendering the same page which can be annoying (especially for search engine as they see it as a different url)
rubyonrails.org/
rubyonrails.org/index
rubyonrails.org/index.html
but on railscast ( I am not sure how you named your default controller, I cannot see a page for railscasts.com/index.html
Great Railscast. However, I'm left curious to see how you will perform validation. In a current system I'm working on, I have a form for a user with an embedded address model. I post via ajax, validate the user fields then the address fields, and use RJS to highlight the specific form fields where an error occurred. Your technique promises to make that whole process much simpler. Can I request that you follow up in railscast 75? :)
@David, I talk a little bit about this in episodes 20 and 21, but I haven't gone into details on role based authorization. Thanks for the suggestion.
http://railscasts.com/tags/9
Great! Thanks for the quick reply ryan, keep up the good work!
Ryan,
Great screencasts, these are incredibly useful. How about a screencast that looks at adding roles/authorization, so admin can edit anything but users can only edit there stuff?
David
@Michael, this episode was just for the creation form, not for editing the project. I'll be addressing editing in the next screencast which will provide a solution to this problem.
I have always wanted to know this. Extremely helpful!Thanks also for your contributions over at railsforum.com!
I can't seem to get this to work whenever you go back and reload the page and try to add more and submit. When you go back and reload the tasks will load up correctly and will have input names of "project[task_attributes][5][name]". When when you submit this you get an error: "undefined method `stringify_keys!' for "5":String. What's worse, if you reload the page and then try and add more tasks, you get this error: "Conflicting types for parameter containers. Expected an instance of Array, but found an instance of Hash. This can be caused by passing Array and Hash based paramters qs[]=value&qs[key]=value." Any suggestions? Thanks.
@erv2, making them draggable is probably possible, but out of the scope of this tutorial. You may want to post on railsforum.com about it.
@Skyblaze, if you don't build any tasks in the "new" action of the controller it should start with zero and still work fine. I honestly haven't tested it yet though.
I'll post the full code after the final episode.
Amazing. I used the ajax version from the rayn's railsforum tutorial, but it really is a code mess :) This non-ajax variation is intuitive and clean. I will wait for the validation and edit tips.
Two other things...if i want to start with 0 tasks field on the view and let the user adds field as it wants how can i do that?
Is it possibile to download somewhere the episodes code?
Very good episode, looking forward to the error handling. Also, how about adding draggable list to arrange the order of the tasks?
@ari, I recommend posting this on railsforum.com as I need to see the code and more details before knowing what's wrong.
@Corrigan, what I have done in the past is store the sreg parameters in a session and redirect to the registration page. This allows the user to complete the registration process and choose a different name if they need to. I'll see if I can put some code up somewhere and I'll add a link here for it.
@Erik, I posted a tutorial on railsforum.com a while back which uses a different technique. It's not nearly as clean but it may handle the file field better:
http://railsforum.com/viewtopic.php?id=1065
@emmanuel, hmm, the iPod version of the videos should work on the iPhone. Are you certain that's the one you are trying? I think others have gotten it to work so I'm not sure what could be the problem.
@Arthur, I want to remove a tag higher up than the "p" tag so it is easier to add more fields to the tack if need be.
@Ryan Bates,
Install will_paginate with svn:// not work to me too. After I install SVN command line this work
@ari: http://railscasts.com/about
To remove the text field you should also call
$(this.parentNode).remove() and it will remove the p node.
For a future topic I'd like to see how to move seamlessly between a show and edit action. This is a pretty common in the real world - users browses though content and then goes into edit mode. Can you recycle a bunch of form elements for the show view and lock them somehow?
I am wondering a bit about how people are handling duplicate nick names. What pattern are you using in your app in order to prevent this from happening. I considered just letting validation fail the attempt to save the user object, but the problem is that some open ID providers (Verisign) allow you to implement a remember me functionality, essentially skipping over the login process on a subsequent login, and sending the same sreg information. This makes it difficult for a user to try a different nick name.
Hey Ryan, any reason why those video do not work on the iphone? I keep on downloading them and they either appear as audio only when getting the ipod version or the video is not compatible when using the itunes version. Any idea?
Thanks
Actually that link jlehman posted gave me a clue.
I'm trying to do this but with a file_field instead of a text_field but I wont get it to work. When a user input error occurs and the new-template is rendered again my file fields are gone⦠I understand that I will probably have to use some other kind of techinque here, but which? Any clues?
@Alex, I don't think the has_many :through association gives you that "build" method. Instead you'll have to build the join model like this:
@article.tagged_articles.build(:tag => Tag.new)
Great screencast Ryan!
But, is there way to build in memory say... tag, for article with :through => :tagged_article association.
Like:
def new
@article = Article.new
@article.tags.build
end
Thanks
Great episode as always. I am officially big fan of Ryan's casts.
If by any chance, can you make an episode about creating/consuming RESTful web services?
Big thanks for your generous contribution to rails community.
@morb, it isn't necessary to define the action in the controller. Rails will automatically look for a template with the name of the action (do_magic.rjs) and just render that. Nothing significant is in the controller.