@Michael, good catch. I didn't even notice that. Strangely enough, if you use the "-x" option to make it an svn external (which is what I normally do), it is smart enough to call it markaby.
Anyway, I recommend renaming the folder to "markaby" so it is correct. Hopefully this will be fixed in a future version of Rails.
Solved my problem, as it seems method to_s from Date does not accept any parameters and for this reason it was giving me this strange problem. Now I wonder how to change date format. Something to be solved with a quick look at the library reference. Thanks again
Ryan, thanks for this great "casts" and all the effort spent in teaching us cool tricks from Rails.
I am having the same kind of problem as zzeroo. As I am still new to Rails and only develop on it in my part-times, I would wonder if the problem (at least in my case) is because I am using class Date instead of DateTime. Please, tell me what you think.
Teaching us that one line that goes in the "markaby" method is just what a lot of us need. It is very simple and well documented but don't underestimate how helpful a video like this can be. It boosts your confidence in the question of whether you're missing anything. There are a lot more libraries that could be introduced almost as simply. Great to have you on board, Ryan. Is anyone else publishing screencasts (besides Geoffrey)?
I personally believe, that... screencasts, such as... Railscasts, PeepCode and so on... will help the US, will help the South Africa, will help Iraq and Asian Countries with educations... for th future of our children!
This and the restful_authentication Railscasts were both very useful. Thanks!
Would like to see a follow-up showing open-id login of new user going to sign-up form instead (to allow additional required fields to be entered/validated: e.g., email, city, real/screen names, etc.).
Would also like to see a deeper exploration of getting information from the user’s OpenID source. I know that some OpenID servers provide access to additional info fields, but haven’t figured that part out yet.
Finally, I’d like to see a way to turn around and offer a user’s login on my server as an OpenID service for other websites the user wants to access.
Heh. I guess I’m asking a lot :-) These are just suggestions and I’ll look forward to your future Railscasts regardless of whether you cover these topics or not.
Just downloaded and expectations are same for it too. Videos tutorial always very affected than reading paper/e-paper books.
Now, the collection is getting bigger so I thought or imagine there should be a rating bar people start rating their best tutorials and new user could easily find the best ones.
Thanks Ryan. It seems to me really that since a user can have multiple Open ID's, really one ought to allow a user to register additional ones against their user account (has many relationship, not an attribute in the User model) so as to prevent multiple User records being added (if that's a concern, of course).
Beware that if you're not going to automatically create users on-the-fly like Ryan does, you'll need to make sure that when a user adds an identity URL to his record manually, it gets normalized.
Authentication won't work if the value in the DB isn't normalized (e.g. missing a trailing slash). I accomplished this with a before_validation callback: http://pastie.caboo.se/91417
Does this handle the use case where the user is already registered on your site, but then decides to log in using OpenID? It looks like in that case, you'd get an additional user added to your DB because the find_or_initialize_by_identity_url would not return anything.
Ryan, I think it would be great if you made a quick little episode demonstrating how to add a forgot password function to the restful_authentication system. This would not only demonstrate the function itself, but demonstrate adding custom actions to a restful application. Just a thought!
@Dave, a new user model is automatically created and saved if they don't already have an account. If they already have an account then it just fetches the record from the database instead of creating it.
This behavior is not required when using OpenID, it is just one way to do it. Alternatively you may want to redirect to the signup page with some fields prefilled.
The user ID is generated automatically through auto-incrementing like all other Rails models.
Currently it doesn't complain if there's already a user with that name. That's because I disabled validations with save(false) call. However, this is just a temporary solution, how you want to handle validations is up to you. One solution is to redirect to the signup page.
Maybe I missed something, but is a user record created in the database upon successful Open ID authentication? What is the user ID of the user that is created? Is it the nickname provided by the Open ID authenticator? What if the nickname conflicts with an existing user name already in your Users model?
Actually, from a readability standpoint, this width is nearly perfect. The with of the main column is about 60 characters--6 less than is considered optimal.
Great episode! For anyone using eager loading on large databases, to get a huge performance boost you should set the column to index on the database of the attribute you're including, e.g. setting the task_id column in the projects table to be an index column using the sql command
ALTER TABLE `projects` ADD INDEX ( `task_id` )
@ofer, good point. I could create a "comment_approval" RESTful controller and avoid the custom REST actions. However, I'm no REST purist. I try to weigh the practicality of the different approaches. I consider the approve/reject actions to be largely about the comment resource (just different forms of update) so I decided to keep them in that controller.
I also like to follow the "simplest thing that could possible work" principle. Adding custom actions feels simpler. However, it's also a bit of a smell and could require some refactoring. The stench isn't quite strong enough IMO though.
Slightly off topic. Curious about the use of custom RESTful actions:
From reading the on-line literature - Purist seem to say you can always adhere to the default actions by adding new controllers.
In your case why aren't you following the pure RESTful pattern and if you were would you build an approval controller where "create" is approving and "destroy" is marking as spam ?
I'm interested in the way to do the same but with validations (RJS and "normal" version). In "normal" version, how to cleanly re-call/re-render the 'show' action of 'ProductsController' with the non-created-and-with-validation-errors Review, as we are in two different controllers? A link to help me? Thanks again!
now that rails edge has query caching, eager loading may not always be the optimal solution, esp. with :select not working, one has to pull every column of all the tables :include'd.
see technoweenies "trick":
http://activereload.net/2007/5/23/spend-less-time-in-the-database-and-more-time-outdoors
http://pastie.caboo.se/63741
me thinks it would be really cool to have a follow-up on this episode. :)
to weskycn:
Don't say anything not related to the topic. obeying the rule is the most polite than words,okey?
actually,I am a chinese too.
-------
blocks in view is powerful,especially with "capture"'s help.
I finished a "table_for" helper with the mechinism,the usage like this:
<% table_for :users do |t|
t.column :full_name {|user| h user.first_name + " " + user.last_name}
t.columns :age,:birthday
t.columns :$edit,:$show
%>
<% t.erb_column('Destroy') do |user| %>
<% if user.name != 'xxx' %>
<%= link_to 'Destroy',user_path(user),:method=>:delete %>
<% end %>
<% end
end
%>
some features like "pagination","odd-even style","column sortable with correct sort-type" supported,and we can imagine more features like "export to excel","Globalization" to be added to "table_for" helper. so only open some options like :sortable=>false,we keep the code clean,consistent and maintainable. (like j2ee's displaytag?)
for it's used in my company,I am sorry not able to share the code to public.
@hhifnawi, this won't generate the full rails skeleton, just a couple files. You should use the "rails" command to generate a full new Rails app. If you still have problems I recommend posting on railsforum.com.
NEED help:
My group are working on rails IDE and we're in the wizard part now and we're trying to generate the Rails skeleton and we looked in the rubygems and found in
gems/1.8/gems/rails-1.2.2/lib/rails_generator/generators/applications/app/app_generator.rb
what does it do, does it generates rails skeleton? are there any other scripts we need to execute as well?
plz email me at hisham86@aucegypt.edu
Rick handled the activation part really well, you'll just have to tweak the files a bit. I did a quick post to show the ideas on how to extend it with activation: http://rubyurl.com/gFX
@viniosity, I haven't checked how restful_authentication handles the account activation, so I'm not sure on the details. You would likely have an "if" condition in the controller checking whether or not the account is activated and display the appropriate error message.
@Ryan Long, eager loading should work with has_many :through as well without any differences. It just does a mutli-table join.
@Michael, good catch. I didn't even notice that. Strangely enough, if you use the "-x" option to make it an svn external (which is what I normally do), it is smart enough to call it markaby.
Anyway, I recommend renaming the folder to "markaby" so it is correct. Hopefully this will be fixed in a future version of Rails.
Solved my problem, as it seems method to_s from Date does not accept any parameters and for this reason it was giving me this strange problem. Now I wonder how to change date format. Something to be solved with a quick look at the library reference. Thanks again
Ryan, thanks for this great "casts" and all the effort spent in teaching us cool tricks from Rails.
I am having the same kind of problem as zzeroo. As I am still new to Rails and only develop on it in my part-times, I would wonder if the problem (at least in my case) is because I am using class Date instead of DateTime. Please, tell me what you think.
if i install the plugin, it is install in vendor/plugins/trunk
Is this a bug from the plugin?
@bug
I believe the restful_auth plugin has been updated since this railscast.
As such, the users controller no longer exists.
Routes that work for me, YMMV.
map.resources :users
map.resource :session
map.signup '/signup', :controller => 'session', :action => 'signup'
map.login '/login', :controller => 'session', :action => 'login'
map.logout '/logout', :controller => 'session', :action => 'logout'
Hope that helps others, threw me for a while as I've got a few projects using this plugin, all as per the railscast.
Teaching us that one line that goes in the "markaby" method is just what a lot of us need. It is very simple and well documented but don't underestimate how helpful a video like this can be. It boosts your confidence in the question of whether you're missing anything. There are a lot more libraries that could be introduced almost as simply. Great to have you on board, Ryan. Is anyone else publishing screencasts (besides Geoffrey)?
ooo.. I knew Markaby would be cool to use I just never figured out a good way. This looks awesome, as usual ;)
I was about to mention HAML as well you beat me to it :D
Haml also has really nice helper support.
Here's what it would look like:
http://pastie.caboo.se/93426
Ok, seriously, cool screencast!
I personally believe, that... screencasts, such as... Railscasts, PeepCode and so on... will help the US, will help the South Africa, will help Iraq and Asian Countries with educations... for th future of our children!
Thanks for screencast.
This and the restful_authentication Railscasts were both very useful. Thanks!
Would like to see a follow-up showing open-id login of new user going to sign-up form instead (to allow additional required fields to be entered/validated: e.g., email, city, real/screen names, etc.).
Would also like to see a deeper exploration of getting information from the user’s OpenID source. I know that some OpenID servers provide access to additional info fields, but haven’t figured that part out yet.
Finally, I’d like to see a way to turn around and offer a user’s login on my server as an OpenID service for other websites the user wants to access.
Heh. I guess I’m asking a lot :-) These are just suggestions and I’ll look forward to your future Railscasts regardless of whether you cover these topics or not.
Thanks again!
You said that eager loading works. What's the correct protocol for eager loading with a has_many :through relationship?
Thanks for those wonderful videos you are sharing with us :)
I would like to know how "dynamic layouts", I would like to add the layouts in my database and then use them as layouts, how can I accomplice that?
I tried to do it as you showed us in the video as follow:
def user_layout
if current_user.admin?
@layout.find_by_name("Normal").htmlCode
else @layout.find_by_name("Default").htmlCode
end
But this isn't working as I excepted, I hope you would have the time to give some example how to develop that :) and thanks in advance for your help.
Just downloaded and expectations are same for it too. Videos tutorial always very affected than reading paper/e-paper books.
Now, the collection is getting bigger so I thought or imagine there should be a rating bar people start rating their best tutorials and new user could easily find the best ones.
Best of Luck
How about automagically calling flash.discard in every format.js block?
MKA: Thank you! Got the same mysterious problem here too.
@Dave, I kept one OpenID per user for simplicity, but you can certainly put it in a separate model and set up a one-to-many association with user.
Thanks Ryan. It seems to me really that since a user can have multiple Open ID's, really one ought to allow a user to register additional ones against their user account (has many relationship, not an attribute in the User model) so as to prevent multiple User records being added (if that's a concern, of course).
Hi, Ryan.
One episode that I want see is about navigation (include nested navigations/level navigation) like the TabNav-plugin.
@Todd, Good point. If they try to log in through openid when they have an existing account it will create another user.
To get around this problem, add some instructions telling them to log in normally and edit their account profile. Here they can set their openid url.
a quick pointer:
in your routes, make sure you put the map.open_id_complete *before* the map.resource :session which is already there.
the resulting error shows up as an un-intuitive #show call on the SessionController
Thanks Ryan. Just added OpenID to my new app.
Beware that if you're not going to automatically create users on-the-fly like Ryan does, you'll need to make sure that when a user adds an identity URL to his record manually, it gets normalized.
Authentication won't work if the value in the DB isn't normalized (e.g. missing a trailing slash). I accomplished this with a before_validation callback: http://pastie.caboo.se/91417
Nice job, as usual, Ryan.
Does this handle the use case where the user is already registered on your site, but then decides to log in using OpenID? It looks like in that case, you'd get an additional user added to your DB because the find_or_initialize_by_identity_url would not return anything.
Ryan, I think it would be great if you made a quick little episode demonstrating how to add a forgot password function to the restful_authentication system. This would not only demonstrate the function itself, but demonstrate adding custom actions to a restful application. Just a thought!
@Dave, a new user model is automatically created and saved if they don't already have an account. If they already have an account then it just fetches the record from the database instead of creating it.
This behavior is not required when using OpenID, it is just one way to do it. Alternatively you may want to redirect to the signup page with some fields prefilled.
The user ID is generated automatically through auto-incrementing like all other Rails models.
Currently it doesn't complain if there's already a user with that name. That's because I disabled validations with save(false) call. However, this is just a temporary solution, how you want to handle validations is up to you. One solution is to redirect to the signup page.
Maybe I missed something, but is a user record created in the database upon successful Open ID authentication? What is the user ID of the user that is created? Is it the nickname provided by the Open ID authenticator? What if the nickname conflicts with an existing user name already in your Users model?
Actually, from a readability standpoint, this width is nearly perfect. The with of the main column is about 60 characters--6 less than is considered optimal.
Read: http://webtypography.net/Rhythm_and_Proportion/Horizontal_Motion/2.1.2/
Could always turn off stylesheets and just read the plain text :) But increasing the width wouldn't be a bad idea.
Great job on the screencast, love 'em! Always informative and great topics!
Great episode! For anyone using eager loading on large databases, to get a huge performance boost you should set the column to index on the database of the attribute you're including, e.g. setting the task_id column in the projects table to be an index column using the sql command
ALTER TABLE `projects` ADD INDEX ( `task_id` )
yeah, I agree with A about the website width, anyways if you use google analytics you can know that for sure.
@ofer, good point. I could create a "comment_approval" RESTful controller and avoid the custom REST actions. However, I'm no REST purist. I try to weigh the practicality of the different approaches. I consider the approve/reject actions to be largely about the comment resource (just different forms of update) so I decided to keep them in that controller.
I also like to follow the "simplest thing that could possible work" principle. Adding custom actions feels simpler. However, it's also a bit of a smell and could require some refactoring. The stench isn't quite strong enough IMO though.
Slightly off topic. Curious about the use of custom RESTful actions:
From reading the on-line literature - Purist seem to say you can always adhere to the default actions by adding new controllers.
In your case why aren't you following the pure RESTful pattern and if you were would you build an approval controller where "create" is approving and "destroy" is marking as spam ?
So nice! Thanks so much for all your casts.
I'm interested in the way to do the same but with validations (RJS and "normal" version). In "normal" version, how to cleanly re-call/re-render the 'show' action of 'ProductsController' with the non-created-and-with-validation-errors Review, as we are in two different controllers? A link to help me? Thanks again!
For anyone interested in Generators for other development areas outside of Rails, check out http://rubigen.rubyforge.org
nice screencast!, ey ryan, maybe a railscast of a simple rbac?, it will be nice ;).
anyway great railscasts ryan!
c'ya
in context with my previous post, here I have another nice link concerning the problems with eager loading:
http://darwinweb.net/article/Free_Form_Manual_Eager_Loading
now that rails edge has query caching, eager loading may not always be the optimal solution, esp. with :select not working, one has to pull every column of all the tables :include'd.
see technoweenies "trick":
http://activereload.net/2007/5/23/spend-less-time-in-the-database-and-more-time-outdoors
http://pastie.caboo.se/63741
me thinks it would be really cool to have a follow-up on this episode. :)
Nice idea! This method worked a little better for me (since '/' characters are cut from params[:path]):
def index
redirect_to "http://www.mydomain.com#{request.request_uri}"
end
I recommend posting this problem on railsforum.com so you can post the details on what you've done and the full stack trace.
I am getting an error
"NameError in SessionController#new "
when I go to
http://localhost:3000/login or
http://localhost:3000/logout
can anyone help me?
to weskycn:
Don't say anything not related to the topic. obeying the rule is the most polite than words,okey?
actually,I am a chinese too.
-------
blocks in view is powerful,especially with "capture"'s help.
I finished a "table_for" helper with the mechinism,the usage like this:
<% table_for :users do |t|
t.column :full_name {|user| h user.first_name + " " + user.last_name}
t.columns :age,:birthday
t.columns :$edit,:$show
%>
<% t.erb_column('Destroy') do |user| %>
<% if user.name != 'xxx' %>
<%= link_to 'Destroy',user_path(user),:method=>:delete %>
<% end %>
<% end
end
%>
some features like "pagination","odd-even style","column sortable with correct sort-type" supported,and we can imagine more features like "export to excel","Globalization" to be added to "table_for" helper. so only open some options like :sortable=>false,we keep the code clean,consistent and maintainable. (like j2ee's displaytag?)
for it's used in my company,I am sorry not able to share the code to public.
let's enjoy blocks in view :)
@hhifnawi, this won't generate the full rails skeleton, just a couple files. You should use the "rails" command to generate a full new Rails app. If you still have problems I recommend posting on railsforum.com.
Can you post a link for your code to review please
NEED help:
My group are working on rails IDE and we're in the wizard part now and we're trying to generate the Rails skeleton and we looked in the rubygems and found in
gems/1.8/gems/rails-1.2.2/lib/rails_generator/generators/applications/app/app_generator.rb
what does it do, does it generates rails skeleton? are there any other scripts we need to execute as well?
plz email me at hisham86@aucegypt.edu
Rick handled the activation part really well, you'll just have to tweak the files a bit. I did a quick post to show the ideas on how to extend it with activation: http://rubyurl.com/gFX
@viniosity, I haven't checked how restful_authentication handles the account activation, so I'm not sure on the details. You would likely have an "if" condition in the controller checking whether or not the account is activated and display the appropriate error message.
For those that want to keep the URL of "/login" when you submit, you can do the following in your routes.rb:
map.login '/login', :controller => 'session', :action => 'new', :conditions => { :method => :get }
just add the :conditions part to the current named route map.login
map.connect '/login', :controller => 'sessions', :action => 'create', :conditions => { :method => :post }
and in your form, put login_path. Now when you submit your form it will stay on '/login' instead of '/session'
if you run rake routes, you can see it.