I had the same problem as everyone above and also failed to get it working with jeremy's gem. I did however get it to work after some investigation.
I took a look at the rails source and it requires ruby-prof 0.6.1. After installing Jeremy's gem I realized it had a slightly different name (jeremy-ruby-prof vs. ruby-prof.) That's probably a github thing but it wasn't satisfying the gem command inside of rails.
So I built the gem from ruby forge source (rake gem, and install manually from the pkg location) and it worked!
Similar problem like Tim: how to (auto-)number the tasks? I don't mind if on remove it isn't actually shown correct, but after commit the task should be written correctly (1, 2, 3, ...) to the database.
1) with either plain or timestamped version numbers, the migrations just care about the order of the numbers..
It seems to be just a difference in how the number is generated.
2) you can disable timestamped migrations by putting this in your environment.rb file:
3) If you have a project with a lot of developers who do schema changes, the timestamps will help.
(Meetings will help more! ;-) )
On the other hand you might have a project where you have a larger schema & dependency change,
and you might need to renumber all your migrations to allow a smooth "rake migrate" (up and down).
In this case you'd have to either "make up" fake timestamps for your migrations, or better: go back
to plain version numbers for the migrations.
We have a question on combining subdomains (done with SubdomainFu) and selenium-on-rails. Whenever we access a subdomain we get a same origin policy permissions error. How do we test an application using selenium that uses subdomains? Thanks!
will display the invitation_key in the email field or any other EXCEPT the invitation_key field (hidden or otherwise). Removing the getter/setter fixes this, though.
I have a website 'xyz.com' that dynamically generates sites for social networks and assigns them each a unique subdomain, ie sn1.xyz.com, sn2.xyz.com etc.
The 'site' controller handles all 'xyz.com' requests without the subdomain whereas the 'network' controller handles all requests that have the subdomain present.
How can I conditionally route incoming request based on whether the subdomain is present or not?
@Philip, thanks for pointing out those details, and I agree with you. There are definitely some extra things you need to consider to polish this up for your site before going into production.
@Michael, did you add invitation_token to the attr_accessible line in your User model?
keeps on redirecting to itself. The account_root controller tries to redirect to the index page if the current account cannot be found. With the conditions not working, it falls into a redirect loop.
While I am getting the error shown in the video when trying to register an account with an incorrect invitation ("invitation required"), the video doesn't show a successful registration with the code being passed into the form. I can't get the new User object to pick up the invitation_token. If I can assign it to the a different field (email, for instance) and it shows up, but the getter/setter methods seem to be interfering with it.
This idea occurred to me awhile ago to handle one client's need for a CMS, it probably could use more work, but I pluginized the thing to use across some other applications that were going to need the same sort of setup. Anyone who is interested can grab it here:
Thanks for an excellent episode, one of the most in-depth so far.
If anyone plans to put this in production, there's a couple edge cases to examine. Consider adding an
attr_accessible :recipient_email
to the invitation class (It looks like everything that could be mass-assigned is handled downstream, but its absence makes me nervous), and pulling :invitation_token from the call to User.attr_accessible (if you later add a user update action its value could be crafted: I could be my own grandkid). If a user can be deleted I think their invite codes could re-submit (&so multiply). Also, the presence of multiple routes to the users/new action looks like a problem here, one that should probably be warned about in restful_authentication.
These are just nitpicks for anyone who might build on this excellent foundation. Clearly this episode was already remarkably deep without these ponderous details.
To everyone getting the "Seeing this instead of the website you expected?" Type errors you need to set the NameVirtualHost directive (http://httpd.apache.org/docs/2.0/mod/core.html#namevirtualhost)
in a global part of the apache conf put:
NameVirtualHost *:80
and then the virtualhost sections should start with
<VirtualHost *:80>
ServerName example.local
…
If you want to run an app on port 80 and 443 I think this would work but I'm not sure
NameVirtualHost *:80
NameVirtualHost *:443
<VirtualHost *:80 *:443>
ServerName example.local
…
Try the apache docs if that doesn't work (http://httpd.apache.org/docs/2.0/vhosts/examples.html)
(paraphrasing the Prolegomena-Kant's more 'accessible' work-here) Space and time are the necessary pre-conditions of all future metaphysics.
God, I love being pretentious! (AND pedantic!)
Right, gross simplifications in response to obtuse philosophical musings over, just wanted to offer a belated thanks to you Ryan--this 'cast has just redeemed Rspec for me.
I use this searchmethod and the result is presented in combination with wicegrid (http://redmine.wice.eu/api/wice_grid/index.html) and it works great.
The method for making a SQL condition is awesome.
Any chance you could do a version of this that worked with both :80 and :443? One of the key reasons I want to use Passenger in development is so I can test things like ssl_only filters, which would otherwise require starting two servers and communicating between them.
Congrats Ryan - lots of information clearly presented.
@Alek - it isn't a virtual attribute. Take a look at the API for belongs_to (http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to). This also works in has_many and has_and_belongs_to_many.
It is a shorthand way to tell the model that you want to connection to another other model, access it as sender, and look for something in User with a related sender_id column. It does all of that in one line. Good luck.
@QuBiT and @Carl; Thanks for kind respond and an explanation.
I am still not getting it. Sorry:-(. Is the :sender and the :recipient a virtual attribute? I am not seeing any hook methods pointing to the :recipient and the :sender.
Does the model, in this case User, receives the invitations' id and it knows who the sender is?
@Carl, when you say an alias do you mean it belongs to that particular model...in this case User?
@Alek, this structure allows you to call something like @invitation.sender and know who the sender is, and @invitation.recipient and know who the recipient is, even though both are rows in the 'User' table. It's basically like an alias for each relationship.
@Alek
Rails would look for a sender and recipient model ... but as ryan did not define a separate sender and recipient model you'll get an error.
for cases where you just want a different name then "invitation.user" and use it for different meanings ryan defined the class attribute to tell rails that invitation.sender and invitation.recipient are user-model objects. hope this helps.
I can't tell you how grateful I am for this: I spent weeks beating my head against various search options, and none of them seemed to make any sense for my needs until I finally found this, and suddenly I have everything I need!
I do have a question, though. How would I write the conditions for a boolean field? I have several boolean (true/false) fields in my tables, and I want users to be able to check a box in a search field when a field should be true. How should I do this?
You mention that you are sponsored by pragmatic.tv and I've tried several times to go there with no luck. Do you know what's up (or down) with their site?
I have a question with regard to associations in the invitation model. Sorry to be a bore, but I am not getting this relationship at all;
belongs_to :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
How does a :sender and a :recipient relate to a class 'User'? Is it through virtual attr? I just can see this connection.
@Ryan Bates: Aha, I see. Didn't recognize it. Thanks.
Once again, great stuff. I began with rails around new years 2007/8 and most of the stuff here have inspired my code and my own little conventions to the better.
I am using the Rails 1.2.3, and follow the instruction that clouder said. But it looks like I still miss the dynamic_states.js, even I have correct output in http://localhost:3000/javascripts/dynamic_states. Could someone give any suggestion? Thanks!
In my application I would like to automatically number my tasks and display the number on the page. So far all of my attempts have resulted in the same number for all lines after the first, e.g. 1, 2, 2, 2.
In my task model:
@@line_no = 1
def initialize(attributes = nil)
super
unless line_no?
self.line_no = @@line_no
@@line_no += 1
end
end
I was thinking about the best way to run a daemon to reindex TS at a certain interval. Would it make sense to use the daemon gem in an initializer to kick off this process?
@Michael Graff - I think that wildcard for subdomains is the best solution. For apps like basecamp, we have to authorize usera for some domain just at the begining when he is loggin and save subdomain it session. This better solution, dont you think?
The match_mode => :boolean ignores all field weighting, but match_mode => :extended honors them. This is a bit puzzling, since Extended seems to be just like Boolean, but with even more query features. Extended lets you use boolean ORs and NOTs, without losing the relevancy rankings.
Here's where Sphinx says it does that:
http://sphinxsearch.com/doc.html#weighting
And here's a code sample:
--- In app/models/article.rb
define_index block
...
# Declare a default relevancy table, which can be overridden at search
set_property :field_weights => { :title => 3, :subtitle => 2 }
...
end
--- In app/controllers/article_controller.rb
...
# Grab a page-load of articles, using title-centric field weights.
@articles = Article.search query_string,
:include => [:author, :comments], :match_mode => :extended,
:field_weights => { :title => 10, :subtitle => 6 },
:page => params[:page], :per_page => 20
aaah, answered my (and your) question. Any methods you add that you want to be available outside of the protected methods in this class need to be added to the self.included call later in authenticated_system.rb.
I have been having trouble getting the :field_weights parameter to behave. I can't find it mentioned in the thinking_sphinx API entries on the various search methods:
http://ts.freelancing-gods.com/rdoc/
The best I can find is this:
http://ts.freelancing-gods.com/rdoc/classes/ThinkingSphinx/Index/Builder.html
Where it says :field_weights is an argument to the set_property method.
This seems to imply that field weighting happens when the index is built, not when the search is performed. I'd rather be able to declare my relevancy preferences at search time (like the video shows), not at index time (like the API seems to say).
I had the same problem as everyone above and also failed to get it working with jeremy's gem. I did however get it to work after some investigation.
I took a look at the rails source and it requires ruby-prof 0.6.1. After installing Jeremy's gem I realized it had a slightly different name (jeremy-ruby-prof vs. ruby-prof.) That's probably a github thing but it wasn't satisfying the gem command inside of rails.
So I built the gem from ruby forge source (rake gem, and install manually from the pkg location) and it worked!
Similar problem like Tim: how to (auto-)number the tasks? I don't mind if on remove it isn't actually shown correct, but after commit the task should be written correctly (1, 2, 3, ...) to the database.
1) with either plain or timestamped version numbers, the migrations just care about the order of the numbers..
It seems to be just a difference in how the number is generated.
2) you can disable timestamped migrations by putting this in your environment.rb file:
config.active_record.timestamped_migrations = false
3) If you have a project with a lot of developers who do schema changes, the timestamps will help.
(Meetings will help more! ;-) )
On the other hand you might have a project where you have a larger schema & dependency change,
and you might need to renumber all your migrations to allow a smooth "rake migrate" (up and down).
In this case you'd have to either "make up" fake timestamps for your migrations, or better: go back
to plain version numbers for the migrations.
We have a question on combining subdomains (done with SubdomainFu) and selenium-on-rails. Whenever we access a subdomain we get a same origin policy permissions error. How do we test an application using selenium that uses subdomains? Thanks!
The correct command is :
script/generate authenticated user sessions
NOTE: use plural sessions and not sigular session as you showed in your screen cast. Else you will have the following error when you try to log in:
uninitialized constant SessionsController
This little thing wasted my 3 hours. You should fix it in your screen cast.
@Michael, hmm, I'd have to see the code. Could you email me the user.rb file? ryan AT railscasts DOT com.
Of course not. That would probably solve my problem. :-)
@ryanb, Yes.
def new
@user.email = @user.invitation_key
...
will display the invitation_key in the email field or any other EXCEPT the invitation_key field (hidden or otherwise). Removing the getter/setter fixes this, though.
Ray, how would I accomplish the following:
I have a website 'xyz.com' that dynamically generates sites for social networks and assigns them each a unique subdomain, ie sn1.xyz.com, sn2.xyz.com etc.
The 'site' controller handles all 'xyz.com' requests without the subdomain whereas the 'network' controller handles all requests that have the subdomain present.
How can I conditionally route incoming request based on whether the subdomain is present or not?
@matt, are you using Rails 2.1?
@Philip, thanks for pointing out those details, and I agree with you. There are definitely some extra things you need to consider to polish this up for your site before going into production.
@Michael, did you add invitation_token to the attr_accessible line in your User model?
I'm having the same problem as jeff and kenny above. Conditions on a route don't seem to be working. For instance, the following route:
map.account_root '',
:controller => 'account_root',
:action => 'index',
:conditions => { :subdomain => /.+/ }
keeps on redirecting to itself. The account_root controller tries to redirect to the index page if the current account cannot be found. With the conditions not working, it falls into a redirect loop.
Any ideas?
I should add I'm using Rails 2.1
While I am getting the error shown in the video when trying to register an account with an incorrect invitation ("invitation required"), the video doesn't show a successful registration with the code being passed into the form. I can't get the new User object to pick up the invitation_token. If I can assign it to the a different field (email, for instance) and it shows up, but the getter/setter methods seem to be interfering with it.
This idea occurred to me awhile ago to handle one client's need for a CMS, it probably could use more work, but I pluginized the thing to use across some other applications that were going to need the same sort of setup. Anyone who is interested can grab it here:
http://github.com/neshmi/super_simple_cms/tree/master
Thanks for an excellent episode, one of the most in-depth so far.
If anyone plans to put this in production, there's a couple edge cases to examine. Consider adding an
attr_accessible :recipient_email
to the invitation class (It looks like everything that could be mass-assigned is handled downstream, but its absence makes me nervous), and pulling :invitation_token from the call to User.attr_accessible (if you later add a user update action its value could be crafted: I could be my own grandkid). If a user can be deleted I think their invite codes could re-submit (&so multiply). Also, the presence of multiple routes to the users/new action looks like a problem here, one that should probably be warned about in restful_authentication.
These are just nitpicks for anyone who might build on this excellent foundation. Clearly this episode was already remarkably deep without these ponderous details.
Great screencast, Ryan. Now you left yourself to show us how to write the rake task that sends out the next 100 invites :)
I'm getting stuck on the validations in the Invitation model. Everything was working fine and I've isolated this line as the problem.
(in models/invitation.rb)
validate :sender_has_invitations, :if => :sender
I get this error:
Validations need to be either a symbol, string (to be eval'ed), proc/method, or class implementing a static validation method
Please help!
To everyone getting the "Seeing this instead of the website you expected?" Type errors you need to set the NameVirtualHost directive (http://httpd.apache.org/docs/2.0/mod/core.html#namevirtualhost)
in a global part of the apache conf put:
NameVirtualHost *:80
and then the virtualhost sections should start with
<VirtualHost *:80>
ServerName example.local
…
If you want to run an app on port 80 and 443 I think this would work but I'm not sure
NameVirtualHost *:80
NameVirtualHost *:443
<VirtualHost *:80 *:443>
ServerName example.local
…
Try the apache docs if that doesn't work (http://httpd.apache.org/docs/2.0/vhosts/examples.html)
or somewhat more directly said, kino:
(paraphrasing the Prolegomena-Kant's more 'accessible' work-here) Space and time are the necessary pre-conditions of all future metaphysics.
God, I love being pretentious! (AND pedantic!)
Right, gross simplifications in response to obtuse philosophical musings over, just wanted to offer a belated thanks to you Ryan--this 'cast has just redeemed Rspec for me.
Thanks for this screencast.
I use this searchmethod and the result is presented in combination with wicegrid (http://redmine.wice.eu/api/wice_grid/index.html) and it works great.
The method for making a SQL condition is awesome.
I love you! This is exactly what I've been wanting to implement in my app. Its great that you listen to your readers suggestions. Love uservoce. :)
@mpearce, Thank you! This is a terrific help, and to rest of you guys! Thanks!
A
Any chance you could do a version of this that worked with both :80 and :443? One of the key reasons I want to use Passenger in development is so I can test things like ssl_only filters, which would otherwise require starting two servers and communicating between them.
Congrats Ryan - lots of information clearly presented.
@Alek - it isn't a virtual attribute. Take a look at the API for belongs_to (http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/belongs_to). This also works in has_many and has_and_belongs_to_many.
It is a shorthand way to tell the model that you want to connection to another other model, access it as sender, and look for something in User with a related sender_id column. It does all of that in one line. Good luck.
Thanks Ryan for this great episode.
I love this podcast so much !
@QuBiT and @Carl; Thanks for kind respond and an explanation.
I am still not getting it. Sorry:-(. Is the :sender and the :recipient a virtual attribute? I am not seeing any hook methods pointing to the :recipient and the :sender.
Does the model, in this case User, receives the invitations' id and it knows who the sender is?
@Carl, when you say an alias do you mean it belongs to that particular model...in this case User?
Thanks Guys!
-Alek
@Per Velschow, hmm, it's working for me. Going to pragmatic.tv should redirect you to:
http://www.pragprog.com/screencasts
@khelll, thanks fixed.
QuBiT beat me to it!
@Alek, this structure allows you to call something like @invitation.sender and know who the sender is, and @invitation.recipient and know who the recipient is, even though both are rows in the 'User' table. It's basically like an alias for each relationship.
@Ryan,
thx for this really useful tutorial.
@Alek
Rails would look for a sender and recipient model ... but as ryan did not define a separate sender and recipient model you'll get an error.
for cases where you just want a different name then "invitation.user" and use it for different meanings ryan defined the class attribute to tell rails that invitation.sender and invitation.recipient are user-model objects. hope this helps.
Ryan, the video sizes of this episode r inversed :
Download (28.5 MB, 22:17)
alternative download for iPod & Apple TV (39.3 MB, 22:17)
I can't tell you how grateful I am for this: I spent weeks beating my head against various search options, and none of them seemed to make any sense for my needs until I finally found this, and suddenly I have everything I need!
I do have a question, though. How would I write the conditions for a boolean field? I have several boolean (true/false) fields in my tables, and I want users to be able to check a box in a search field when a field should be true. How should I do this?
Many thanks!!
Thanks for another great screencast.
You mention that you are sponsored by pragmatic.tv and I've tried several times to go there with no luck. Do you know what's up (or down) with their site?
Ryan:
Thanks for a terrific podcast again.
I have a question with regard to associations in the invitation model. Sorry to be a bore, but I am not getting this relationship at all;
belongs_to :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
How does a :sender and a :recipient relate to a class 'User'? Is it through virtual attr? I just can see this connection.
Thanks Ryan.
-Alek
@Ryan Bates: Aha, I see. Didn't recognize it. Thanks.
Once again, great stuff. I began with rails around new years 2007/8 and most of the stuff here have inspired my code and my own little conventions to the better.
@Aerpe, that is generated by restful_authentication. I believe those are just 3 modules they use to handle the authentication.
I am using the Rails 1.2.3, and follow the instruction that clouder said. But it looks like I still miss the dynamic_states.js, even I have correct output in http://localhost:3000/javascripts/dynamic_states. Could someone give any suggestion? Thanks!
Very nice railscast!
Sorry if this is a little off-topic but I noticed you've done something nifty with the authentication system.
include Authentication
include Authentication::ByPassword
include Authentication::ByCookieToken
Is that child classes in the authentication.rb file to give it more flexibility?
Kind regards
Aerpe
In my application I would like to automatically number my tasks and display the number on the page. So far all of my attempts have resulted in the same number for all lines after the first, e.g. 1, 2, 2, 2.
In my task model:
@@line_no = 1
def initialize(attributes = nil)
super
unless line_no?
self.line_no = @@line_no
@@line_no += 1
end
end
Ideas?
Hi Ryan, I was wondering, what do you use to generate the 'Previous' and 'Next' links that we see above?
Thanks in advance,
-Conrad
I was thinking about the best way to run a daemon to reindex TS at a certain interval. Would it make sense to use the daemon gem in an initializer to kick off this process?
@Michael Graff - I think that wildcard for subdomains is the best solution. For apps like basecamp, we have to authorize usera for some domain just at the begining when he is loggin and save subdomain it session. This better solution, dont you think?
@chris ("why not just leave the argument to the lambda as "t" and then in the proc use "t || 2.weeks.ago" ?"):
It's so you can leave the arg out -- it fakes an optional parameter.
See:
http://pastie.org/258863
Okay, I think I found the problem.
The match_mode => :boolean ignores all field weighting, but match_mode => :extended honors them. This is a bit puzzling, since Extended seems to be just like Boolean, but with even more query features. Extended lets you use boolean ORs and NOTs, without losing the relevancy rankings.
Here's where Sphinx says it does that:
http://sphinxsearch.com/doc.html#weighting
And here's a code sample:
--- In app/models/article.rb
define_index block
...
# Declare a default relevancy table, which can be overridden at search
set_property :field_weights => { :title => 3, :subtitle => 2 }
...
end
--- In app/controllers/article_controller.rb
...
# Grab a page-load of articles, using title-centric field weights.
@articles = Article.search query_string,
:include => [:author, :comments], :match_mode => :extended,
:field_weights => { :title => 10, :subtitle => 6 },
:page => params[:page], :per_page => 20
Great stuff as always thank you very much!
aaah, answered my (and your) question. Any methods you add that you want to be available outside of the protected methods in this class need to be added to the self.included call later in authenticated_system.rb.
Nick, I'm hitting the same problem you are about the defined methods. Would be great if you or someone figured it out...
Only thing i found is this:
Please use Jeremy Kamper's ruby-prof :http://github.com/jeremy/ruby-prof/tree/master
gem sources -a http://gems.github.com
sudo gem install jeremy-ruby-prof
but does not work for me either...
Oops. Forgot to attach my email address to that message.
Great work, Ryan. Your generous contributions of work have saved me a great deal of aggravation ever since I discovered them.
Is there an error in the video?
I have been having trouble getting the :field_weights parameter to behave. I can't find it mentioned in the thinking_sphinx API entries on the various search methods:
http://ts.freelancing-gods.com/rdoc/
The best I can find is this:
http://ts.freelancing-gods.com/rdoc/classes/ThinkingSphinx/Index/Builder.html
Where it says :field_weights is an argument to the set_property method.
This seems to imply that field weighting happens when the index is built, not when the search is performed. I'd rather be able to declare my relevancy preferences at search time (like the video shows), not at index time (like the API seems to say).
Am I missing something here?