One more thing… I haven't seen a Fileupload plugin which is capable of keeping the temporar file of an upload if the validation fails.
For instance we've the model Medium which has_attachment :file and validates_presence_of :comment. If we left out the comment but specified a :file (let's say a big one... 200MB...) the validation will fail and the data is lost.
It's pretty annoying if you have to upload the file again.
As a workaround you can reflect the validation on client side... but it's not a solution for the problem.
thanks Koen Van der Auwera.
Another way for solving this is setting PATH as environment variable for Mac OS X 10.5 in /System/Library/LaunchDaemons/org.apache.httpd.plist:
Very interesting video, as new to rails and new to javascript in general, I was wondering how to make both work together, but couldn't figure it out because of information overload. This screencasts sums it up pretty well, now all I have to do is learn a bit more javascript and jquery.
I'm using paper clip to upload documents (doc and rtf) it workd fine for a while then it stops suddenly! I can't figure out what's the problem but when I restart my mongrel instance it works fine again... anyone knows anything about it??
For some reason when I used Paperclip to resize images for thumbnails it produced files of 0bytes. I had to specify in the model that I wanted jpg files created even if the original was a jpg.
In the following instance the 'small' picture would be fine, but the 'regular' size would be corrupt.
An example of a rake db:migrate:up would be if you are moving from one db to another (ie sqlserver version XYZ.1 to sqlserver version XYZ.2) and have a bunch of imported data (static data) as a migration.
So: rake db:schema:dump on sqlserverXYZ.1, goto sqlserverXYZ.2, do a rake db:schema:load
Then you would rake db:migrate:up VERSION=XXXXXXXXX (your import migrations).
That way - you don't have to worry about sqlserver version dependencies with migrations that may fail due to version incompatablity - but can still use the migration scripts needed to load your static data
Thanks Pat, i have almost completed my project into sphinx, and i found sphinx much much easier than ferret. Like it provides default will paginate support and its delta feature is also very very good and useful, Plus provides a lot of default functionalities. Pat i really appreciate and congrates you for developing this wonderful plugin. I also recommend others to use this plugin.
Is there a way to make the link_to :delete to be less unobtrusive? I really dont like how it generates a full form in place along with the authenticity_token which means i can't cache anything with that link.
One idea is that we put the authenticity_token in the meta tag/or some other suitable non-cached part of the page with an id and use jquery to scan for delete links and handle the click event on those links to make the correct call to the server along with the authenticity token in place. Anyone already worked on something like that?
Fantastic screencast! Helped me refactor some similar stuff I had been doing with Rails and jQuery. For those who'd like to check out another tutorial on this subject, my blog post:
So after a lot of research I've figured out how to do this somewhat properly. Short answer is:
def expire_cache(question)
expire_fragment(%r{public/questions.*})
end
Here's the explanation:
1. You can't use expire_action, you need to use expire_fragment
2. You need to use a regex
So if you take a look at the source for expire_action and expire_fragment you'll notice that expire_fragment has a "key" passed to it and expire_action does not accept one:
You'll also notice that expire_action is largely just a proxy to expire_fragment if all you're doing is passing it an actual path.
You'll probably want to craft your regex much more elegantly and safely than I have done here, especially if you are caching more than just one thing.
In the end though I see it as an issue with the rails code and expire_action should take the regex as an argument just like expire_fragment does I think.
I figured out how to get paginated pages to cache, but I'm having trouble getting them to expire:
def expire_cache(question)
expire_action "public/questions/"
end
The index page (page 1) expires properly, but all other pages do not - they cache once and never expire.
I've tried putting * at the end of that path and also including the #{params[:page} at the end of the path (I don't think this should work though since that isn't passed). How can you erase the cache for an entire directory?
any reason a cache sweeper would work in development, but not in production? I'm running passenger and I've tried with both memory store and file store and my sweepers aren't working. They work great in development though.
Pull the encryption methods from restful authentication.
#These are needed to create the salt for user passwords
def secure_digest(*args)
Digest::SHA1.hexdigest(args.flatten.join('--'))
end
def make_token
secure_digest(Time.now, (1..10).map{ rand.to_s })
end
#This is needed to encrypt the user password
def password_digest(password, salt)
digest = REST_AUTH_SITE_KEY
REST_AUTH_DIGEST_STRETCHES.times do
digest = secure_digest(digest, salt, password, REST_AUTH_SITE_KEY)
end
digest
end
Then populate your user table using these methods:
User.populate 10 do |user|
user.email = Faker::Internet.email
user.salt = make_token
user.crypted_password = password_digest('mypassword',user.salt)
end
You can make this work with restful authentication by setting user.salt and user.crypted_password. Pull the encryption methods from restful authentication:
Sphinx itself does support this, but it's not yet been implemented in Thinking Sphinx (although I've had someone supply a patch in the last week - I just need to find time to review and possibly merge it).
Thanks Pat,Is sphinx providing highlight feature? right now i m using rails helper function for highlight, whether sphinx provide any
functionality like this?.
do anyone of you know how to include by paperclip generated thumbnails to the to_xml methode?
If I use methods I can specify an array with fields but there I can't say the variation (e.g. small part of photo).
I tried for a couple days to make this work with the RESTful authentication. I wanted to add 'roles' to user accounts.
so I have a User class and a Role class. both are HABTM with a proper join table.
I'm not sure exactly what "RESTful authentication" is doing differently, hiding methods or something, but I had to specifically add ":role_ids" in where you specify attr_accessible in the User class.
Analagising this to the example, you'd have to specifically put
attr_accessible :catagory_ids
in the Product class
I'm not sure why this is, but I hope I can save someone some frusteration!
Any recommendations against using fleximage? http://github.com/Squeegy/fleximage/wikis
paperclip looks very easy, but so does fleximage. The one thing that really catches my attention about it is the dynamic resizing:
http://github.com/Squeegy/fleximage/wikis/rendering
From what I understand it will render whatever size you want at anytime after the upload, so you don't have to figure out all your sizes in advance and then build your own rake task if you want to make a new size.
Those looking for the pagination code, I used this and it seems to work (using restful authentication for the login info):
def index_cache_path
if logged_in? && current_user.has_role?('administrator')
"/admin/questions/#{params[:page]}"
else
"/public/questions/#{params[:page]}"
end
end
Hey Bryan, as a rails newbi from Germany I love your casts. And with regards to paperclip: my project uses file_column but I would like to switch to paperclip. Do you know how I can make the switch smooth so that I cann still use the so far uploaded Files (path: system/user/picture/<id>/<filename>)? Great if you could help me.
All the best. Im a big fan.
Nick
when i use git to install paperclip via "script/plugin install git://github.com/thoughtbot/paperclip.git", i get the following error (after which, if i try to use the paperclip generator, it says it doesn't exist)...
http://pastie.org/318325
If you could give me ANY help i would appreciate it. i can't tell if my git install is screwed up, or if i'm missing something. everyone else seems to have an easy time installing this.
Wasn't there a problem when using Jquery and CSRF protection ?
Do we still need thos kind of hacks : http://errtheblog.com/posts/73-the-jskinny-on-jquery#comment_1154 ?
i think jquery is holding totally different ideas from Prototype.
jquery aims to maintain a minimal core for dom & ajax , but prototype is kind of ruby-clone on JS.
I just got done with a project where I used jQuery quite extensively. I find it a lot of fun to use, and easier the Prototype because it “is just selector/whistles-and-dongles (effects) framework.” My one big peace of learning from this project was to limit my use of 'id' in my html as much as possible. It is a real nightmare having to name every element you want to use. The selector in jQuery is much more powerful being a superset of CSS3.
My humble suggestion is to initially skip the id for anything that doesn't need it for CSS. If selection is to complex or ambiguous, first try adding a class to an element. Sense classes are reusable, it makes code reuse simple as adding a class to other elements. Your form for example could have been selected simply as $('form') all forms on a page will then submit with Ajax. If this is not appropriate, try $('#some_div form'). Or maybe add an 'ajax' class to the forms that you want to submit asynchronously.
The need to constantly name every element on a page will eventually drive you up the wall.
@derek, no merb cast planned (since I want to stay on topic of Rails), but if there's enough interest then maybe.
@Gruszks, I left off validations to keep things simple and because it didn't flow well. I'm also playing around with a few different ways to handle AJAX validations, so maybe it will be a separate screencast.
"$(document).ready(function() {" can actually be shortened down to "$(function() {" since the default behavior of $() receiving a function is the same as ready on document.
However, I use "jQuery(function($) {", so that it wont be an issue if something overrides the $ variable - it is passed as an argument to the callback here so you wont be accessing the global variable inside the function body. Note that $ is the same as the "jQuery" variable. If you load jQuery last and need $ to be what it was before, you can also call "jQuery.noConflict();" to restore it.
Also worth noting is that semicolons are not often required, but encouraged.
One more thing… I haven't seen a Fileupload plugin which is capable of keeping the temporar file of an upload if the validation fails.
For instance we've the model Medium which has_attachment :file and validates_presence_of :comment. If we left out the comment but specified a :file (let's say a big one... 200MB...) the validation will fail and the data is lost.
It's pretty annoying if you have to upload the file again.
As a workaround you can reflect the validation on client side... but it's not a solution for the problem.
Hi,
thanks Koen Van der Auwera.
Another way for solving this is setting PATH as environment variable for Mac OS X 10.5 in /System/Library/LaunchDaemons/org.apache.httpd.plist:
http://gist.github.com/28112
Very interesting video, as new to rails and new to javascript in general, I was wondering how to make both work together, but couldn't figure it out because of information overload. This screencasts sums it up pretty well, now all I have to do is learn a bit more javascript and jquery.
Fantastic stuff Ryan. If you knew how long I've been trying to understand handling nested models...
I created an unobtrusive jQuery screen cast a little while ago inspired by these Railscasts.
http://thenexttrain.co.za/2008/08/screencast-ruby-on-rails-unobtrusive-jquery/
Checked my mongrel log and found this: Error reading HTTP body: #<RuntimeError: Socket read returned insufficient data: 10379>
I'm using paper clip to upload documents (doc and rtf) it workd fine for a while then it stops suddenly! I can't figure out what's the problem but when I restart my mongrel instance it works fine again... anyone knows anything about it??
This broke for me when upgrading to 2.2.2
The content_for capture in application_helper.rb doesn't fail, but it also doesn't insert the stylesheet/javascript into the template.
Any ideas?
For some reason when I used Paperclip to resize images for thumbnails it produced files of 0bytes. I had to specify in the model that I wanted jpg files created even if the original was a jpg.
In the following instance the 'small' picture would be fine, but the 'regular' size would be corrupt.
has_attached_file :photo, :styles => { :small => ["100x100#", :jpg], :regular => "300>"}
If anyone is having trouble on Windows I've found a solution:
http://ifakedit.com/log/2008/11/21/pretty-rails-logs-in-windows/
It uses MSYS that Git comes with to tail the file. This enables coloring and such.
Nice one. I wish this worked with image_submit_tag too.
The name attribute does not not get passed back in the params hash for image_submit_tag
Awesome. Thanks so much, Ryan. It seems as though whenever I need to do something which is new for me you have a screencast about it.
Keep up the great work. You rock! :-)
DanNewman's method looks better - putting the authorization token in the layout header.
Although I'm wondering if that's a security hole?
@Aditya - I had this same exact issue. Here is my solution:
http://pastie.org/320945
(Basically I load the edit form into the page and change _method to 'delete' instead of 'put', and submit :-P)
Ryan - thanks so much! I learned a lot :-)
An example of a rake db:migrate:up would be if you are moving from one db to another (ie sqlserver version XYZ.1 to sqlserver version XYZ.2) and have a bunch of imported data (static data) as a migration.
So: rake db:schema:dump on sqlserverXYZ.1, goto sqlserverXYZ.2, do a rake db:schema:load
Then you would rake db:migrate:up VERSION=XXXXXXXXX (your import migrations).
That way - you don't have to worry about sqlserver version dependencies with migrations that may fail due to version incompatablity - but can still use the migration scripts needed to load your static data
Thanks Pat, i have almost completed my project into sphinx, and i found sphinx much much easier than ferret. Like it provides default will paginate support and its delta feature is also very very good and useful, Plus provides a lot of default functionalities. Pat i really appreciate and congrates you for developing this wonderful plugin. I also recommend others to use this plugin.
Is there a way to make the link_to :delete to be less unobtrusive? I really dont like how it generates a full form in place along with the authenticity_token which means i can't cache anything with that link.
One idea is that we put the authenticity_token in the meta tag/or some other suitable non-cached part of the page with an id and use jquery to scan for delete links and handle the click event on those links to make the correct call to the server along with the authenticity token in place. Anyone already worked on something like that?
Fantastic screencast! Helped me refactor some similar stuff I had been doing with Rails and jQuery. For those who'd like to check out another tutorial on this subject, my blog post:
http://polyrails.com/2008/11/11/steps-to-unobtrusive-rails-with-jquery/
Covers AJAX approach leveraging your existing rails templates (eg edit.html.erb) and reporting validation errors w/ jQuery unobtrusive JS.
==How to expire paginated pages
So after a lot of research I've figured out how to do this somewhat properly. Short answer is:
def expire_cache(question)
expire_fragment(%r{public/questions.*})
end
Here's the explanation:
1. You can't use expire_action, you need to use expire_fragment
2. You need to use a regex
So if you take a look at the source for expire_action and expire_fragment you'll notice that expire_fragment has a "key" passed to it and expire_action does not accept one:
http://api.rubyonrails.org/classes/ActionController/Caching/Fragments.html
http://api.rubyonrails.org/classes/ActionController/Caching/Actions.html
You'll also notice that expire_action is largely just a proxy to expire_fragment if all you're doing is passing it an actual path.
You'll probably want to craft your regex much more elegantly and safely than I have done here, especially if you are caching more than just one thing.
In the end though I see it as an issue with the rails code and expire_action should take the regex as an argument just like expire_fragment does I think.
Hey Ryan -
I figured out how to get paginated pages to cache, but I'm having trouble getting them to expire:
def expire_cache(question)
expire_action "public/questions/"
end
The index page (page 1) expires properly, but all other pages do not - they cache once and never expire.
I've tried putting * at the end of that path and also including the #{params[:page} at the end of the path (I don't think this should work though since that isn't passed). How can you erase the cache for an entire directory?
Franco,
just put jQuery.noConflict() in your application.js, and jQuery will relinquish control of the $ method
Great tutorial but not easy to understand. Thanks a lot for our help.
any reason a cache sweeper would work in development, but not in production? I'm running passenger and I've tried with both memory store and file store and my sweepers aren't working. They work great in development though.
Argh, pastie...
Pull the encryption methods from restful authentication.
#These are needed to create the salt for user passwords
def secure_digest(*args)
Digest::SHA1.hexdigest(args.flatten.join('--'))
end
def make_token
secure_digest(Time.now, (1..10).map{ rand.to_s })
end
#This is needed to encrypt the user password
def password_digest(password, salt)
digest = REST_AUTH_SITE_KEY
REST_AUTH_DIGEST_STRETCHES.times do
digest = secure_digest(digest, salt, password, REST_AUTH_SITE_KEY)
end
digest
end
Then populate your user table using these methods:
User.populate 10 do |user|
user.email = Faker::Internet.email
user.salt = make_token
user.crypted_password = password_digest('mypassword',user.salt)
end
You can make this work with restful authentication by setting user.salt and user.crypted_password. Pull the encryption methods from restful authentication:
<script src='http://pastie.org/319672.js'></script>
Then populate your user table using these methods:
<script src='http://pastie.org/319680.js'></script>
Hi Faisal
Sphinx itself does support this, but it's not yet been implemented in Thinking Sphinx (although I've had someone supply a patch in the last week - I just need to find time to review and possibly merge it).
Thanks Pat,Is sphinx providing highlight feature? right now i m using rails helper function for highlight, whether sphinx provide any
functionality like this?.
how does this work if my model only has a unique ID column? the "name" is not unique.
Hi @all,
do anyone of you know how to include by paperclip generated thumbnails to the to_xml methode?
If I use methods I can specify an array with fields but there I can't say the variation (e.g. small part of photo).
Any ideas?
Thanks for your help,
Steffen
Good very good!!
Very interesting write up.
I tried for a couple days to make this work with the RESTful authentication. I wanted to add 'roles' to user accounts.
so I have a User class and a Role class. both are HABTM with a proper join table.
I'm not sure exactly what "RESTful authentication" is doing differently, hiding methods or something, but I had to specifically add ":role_ids" in where you specify attr_accessible in the User class.
Analagising this to the example, you'd have to specifically put
attr_accessible :catagory_ids
in the Product class
I'm not sure why this is, but I hope I can save someone some frusteration!
Any recommendations against using fleximage? http://github.com/Squeegy/fleximage/wikis
paperclip looks very easy, but so does fleximage. The one thing that really catches my attention about it is the dynamic resizing:
http://github.com/Squeegy/fleximage/wikis/rendering
From what I understand it will render whatever size you want at anytime after the upload, so you don't have to figure out all your sizes in advance and then build your own rake task if you want to make a new size.
Those looking for the pagination code, I used this and it seems to work (using restful authentication for the login info):
def index_cache_path
if logged_in? && current_user.has_role?('administrator')
"/admin/questions/#{params[:page]}"
else
"/public/questions/#{params[:page]}"
end
end
Solved my issue by installing ImageMagick-6.4.5-8-Q16-windows-dll.exe
@Laser Lemon
I am getting the same error on two different machines, a vista and an XP.
I do not have imagemagick installed.
AppData/Local/Temp/stream.2620.0 is not recognized by the 'identify' command.
Hey Bryan, as a rails newbi from Germany I love your casts. And with regards to paperclip: my project uses file_column but I would like to switch to paperclip. Do you know how I can make the switch smooth so that I cann still use the so far uploaded Files (path: system/user/picture/<id>/<filename>)? Great if you could help me.
All the best. Im a big fan.
Nick
Hi Yves, Laser Demon, all,
I got it working with an intializer: http://gist.github.com/26476 - Passenger + Paperclip that is.
via http://www.fuzzylizard.com/archives/2008/07/05/954/
when i use git to install paperclip via "script/plugin install git://github.com/thoughtbot/paperclip.git", i get the following error (after which, if i try to use the paperclip generator, it says it doesn't exist)...
http://pastie.org/318325
If you could give me ANY help i would appreciate it. i can't tell if my git install is screwed up, or if i'm missing something. everyone else seems to have an easy time installing this.
@Ryan, correction on my previous comment -- looks like Accept header recognition was re-enabled with this commit:
http://github.com/rails/rails/commit/4ce9931f4f30045b2975328e7d42a02188e35079
@Ryan, Great episode! I have always enjoy learning from you. Each episode is like equivalent of a chapter of book, only easier to grasp!
By following your episode, I was able to get my starling and workling working in less than 30 minutes.
@All, Here are just few gotchas based on my experience that I would to share with other people learning.
1. It seems that every time I change the code in the worker, I have to reload the working client; otherwise, change will not take effect.
2. When calling the async_xxx method, its important to spell correctly, otherwise, no warning or error will be given.
By the way, can you achieve same technique with jQuery?
http://arturaz.net/blog/?p=545
Wasn't there a problem when using Jquery and CSRF protection ?
Do we still need thos kind of hacks : http://errtheblog.com/posts/73-the-jskinny-on-jquery#comment_1154 ?
Great screencast by the way ;)
Hi all. Is there some way to keep the prototype working together with jquery?
I would like to migrate to jquery, but I want to do it progressively.
Thanks to the railscast.
Ryan, an AJAX validation screencast would be very helpful.
What is the benefit of using gems as opposed to plugins?
i think jquery is holding totally different ideas from Prototype.
jquery aims to maintain a minimal core for dom & ajax , but prototype is kind of ruby-clone on JS.
I just got done with a project where I used jQuery quite extensively. I find it a lot of fun to use, and easier the Prototype because it “is just selector/whistles-and-dongles (effects) framework.” My one big peace of learning from this project was to limit my use of 'id' in my html as much as possible. It is a real nightmare having to name every element you want to use. The selector in jQuery is much more powerful being a superset of CSS3.
My humble suggestion is to initially skip the id for anything that doesn't need it for CSS. If selection is to complex or ambiguous, first try adding a class to an element. Sense classes are reusable, it makes code reuse simple as adding a class to other elements. Your form for example could have been selected simply as $('form') all forms on a page will then submit with Ajax. If this is not appropriate, try $('#some_div form'). Or maybe add an 'ajax' class to the forms that you want to submit asynchronously.
The need to constantly name every element on a page will eventually drive you up the wall.
@derek, no merb cast planned (since I want to stay on topic of Rails), but if there's enough interest then maybe.
@Gruszks, I left off validations to keep things simple and because it didn't flow well. I'm also playing around with a few different ways to handle AJAX validations, so maybe it will be a separate screencast.
@Dag, thanks for the tips!
"$(document).ready(function() {" can actually be shortened down to "$(function() {" since the default behavior of $() receiving a function is the same as ready on document.
However, I use "jQuery(function($) {", so that it wont be an issue if something overrides the $ variable - it is passed as an argument to the callback here so you wont be accessing the global variable inside the function body. Note that $ is the same as the "jQuery" variable. If you load jQuery last and need $ to be what it was before, you can also call "jQuery.noConflict();" to restore it.
Also worth noting is that semicolons are not often required, but encouraged.