Ryan - thank you for these screencasts. They're extremely helpful. I have one question regarding this topic. I'm trying to update a DOM, but the DOM is in javascript so I can't see it in the browser view-source to see if I have the correct id. I can see the javascript that's sent to the browser with firebug, but it's quite indecipherable (to me). Is there any way to view the javascript as html?
Hello,
I have been trrying to make this work but will forms for people ans organisation instead of projects and tasks.
<%fields_for "person[organisation_attributes][]",organisation do |org_form|%>
<div id = "organisation"><%=render :partial=>'organisation_with_index_nil_for_person',:collection=>@person.organisations,:locals=>{:org_form=>org_form}%>
In the fields_for section i am getting an error message "undefined local variable or method organisation."
in my Person model i have
class Person < ActiveRecord::Base
has_and_belongs_to_many :organisations
My Organisation model is as
class Organisation < ActiveRecord::Base
has_and_belongs_to_many :people
Please can anyone help me to figure out the mistake.Have been trying since long.
@ryan
How would one do the call to such an authenticated controller from activeresource. How does one pass the request authentification at the reqest time. does that go into the model or is that a step done during the find?
I mean like so:
*model*
class Event < ActiveResource::Base
self.site ="http://localhost:3000/"
end
For those looking for Ryan's ugly hack for the by_date method check it out here:
http://railsforum.com/viewtopic.php?id=3741
I found this today and it presented a clever way to accomplish this functionality. It may not be pretty or rails-ish Ryan, but it gets the job done!
Thanks for all the casts Ryan - I check here when I don't know something, before I check anyway else. I subscribed today to your feed in iTunes, so I'll make sure I get the votes going.
Here you've done:
add_column_to_table, but elsewhere they say do:
AddColumnToTable
in the migration script.
Also, could you discuss references keyword when used in this situation. It doesn't seem to work in conjuction with the add/remove migrations, but does work in the initial scaffold command.
@Eric, this should work in Rails 1.2 as well. The only difference is the file in "initializers" directory won't be loaded automatically. You'll have to either manually load it or place it directly in environment.rb.
Good vid but don't follow the advice about not pluralising your sessionscontroller - rails is notorious for throwing up bugs when it comes to this kind of thing, and it took me several hours to work out why there were weird 'uninitialized constant SessionsController' errors. Totally bad advice.
Nice episode that demonstrates Ruby knowledge and skills. As Ruby is a great language for DSL, it has great features to expand Rails. Just show us more like that.
What if the user has multiple browser windows open to the site? Are they now sharing the same session information, even though they should be considered two different sessions?
Everyone getting the "is not allowed as an instance variable name" error: one possibility is that you're feeding fields_for a nil object as the second argument.
The error message is really misleading, since it has nothing to do with the format of the string you're sending. My guess is that, failing the existence of the object, it tries to transform the string into a variable.
I've always wanted to find a way to not have any passwords in my SVN. But, even with your suggestion, how would I do that when e.g. using deprec (the cap deply taks available at deprec.org)?
The only solution I can see is completely ignoring the config.yml in the SVN and keeping it far away from the app directory (as something like /var/www/apps/appname/current is replaced on each deploy). So, should one put it in /etc/ instead, or is there a nicer solution?
What happened to Convention over Configuration? So if you have a bunch of lil configuration options, whats the point from deviating away from what Rails gives us for configuration options? I'm lost...
This does a good job at explaining not to do this, too bad I missed it (or it wasnt around) when I got my first auth plugin that stored the user in the db.
Anyway, for those of us that do have the user in the session (and cant easily remove it), what are the rules for how active record interacts with the session.
For example if I set a attribute on my session object and save it, it will be the same in both the session and the active record right?
If I store a user object in the session, will it store related objects in the session also, how far will it traverse the object tree?
For '... is not allowed as an instance variable name' I ended up using this for each field and removing it from the fields_for call completely. I'm running Rails 2.0.2.
I'm shocked, i'll have to see it another 2 or more times before understand it all. But it's really nice, and i'll use this approach for some good refactoring in the code :)
Very cool, i think i've to change a lot of stuff. i've done a really bad thing (the permalink contains all the id-permalink stuff, and then i changed the routes.rb to use it instead of the id... a really bad thing :) )
Keep up the great work guys! As I continue my education with rails (and ruby) into the 2.0 transition, your railscasts are a breath of fresh air in the often dark tunnel I call rails newbieness of which I suffer greatly.
Or even better you can also show a notice, so will be:
def index
if params[:search]
@projects = Project.find(:all, :conditions => ["name LIKE ?", "%#{params[:search]}%"])
if @projects.size.zero?
flash[:notice] = "No result found"
@projects = Project.find(:all)
end
else
@projects = Project.find(:all)
end
end
def index
if params[:search]
@projects = Project.find(:all, :conditions => ["name LIKE ?", "%#{params[:search]}%"])
if @projects.size.zero?
@projects = Project.find(:all)
end
else
@projects = Project.find(:all)
end
end
if i add the first line:
APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]
then:
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
Exiting
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `load': syntax error on line 7, col 11: `' (ArgumentError)
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `load'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:144:in `load_file'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:143:in `open'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:143:in `load_file'
from /Users/michaelvoigt/Documents/private/projects/kraeftemessen/trunk/kraeftemessen/rails/kraeftemessen/config/environment.rb:84
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /Library/Ruby/Gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require'
... 23 levels...
from /Library/Ruby/Gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require'
from script/server:3
I'd add a string "level" column to each user. In that you could save for e.g "Writer", "Reader", "Editor", "Admin", and others you need. Then when you just need to add some controls as you do for the admin area. For e.g.
if current_user.writer?
<show form to write>
end
and the writer? method would be like this:
def writer?
current_user.level == "Writer"
end
Be aware of the level, if the user can choose her level pay attention she don't select the Admin level.
He's using a REST way...
In the routes.rb he set map.resources :sessions
With this he can do a post request on sessions_path (or sessions_url) to do a create. With a delete request on an id session_url(id), :method => :delete call for a destroy and session_url(id), :method => :put is a call for update.
For more info have a look here http://api.rubyonrails.com/classes/ActionController/Resources.html
@Phillip:
Probably the easier way to do that with a table is to use something like this:
<table><tr>
<% @tasks.in_groups_of(4, false) do |row_tasks| %>
<td>
<% for task in row_tasks %>
<p><%= task.name %></p>
<% end %>
</td>
<% end %>
</tr></table>
(I don't know if it's possible to have each element in a cell, probably yes, but will be more complicated)
i do something very similar to this with my .yml files. if you don't want to commit your username/password in your repository like me, you can use a capistrano task like
task :create_config_config do
set :a_username, Capistrano::CLI.password_prompt('admin_username: ')
set :a_password, Capistrano::CLI.password_prompt('admin_password: ')
contents = render_erb_template(File.dirname(__FILE__) + "/templates/config.yml.erb")
put contents, "#{shared_path}/config/config.yml"
end
When using this is there anything different for Rails 2.0.2 (specifically cookie-based session stores)?
Also, I keep getting 'uninitialized constant OpenID::Store'
I looked at http://drnicwilliams.com/2007/07/26/sample-app-rails-multiple-openids-per-user/
and there is a 'gems' directory in vendor which contains ruby-openid-x.x.x and there's 'stores.rb' inside.
hi,
can somebody tell me how the create action is called? in the screencast i just see a:
<% form_tag sessions_path do -%>
no mention of a create anywhere. I know how to fix this myself but i am just wondering how this works in the screencast without any mention of 'create' anywhere.
Your screencast helped a lot solving the problem which I previously solved in a rather complicated manner.
I have a question to ask.
What if my project has 3 different type of tasks ->
A task can be either a
- File
-File Upload(Model : File)
-HTML ADD (Model : File)
-Link (Model : Link)
Now, I want three links at the bottom of the project to add file/html/link where html and file use the same model.
Now, in case of add html i want to redirect to a WYSYWIG editor(displaying it in the same page could get dirty) from where user can write the html and save it. I think a popup would be helpful in this case. And, then saving would redirect to the same form, from where you can save the project. Any heads-up on how this can be implemented ?
+1 for screencast on this.
You say to only store simple objects in the session like arrays, hashes, integers, etc. But what about complex objects that don't need to keep in sync with the db and are temporary, like a shopping cart class? I've been storing the entire shopping cart in the session for a while now and I think the only downside is that the Marshaled object can get pretty big, requiring a long text db column, that and if you make any changes to the shopping cart class you of course have to kill any open sessions. Now that rails 2.0 is no longer storing sessions in the db and file system, is there a size constraint on how much data can be kept in a cookie? Any advice?
wow, nice screencast. I love the way you can hack ruby.
I'm using your name because I wondered wether its possible without being the admin, sorry. Just being curious!
[admin edit] Yep, its possible - probably something I should fix...
really needed to work with the new concepts in rails 2.0.2
Ah..nice. Thanks, but I'm getting this error on my setup:
logger_additions.rb:1: warning: toplevel constant Logger referenced by ActiveRecord::Base::Logger
I removed the line:
logger = ActiveRecord::Base.logger
and changed to:
def RAILS_DEFAULT_LOGGER.debug_variables(bind)
...
end
Hope it'll help others with similar issue.
Ryan - thank you for these screencasts. They're extremely helpful. I have one question regarding this topic. I'm trying to update a DOM, but the DOM is in javascript so I can't see it in the browser view-source to see if I have the correct id. I can see the javascript that's sent to the browser with firebug, but it's quite indecipherable (to me). Is there any way to view the javascript as html?
I like big tips and I can not lie!!!
Hello,
I have been trrying to make this work but will forms for people ans organisation instead of projects and tasks.
<%fields_for "person[organisation_attributes][]",organisation do |org_form|%>
<div id = "organisation"><%=render :partial=>'organisation_with_index_nil_for_person',:collection=>@person.organisations,:locals=>{:org_form=>org_form}%>
In the fields_for section i am getting an error message "undefined local variable or method organisation."
in my Person model i have
class Person < ActiveRecord::Base
has_and_belongs_to_many :organisations
My Organisation model is as
class Organisation < ActiveRecord::Base
has_and_belongs_to_many :people
Please can anyone help me to figure out the mistake.Have been trying since long.
@ryan
How would one do the call to such an authenticated controller from activeresource. How does one pass the request authentification at the reqest time. does that go into the model or is that a step done during the find?
I mean like so:
*model*
class Event < ActiveResource::Base
self.site ="http://localhost:3000/"
end
*irb*
s=Event.find 989
For those looking for Ryan's ugly hack for the by_date method check it out here:
http://railsforum.com/viewtopic.php?id=3741
I found this today and it presented a clever way to accomplish this functionality. It may not be pretty or rails-ish Ryan, but it gets the job done!
Thanks for all the casts Ryan - I check here when I don't know something, before I check anyway else. I subscribed today to your feed in iTunes, so I'll make sure I get the votes going.
Here you've done:
add_column_to_table, but elsewhere they say do:
AddColumnToTable
in the migration script.
Also, could you discuss references keyword when used in this situation. It doesn't seem to work in conjuction with the add/remove migrations, but does work in the initial scaffold command.
@Eric, this should work in Rails 1.2 as well. The only difference is the file in "initializers" directory won't be loaded automatically. You'll have to either manually load it or place it directly in environment.rb.
Thanks a ton for your screencasts!
Does this only apply to Rails 2.0 or does this also work in 1.8.6?
I've found a patch from here(http://dev.rubyonrails.org/ticket/10604 ) and downloaded it.
after that,moved to
vendor/plugins/open_id_authentication
$ patch -p0 < update_openid_plugin_to_ruby_openid_2.diff
It worked!
Well, I decided that I needed an actual in_vertical_groups_of. I made a post over at ruby-forum about it.
http://www.ruby-forum.com/topic/137230
Peace,
Phillip
Good vid but don't follow the advice about not pluralising your sessionscontroller - rails is notorious for throwing up bugs when it comes to this kind of thing, and it took me several hours to work out why there were weird 'uninitialized constant SessionsController' errors. Totally bad advice.
Nice episode that demonstrates Ruby knowledge and skills. As Ruby is a great language for DSL, it has great features to expand Rails. Just show us more like that.
Thanks and Happy New year!
that was sick, nice script-foo. i have always wanted to do what eval does, just didnt know how to do it or what to call it.
I was just looking for something on this subject last night! One more awesome screencast. Keep it up!
It is hard to thank you enough for these wonderful screencasts. Thanks and have a wonderful 2008!
so I've learned one more thing in 2007 about ruby and rails, just great, thx!
thx 4 all in this year and a happy new year 2008 to Ryan and to all those who are watching this!
What if the user has multiple browser windows open to the site? Are they now sharing the same session information, even though they should be considered two different sessions?
With HTTP Basic authentication, can you also use OpenID? A screencast on that would be tremendously helpful. Thanks for the great work!
Everyone getting the "is not allowed as an instance variable name" error: one possibility is that you're feeding fields_for a nil object as the second argument.
The error message is really misleading, since it has nothing to do with the format of the string you're sending. My guess is that, failing the existence of the object, it tries to transform the string into a variable.
I've always wanted to find a way to not have any passwords in my SVN. But, even with your suggestion, how would I do that when e.g. using deprec (the cap deply taks available at deprec.org)?
The only solution I can see is completely ignoring the config.yml in the SVN and keeping it far away from the app directory (as something like /var/www/apps/appname/current is replaced on each deploy). So, should one put it in /etc/ instead, or is there a nicer solution?
Hi,
Is there a way of using find_all_by type methods to replace conditions with wildcards in using LIKE or REGEXP?
Thanks very much for your help
What happened to Convention over Configuration? So if you have a bunch of lil configuration options, whats the point from deviating away from what Rails gives us for configuration options? I'm lost...
thanks for this railscast Ryan!
This does a good job at explaining not to do this, too bad I missed it (or it wasnt around) when I got my first auth plugin that stored the user in the db.
Anyway, for those of us that do have the user in the session (and cant easily remove it), what are the rules for how active record interacts with the session.
For example if I set a attribute on my session object and save it, it will be the same in both the session and the active record right?
If I store a user object in the session, will it store related objects in the session also, how far will it traverse the object tree?
thanks
Joel
For '... is not allowed as an instance variable name' I ended up using this for each field and removing it from the fields_for call completely. I'm running Rails 2.0.2.
f.hidden_field :id, { :name => 'foo[bar][][id]' }
Works, but is annoyingly repetitive.
I'm shocked, i'll have to see it another 2 or more times before understand it all. But it's really nice, and i'll use this approach for some good refactoring in the code :)
Very cool, i think i've to change a lot of stuff. i've done a really bad thing (the permalink contains all the id-permalink stuff, and then i changed the routes.rb to use it instead of the id... a really bad thing :) )
Keep up the great work guys! As I continue my education with rails (and ruby) into the 2.0 transition, your railscasts are a breath of fresh air in the often dark tunnel I call rails newbieness of which I suffer greatly.
Or even better you can also show a notice, so will be:
def index
if params[:search]
@projects = Project.find(:all, :conditions => ["name LIKE ?", "%#{params[:search]}%"])
if @projects.size.zero?
flash[:notice] = "No result found"
@projects = Project.find(:all)
end
else
@projects = Project.find(:all)
end
end
@Some1
You can do something like:
def index
if params[:search]
@projects = Project.find(:all, :conditions => ["name LIKE ?", "%#{params[:search]}%"])
if @projects.size.zero?
@projects = Project.find(:all)
end
else
@projects = Project.find(:all)
end
end
I have foregot the require 'yaml', SORRY!
if i add the first line:
APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]
then:
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
Exiting
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `load': syntax error on line 7, col 11: `' (ArgumentError)
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:133:in `load'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:144:in `load_file'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:143:in `open'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/yaml.rb:143:in `load_file'
from /Users/michaelvoigt/Documents/private/projects/kraeftemessen/trunk/kraeftemessen/rails/kraeftemessen/config/environment.rb:84
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /Library/Ruby/Gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require'
... 23 levels...
from /Library/Ruby/Gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require'
from script/server:3
@Vincent
I've tried both in the irb and the second one doesn't work:
irb(main):018:0> def full_name(=name)
irb(main):019:1> end
SyntaxError: compile error
(irb):18: syntax error, unexpected '=', expecting ')'
The other (def full_name=(name)) works without problems
@jocelyn
I'd add a string "level" column to each user. In that you could save for e.g "Writer", "Reader", "Editor", "Admin", and others you need. Then when you just need to add some controls as you do for the admin area. For e.g.
if current_user.writer?
<show form to write>
end
and the writer? method would be like this:
def writer?
current_user.level == "Writer"
end
Be aware of the level, if the user can choose her level pay attention she don't select the Admin level.
@Mieg
He's using a REST way...
In the routes.rb he set map.resources :sessions
With this he can do a post request on sessions_path (or sessions_url) to do a create. With a delete request on an id session_url(id), :method => :delete call for a destroy and session_url(id), :method => :put is a call for update.
For more info have a look here http://api.rubyonrails.com/classes/ActionController/Resources.html
@William Monk
You just need a reverse :)
<% @task_months.keys.sort.reverse.each do |month| %>
@Phillip:
Probably the easier way to do that with a table is to use something like this:
<table><tr>
<% @tasks.in_groups_of(4, false) do |row_tasks| %>
<td>
<% for task in row_tasks %>
<p><%= task.name %></p>
<% end %>
</td>
<% end %>
</tr></table>
(I don't know if it's possible to have each element in a cell, probably yes, but will be more complicated)
Mo Rashed: Thanks for the tip! I actually have :
def to_param
"#{id}-#{title.gsub(/[^a-z1-9]+/i, '-')}.html"
end
Having .html makes it more search engine friendly.
Why do we need to use this method when Rails 2.0 has initializers? I can declare all my configuration under initializers directory, right?
I could have s3_config, mailer settings etc in its own initializer.
I've been doing this for a while, too. This is what I do to get ERB in my YAML (like in fixtures). It also uses ostruct as described by thom above.
require 'ostruct'
raw_config = File.read("#{RAILS_ROOT}/config/config.yml")
erb_config = ERB.new(raw_config).result
config = YAML.load(erb_config)[RAILS_ENV]
Site = OpenStruct.new(config)
I can now do stuff like
foo_path: <%= RAILS_ROOT %>/tmp/foo
Is there a difference between setting method headers like this:
def full_name=(name)
and
def full_name(=name).
Thank you!
i do something very similar to this with my .yml files. if you don't want to commit your username/password in your repository like me, you can use a capistrano task like
task :create_config_config do
set :a_username, Capistrano::CLI.password_prompt('admin_username: ')
set :a_password, Capistrano::CLI.password_prompt('admin_password: ')
contents = render_erb_template(File.dirname(__FILE__) + "/templates/config.yml.erb")
put contents, "#{shared_path}/config/config.yml"
end
I'm using the following in `config/initializers/app_config.rb`:
require 'ostruct'
require 'yaml'
# Load application configuration
config = OpenStruct.new(YAML.load_file("#{RAILS_ROOT}/config/application.yml"))
::AppConfig = OpenStruct.new(config.send(RAILS_ENV))
Now I can use it in my application like this
AppConfig.perform_authentication
When using this is there anything different for Rails 2.0.2 (specifically cookie-based session stores)?
Also, I keep getting 'uninitialized constant OpenID::Store'
I looked at http://drnicwilliams.com/2007/07/26/sample-app-rails-multiple-openids-per-user/
and there is a 'gems' directory in vendor which contains ruby-openid-x.x.x and there's 'stores.rb' inside.
Still getting the error, any ideas?
hi,
can somebody tell me how the create action is called? in the screencast i just see a:
<% form_tag sessions_path do -%>
no mention of a create anywhere. I know how to fix this myself but i am just wondering how this works in the screencast without any mention of 'create' anywhere.
BTW i am a big fan of the railscasts, thanks!
Ryan,
When you search about other word not in the list, it will show you blank page.
How I can avoid blank results?
Your advice please.
Your screencast helped a lot solving the problem which I previously solved in a rather complicated manner.
I have a question to ask.
What if my project has 3 different type of tasks ->
A task can be either a
- File
-File Upload(Model : File)
-HTML ADD (Model : File)
-Link (Model : Link)
Now, I want three links at the bottom of the project to add file/html/link where html and file use the same model.
Now, in case of add html i want to redirect to a WYSYWIG editor(displaying it in the same page could get dirty) from where user can write the html and save it. I think a popup would be helpful in this case. And, then saving would redirect to the same form, from where you can save the project. Any heads-up on how this can be implemented ?
+1 for screencast on this.
You say to only store simple objects in the session like arrays, hashes, integers, etc. But what about complex objects that don't need to keep in sync with the db and are temporary, like a shopping cart class? I've been storing the entire shopping cart in the session for a while now and I think the only downside is that the Marshaled object can get pretty big, requiring a long text db column, that and if you make any changes to the shopping cart class you of course have to kill any open sessions. Now that rails 2.0 is no longer storing sessions in the db and file system, is there a size constraint on how much data can be kept in a cookie? Any advice?