@Chris password_hash can be used because the whole hash output from BCrypt also contains the salt and hash_secret is smart enough to detect that and just use the salt.
In fact, I would not even store the salt in the database any more. It's not needed and just increases the chance of bugs (duplicated storage of state is never a good idea).
@Pawe? what is your reasoning behind sticking to a non-standard and less secure solution? I can see that you might not want to change your existing old code, which is totally fine, but coming here to a tutorial about addition authentication from scratch to new applications, recommending an outdated and non-standard solution of the publicly accepted more secure standard solution seems not too intelligent.
@Tiaglo Scolari: this is the best solution I could find! Simple but effective. I have renamed ajax_loaded to state_pushed, but this is the only modification I could come up with :) (I support AJAX queries even if history state is not available)
This is really useful and went 99% of the way to getting me going with CollectiveIdea's Delayed::Job plugin with Rails3. However, one absolutely crucial but missing piece from this Railscast, at least with respect to Rails3 is that without adding a line to your config/application.rb file to load your lib/mailing_job.rb file when your application is initialize!d means that your class definition will not be available to the jobs:work rake task when it tries to dequeue a job from the database and run it. As such, you will see jobs queuing and dequeuing, but nothing will happen; your perform method will not be called because your class will not be available to Delayed::Job when it YAML::load()s your delayed job.
I'm not sure if it's changed since this 'cast came out but I had to do several more steps or the AJAX doesn't work:
Most importantly the jquery-rails install doesn't do all it needs to so you have to add "jquery rails" to your javascript_expansions[:default] yourself. i.e. in your config/application.rb file make sure you have:
config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
Next you need to add ", :remote => true" to the end of the form_tag line in your partial file:
<%= form_tag products_path, :method => 'get', :id => "products_search", :remote => true do %>
Hopefully that helps anyone having problems following your mostly excellent tutorial.
Awesome stuff...I'm using windows 7 with rails 3.0.3 and it work good...but for some reason I deploy it to heroku it does work, I remove the gemlock file like it suggest on some forums it worked again but the 2nd time I did a commit it got stuck again...not sure if anyone knows a permanent fix fox this
If it helps anyone, this is what I ended up with in my RJS file - assuming I had hidden 'folder_notice_success' and 'folder_notice_fail' divs above the form and I had a simple form that could only possibly return one error. I need to clean this up (and I have no idea what I'm doing), but it seems to work great. I'm also calling a Javascript function in the view that uses and AJAX call to refresh a list of folders (since this is all from a form_remote that creates a new folder). But, I'm only calling that function if the @folder.save was successful:
CONTROLLER:
respond_to do |format|
if @folder.save
flash[:notice] = "New folder successfully created!"
format.html { redirect_to 'new' }
format.js
else
flash[:error] = "doesn't matter right now as long is something is here."
format.html { redirect_to 'new' }
format.js
end
end
RJS FILE:
if !flash[:notice].blank?
page[:folder_name].value = ''
page.replace_html :folder_notice_success, flash[:notice]
page[:folder_notice_success].show
page.delay(3) do
page[:folder_notice_success].hide
end
page << "folder_lookup()"
elsif !flash[:error].blank?
page.replace_html :folder_notice_fail, 'ERROR: ' + @folder.errors.to_xml
page[:folder_notice_fail].show
page.delay(4) do
page[:folder_notice_fail].hide
end
end
flash.discard
Hey Ryan do you believe that the Notifications is a good place to catch exception or Rack is better? Ideally I would to track all exceptions not just the ones that happen during a request for example catch exception when using Runner or when an asyncronous function is executed in a task queue.
For those getting a 401 error - OAuth::Unauthorized I found the following two things could generate this:
1. When setting up the twitter account you must specify the return url (use 127.0.0.1 instead of localhost as localhost won't validate as a proper url). If you don't, twitter will set your account as a client call type, not a browser call, and somehow this ends in a 401 error.
2. A mistake in pasting in the two provider keys that twitter provided.
Ryan, Thanks for another precise tutorial. I have used MetaWhere with jQGrid and its multisearch feature and thought I might share this. The url from the multisearch contains a json hash. To use the parameters in the hash I did the following in the controller:-
<script src="https://gist.github.com/809192.js"> </script>
and then pass the filters hash to the where(filters). This works very well. However I do not know how to use the parameters coming from the 'groupOp' key of the json hash. Help will be appreciated.
Once again many thanks and hope the above will be of help to a few.
Hi Ryan,
thanks for this! you talked about how if you don't embed the javascript in the html.erb file (ie have an external js with the graph info instead), you would need to do something else (ajaxy i'm guessing?) could you describe how to do this or point me in the right direction? I'm really new to the js and ajax scene :)
Very good! I did a small gist with modifications to get all ajax links (data-remote) automatically, and a small fix to the initial page status. If any one is interested: https://gist.github.com/807074
@10, just add some flagging and you can sort on your side with the most spam flags you can delete from time to time. This will improve your existing awesome content which you probably spend like hundreds of hours on. Thank you so very much!
its all nice and nice BUT the harder parts about 0authentification are confirmation emails, password resets and generating (even non-html) mails. I hope you cover such a thing too then I can drop devise.
I fully agree... generators are better than engines for "unfinished" or to-by-heavily-modified parts of applications, still Devise is great ;)
Great screencast Ryan. As I was watching it and noticed how the view determines the search criteria I immediately rose my red flag with security in mind. I was glad you mentioned the security issue and the solution towards the end. Thank you.
Very cool screencast Ryan. I had heard about both of these gems before but hadn't seen them in action. The MetaWhere.operator_overload! is also supercool. By the way, Ryan mentioned that both Datamapper and Mongoid have those predicate finders (e.g. :name.gt, :name.lt...etc). Just wanted to let people know that MongoMapper has the same predicate style finders using the custom Plucky gem. Its built into MongoMapper querying. Again awesome screencast
Thanks, Ryan! One of my favorite features of MetaWhere is intelligent hash condition mapping. This means that you can do really complex join operations and still write your wheres just by using the association names. MetaWhere will find the right table name automatically.
See http://metautonomo.us/projects/metawhere/#associations for more.
Thanks for this Ryan! I saw these gems a while back but use mongodb. Is there anyway to use with mongodb not active record or is there another gem you know if that does the same ?
Its unfortunate that Ben Johnson has dropped off the face of the Earth with Searchlogic and Authlogic. I'd love to see these gems running on Rails 3 but at least Meta Search and Declarative Authorization fit my needs.
I've never posted on your casts before... but I'm using them more and more now that I'm working with Rails on a daily basis...
So I think it's time to say thank you, and congrats on reaching #250 :)
great idea to have a RC more on the metal this time, seamed like a very nice voyage in time :).
@Tim, I'd say paranoiac: your ivar is living during the request only! I admit though, that paranoiac is good when it comes to security ;). However, you also need to flush the params hash and maybe one or two other things. And probably the object in which you are flushing is going to die very, very soon after the save, and flushing before the save might not be a brilliant move ;).
@Junhyun: MetaSearch adjusts the form method automatically in cases where the object supplied is a MetaSearch::Builder (as @search is)
@Chris password_hash can be used because the whole hash output from BCrypt also contains the salt and hash_secret is smart enough to detect that and just use the salt.
In fact, I would not even store the salt in the database any more. It's not needed and just increases the chance of bugs (duplicated storage of state is never a good idea).
@Pawe? what is your reasoning behind sticking to a non-standard and less secure solution? I can see that you might not want to change your existing old code, which is totally fine, but coming here to a tutorial about addition authentication from scratch to new applications, recommending an outdated and non-standard solution of the publicly accepted more secure standard solution seems not too intelligent.
How did we get to the index path when submitting the form_for(@search) without specifying the GET method?
Oooo you beautiful man you! I am just about to start creating a search page with various dropdowns and options etc and his just made my day.
Definitely nicer than Searchlogic. Thanks, Ryan!
@Tiaglo Scolari: this is the best solution I could find! Simple but effective. I have renamed ajax_loaded to state_pushed, but this is the only modification I could come up with :) (I support AJAX queries even if history state is not available)
This is really useful and went 99% of the way to getting me going with CollectiveIdea's Delayed::Job plugin with Rails3. However, one absolutely crucial but missing piece from this Railscast, at least with respect to Rails3 is that without adding a line to your config/application.rb file to load your lib/mailing_job.rb file when your application is initialize!d means that your class definition will not be available to the jobs:work rake task when it tries to dequeue a job from the database and run it. As such, you will see jobs queuing and dequeuing, but nothing will happen; your perform method will not be called because your class will not be available to Delayed::Job when it YAML::load()s your delayed job.
I'm not sure if it's changed since this 'cast came out but I had to do several more steps or the AJAX doesn't work:
Most importantly the jquery-rails install doesn't do all it needs to so you have to add "jquery rails" to your javascript_expansions[:default] yourself. i.e. in your config/application.rb file make sure you have:
config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
Next you need to add ", :remote => true" to the end of the form_tag line in your partial file:
<%= form_tag products_path, :method => 'get', :id => "products_search", :remote => true do %>
Hopefully that helps anyone having problems following your mostly excellent tutorial.
Awesome stuff...I'm using windows 7 with rails 3.0.3 and it work good...but for some reason I deploy it to heroku it does work, I remove the gemlock file like it suggest on some forums it worked again but the 2nd time I did a commit it got stuck again...not sure if anyone knows a permanent fix fox this
Nicolas: MetaSearch has that. See http://bit.ly/fKXH9Q for the docs.
I still miss Searchlogic's field_like_any it was kind of useful for some autocomplete stuff =/
How do you handle exception here ? Don't want to have this ugly "HTTP Basic: Access denied." sign.
rails g devise:views has to be used instead of rails generate devise_views which is not deprecated in current versions of Rails and Devise.
awesome screencast. sort link helper is cool one in this plugin.
Very nice, so it's a bit like objective-c/cocoa does it.
If it helps anyone, this is what I ended up with in my RJS file - assuming I had hidden 'folder_notice_success' and 'folder_notice_fail' divs above the form and I had a simple form that could only possibly return one error. I need to clean this up (and I have no idea what I'm doing), but it seems to work great. I'm also calling a Javascript function in the view that uses and AJAX call to refresh a list of folders (since this is all from a form_remote that creates a new folder). But, I'm only calling that function if the @folder.save was successful:
CONTROLLER:
respond_to do |format|
if @folder.save
flash[:notice] = "New folder successfully created!"
format.html { redirect_to 'new' }
format.js
else
flash[:error] = "doesn't matter right now as long is something is here."
format.html { redirect_to 'new' }
format.js
end
end
RJS FILE:
if !flash[:notice].blank?
page[:folder_name].value = ''
page.replace_html :folder_notice_success, flash[:notice]
page[:folder_notice_success].show
page.delay(3) do
page[:folder_notice_success].hide
end
page << "folder_lookup()"
elsif !flash[:error].blank?
page.replace_html :folder_notice_fail, 'ERROR: ' + @folder.errors.to_xml
page[:folder_notice_fail].show
page.delay(4) do
page[:folder_notice_fail].hide
end
end
flash.discard
Hey Ryan do you believe that the Notifications is a good place to catch exception or Rack is better? Ideally I would to track all exceptions not just the ones that happen during a request for example catch exception when using Runner or when an asyncronous function is executed in a task queue.
@Ryan and @Geoff,
Even though Time.zone is thread-local, that won't prevent it from leaking from one request to a subsequent request on the same thread.
Here's the fix for that:
https://gist.github.com/809775
For those getting a 401 error - OAuth::Unauthorized I found the following two things could generate this:
1. When setting up the twitter account you must specify the return url (use 127.0.0.1 instead of localhost as localhost won't validate as a proper url). If you don't, twitter will set your account as a client call type, not a browser call, and somehow this ends in a 401 error.
2. A mistake in pasting in the two provider keys that twitter provided.
Ryan, Thanks for another precise tutorial. I have used MetaWhere with jQGrid and its multisearch feature and thought I might share this. The url from the multisearch contains a json hash. To use the parameters in the hash I did the following in the controller:-
<script src="https://gist.github.com/809192.js"> </script>
and then pass the filters hash to the where(filters). This works very well. However I do not know how to use the parameters coming from the 'groupOp' key of the json hash. Help will be appreciated.
Once again many thanks and hope the above will be of help to a few.
in the asciicast, this line:
BCrypt::Engine.hash_secret(password, password_salt)
got changed to this:
BCrypt::Engine.hash_secret(password, password_hash)
pass it on to whomever does asciicasts i guess
It would be good to have an episode on tableless models with MongoID!
Hi Ryan,
thanks for this! you talked about how if you don't embed the javascript in the html.erb file (ie have an external js with the graph info instead), you would need to do something else (ajaxy i'm guessing?) could you describe how to do this or point me in the right direction? I'm really new to the js and ajax scene :)
Just for comparison (the same markup with rails content_tag helper):
content_tag :div, nil, :class => 'error_messages' do
content = content_tag(:h2, "... errors occurred")
content << content_tag(:p, "There were problems...:")
content << content_tag(:ul) do
object.errors.to_a.map do |msg|
content_tag :li, msg
end.join.html_safe
end
end
rails g devise:install when using rails 3.0.x
When using rails generate devise_install it now leads to an error in the following steps.
Very good! I did a small gist with modifications to get all ajax links (data-remote) automatically, and a small fix to the initial page status. If any one is interested: https://gist.github.com/807074
Excellent screencast! Thank you for always providing such helpful content!
@arkadiy kraportov check out https://github.com/cldwalker/hirb . Ryan covers it quickly on some previous episode.
user 718: I've got the same problem.
It's fixed according to the mongoid author, but I'm not sure that fix is already pushed in rc 7
@10, just add some flagging and you can sort on your side with the most spam flags you can delete from time to time. This will improve your existing awesome content which you probably spend like hundreds of hours on. Thank you so very much!
Hey Ryan,
its all nice and nice BUT the harder parts about 0authentification are confirmation emails, password resets and generating (even non-html) mails. I hope you cover such a thing too then I can drop devise.
I fully agree... generators are better than engines for "unfinished" or to-by-heavily-modified parts of applications, still Devise is great ;)
i might have missed something.. how did you get this nice model printout from a console?
Great screencast Ryan. As I was watching it and noticed how the view determines the search criteria I immediately rose my red flag with security in mind. I was glad you mentioned the security issue and the solution towards the end. Thank you.
Very cool screencast Ryan. I had heard about both of these gems before but hadn't seen them in action. The MetaWhere.operator_overload! is also supercool. By the way, Ryan mentioned that both Datamapper and Mongoid have those predicate finders (e.g. :name.gt, :name.lt...etc). Just wanted to let people know that MongoMapper has the same predicate style finders using the custom Plucky gem. Its built into MongoMapper querying. Again awesome screencast
There is a railsdog fork from the searchlogic what is working fully compatible with rails 3
https://github.com/railsdog/searchlogic
gem 'rd_searchlogic', :require => 'searchlogic', :git => 'git://github.com/railsdog/searchlogic.git'
Really great Screencast! I hat using this SQL code and so I'm happy about this alternative. Why the hack is this not build in standard ActiveRails?
Thanks, Ryan! One of my favorite features of MetaWhere is intelligent hash condition mapping. This means that you can do really complex join operations and still write your wheres just by using the association names. MetaWhere will find the right table name automatically.
See http://metautonomo.us/projects/metawhere/#associations for more.
Thanks for this Ryan! I saw these gems a while back but use mongodb. Is there anyway to use with mongodb not active record or is there another gem you know if that does the same ?
thanks
Keep up the great work!
Where is twitter or facebook like button
Its unfortunate that Ben Johnson has dropped off the face of the Earth with Searchlogic and Authlogic. I'd love to see these gems running on Rails 3 but at least Meta Search and Declarative Authorization fit my needs.
Has anyone else had issue using the key value?
I've been trying to get that to work, but can't figure it out.
gem "mongoid", "2.0.0.rc.7"
gem "bson_ext", "~> 1.2"
Too bad that many nice solutions are hardwired to ActiveRecord and SQL.
I had hoped that ActiveModel would enable them to build things working with MongoDB or Datemapper too.
But it seems those are too different after all.
Thanks, it's perfect for creating complex search forms.
Very nice screencast! Looks like an elegant way to code an advanced search for a site.
Tested with Rails 3. It's working smoothly with Formtastic too. This looks better than ugly scope based searches. Another great episode! Thanks Ryan.
Hello Ryan,
Please consider doing another episode using Devise's new omniauth integration support?
Thanks for all the hard work.
Bharat
I wanna try this, thanks for share Ryan
Hi Ryan,
I've never posted on your casts before... but I'm using them more and more now that I'm working with Rails on a daily basis...
So I think it's time to say thank you, and congrats on reaching #250 :)
Cheers
Olivier
Ryan
great idea to have a RC more on the metal this time, seamed like a very nice voyage in time :).
@Tim, I'd say paranoiac: your ivar is living during the request only! I admit though, that paranoiac is good when it comes to security ;). However, you also need to flush the params hash and maybe one or two other things. And probably the object in which you are flushing is going to die very, very soon after the save, and flushing before the save might not be a brilliant move ;).
Cheers
Robert
Ryan,
I cannot view/download any video from you webside. media.railscasts.com is down! What happened?