In my UserController I have load_and_authorize_resource and
def edit
@user = current_user
end
And of course I get a exception when a non authenticate user try to access to /users/:id/edit because it's trying to load the user in load_and_authorize_resource.
So where is my mistake ? :S
Is it not possible to check the right before loading the ressources into load_and_authorize_resource ?
Anyone have any experience doing dynamic selects menus with very large numbers of option data? I've tried just JS and Ajax and both options are very slow on the first change. My first select has about 700 options, the second over 5000.
I need the same..
<< Is it possible to have a text field associated with each checkbox? What if the form creates an entry in the join table, but also should set a property in the jointable/join object itself? As an example, there is a free form text field for notes on the choice made by marking the checkbox.>>
Thank you
Great plugin! However, I am having trouble using it on a controller without a companion model. For instance, I have a Calendar controller that builds and displays a calendar but there is not Calendar model for CanCan to lock onto. So I'm getting a "uninitialized constant" error when it tries to create a Calendar model.
I realize that I should probably not be calling "load_and_authorize_resource" but I'm not sure how else to get CanCan to secure the controller. Any tips on using CanCan without a model?
I like the idea of declarative authorization and I plan to implement it on my front-end application. However I feel that CanCan makes one incorrect and oversimplifying assumption: that (for example) the :update action applied to an object in one controller is the same as :update applied via a different controller.
Of course I am talking about the case of MyObjectsController vrs Admin::MyObjectsController.
I am sold on using separate Admin:: controllers due to vast differences in the interface for admin/non-admin usage. That leaves me needing to authorize actions based not just on the model and user (as CanCan seems to do,) but also on what controller is selected.
Am I missing something? Have I overlooked a simple way to use CanCan's ability definitions to limit actions by controller?
So what's the point for this? Simply encapsulating validations in a model? In that case, wouldn't it be easy to just no call the save method and that's it? It's surely less code.
As far as validations, would Rails 3 improve this type of code?
Something like this perhaps?
class Recommendation
include ActionModel::Validations
attr_accessor :from_email
validates_presense_of :from_email
end
An overview of some Rails 3 things (like the new routing) might be nice. There has been a frenzy of commits recently. Maybe they are gearing up for a RC, one year exactly from the announcement of the merge...
Thanks for the great screencast, Ryan.
Note:
From Cucumber 0.4.5 and onwards you will also need to install the 'cucumber-rails' gem, or else 'script/generate cucumber' will fail.
@zizo: whatever object you're calling is nil, try adding something like:
@user = User.new
to your controller. That helped me when I had the same error with my @user object.
Hey, I love your site, and the tutorials are so helpful.
I'm trying to implement this project, but I'm running into error after error. I'm just a newbie, could you help me?
Here's the error I'm currently stuck on:
Authlogic::Session::Activation::NotActivatedError in HomepageController#home
You must activate the Authlogic::Session::Base.controller with a controller object before creating objects
Still, I believe this may soon become obsolete with the work being done in the ActiveModel project, which extracts validations, callbacks, etc. from ActiveRecord and ActiveModel.
Generally, I prefer a plain Ruby class whenever I need a tableless model. It's also good practice if you want to move towards NoSQL design and storage.
@Bjarki:
A good reason to store searches in your database might be logging, especially of empty searches (i.e. those returning no results).
Also, you could investigate collaborative filtering and provide automated recommendations based on previous searches.
Another plus comes form the url generated when creating a search. This url could be emailed and reused and you'd know how those visits are all related.
I thought I'd point out James Golick's latest tool - FriendlyORM.
It's similar in concept to what you cover here, but packaged up neatly with a few additional features.
Check it at http://github.com/jamesgolick/friendly
I am doing an application that requires multi-field search, you said in the episode that you always store user submitted information in the database. What would be the reason for storing searches in a database? I am asking because I am struggling with the concept of having table-less search or not.
Hi there,
Great cast again!
Like Ryan, I also researched the topic on table-less models about two months ago. While there are other solutions, I too chose the one Ryan liked most. Here's my implementation:
# Define an abstract base class for Tableless ActiveRecord models:
# and then use it like that:
# class Foo < TablelessModel
# column :bar, :string
# validates_presence_of :bar
# end
class TablelessModel < ActiveRecord::Base
def self.columns
@columns ||= [];
end
# Override the save method to prevent exceptions.
def save(validate = true)
validate ? valid? : true
end
end
I use it in a bit different way though: I have a base model class called TablelessModel and inherit from it whenever needed.
I needed table-less models because in my applications I frequently have some more complicated reports, which need more complex SQL queries. Since the SQL queries etc belong in the models, I started implementing them as (class or instance) methods in the models. But I didn't like cluttering my models with code that sometimes doesn't belong there, like some find_by_sqls needed by some report. So I implemented my models to deal with the DB tables/resources and wherever needed, I implemented table-less models to hold the report SQL queries and other logic.
I'm writing this as a possible use case of this techinque, although my own table-less models often do have to deal with the database, just not with an existing table.
"Not to mention removing the coupling between the database and the code."
You keep mentioning this over and over, but I don't see how the bitmask approach removes the coupling. All it does is introduce a different kind of coupling, one which is much harder to see than going to a join model and roles table: the precise number that contains the bitmask is COMPLETELY coupled with the array entries inside the ROLES constant.
Changing the latter breaks everything, unless you never remove an entry and only strictly append new entries to the end (you mention that).
This is one of those "clever" solutions that will only cause you pain later on when you've forgotten what you did and why (or your teammates will break it for you :-).
What I want to know is if the action name is "update_article" instead of "update", the following code can still work?
<% if can? :update_article, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
hi i wanna ask that
in this program can we show user's article..what i mean when we login can we just see the article who logins..if its possible how we can do it
hi ryan,
first thanks for the cancan.
question, in your example there are multiple blogs/subdomains, can i set up cancan where a user can have different roles depending on the group/blog/subdomain he/she is a member of?
to brute force this, i would have a user, group, and groupmembership table where groupmembership table would contain user_id, group_id, and role_id. can cancan make this easier?
Ok, sorry. After spending some time going through the source I found that I can just define permission_denied on my controller and it will be called and I can do whatever I want! Problem solved!
class ApplicationController < ActionController::Base
around_filter :authorize_redirect
def authorize_redirect
yield
if response.body == "You are not allowed to access this action."
response.redirect('/login', 550)
end
end
end
but the authorization magick has already rendered, so I cannot render or redirect :(
Thanks for doing a screencast on this. I haven't had the time to dig deep into CanCan but from what I saw earlier it seemed very nice. Now, after watching this video it will definitely be my main authorization tool! I really like it's simplicity, productivity and approach to handling authorization.
I tried it out and it works fantastic. I have one question though. I noticed the ability.rb file could become quite long, depending on the amount of roles and models you want to authorize. Do you have any recommendation (or would you not recommend it) to put each "role" in it's own file? Like maybe: lib/roles/user.rb moderator.rb admin.rb etc. and then load them in? If you would separate them, how would you organize this? (just looking for some conventions) ;)
Thanks again.
I am looking forward to using this in my future applications!
Hi, for those who have still problem with paperclip on windows and are still getting error:
"not recognized by the 'identify' command." and the solution: http://blog.jonathanhinson.com/2009/04/27/getting-paperclip-working-in-windows/ does not work:
I've reinstalled ruby with "http://rubyforge.org/frs/download.php/66871/rubyinstaller-1.8.6-p383-rc1.exe", uninstall imagemagick and install imagemagick 6.5.8-6 q16 and nothing more and it works! No more errors.
Hope it helps..
Okay, you made me fall in love with Declarative Authorization, and I got it working. So I have three questions about CanCan.
1.) It strikes me that CanCan is very similar to DA. What are the key 2 differences between CanCan and DA? What does 'heavy' mean?
2.) You showed us two controllers: comments & articles. I would love to see the users controller and see if you are able to use the current_user method there. I had to turn off the auto-model-loading functionality in my user controller when using DA.
3.) In comment 29 of episode 188 Jochen Kempf shared a way to 'control non-action related content'. Does CanCan have a solution for this?
tast bud...
A very similar but easier DSL is http://github.com/AnthonyCaliendo/acts_without_database
Woooo that's THE plugin 2009 ! ;) I love it.
I facing a small problem (for me).
In my UserController I have load_and_authorize_resource and
def edit
@user = current_user
end
And of course I get a exception when a non authenticate user try to access to /users/:id/edit because it's trying to load the user in load_and_authorize_resource.
So where is my mistake ? :S
Is it not possible to check the right before loading the ressources into load_and_authorize_resource ?
Cancan is so great and fast to implement !!! :)
Thanks
Anyone have any experience doing dynamic selects menus with very large numbers of option data? I've tried just JS and Ajax and both options are very slow on the first change. My first select has about 700 options, the second over 5000.
Re: my previous post ( RnR Tom Dec 22, 2009 at 17:41)
A simple solution is available at:
http://wiki.github.com/ryanb/cancan/authorization-for-namespaced-controllers
I need the same..
<< Is it possible to have a text field associated with each checkbox? What if the form creates an entry in the join table, but also should set a property in the jointable/join object itself? As an example, there is a free form text field for notes on the choice made by marking the checkbox.>>
Thank you
Great plugin! However, I am having trouble using it on a controller without a companion model. For instance, I have a Calendar controller that builds and displays a calendar but there is not Calendar model for CanCan to lock onto. So I'm getting a "uninitialized constant" error when it tries to create a Calendar model.
I realize that I should probably not be calling "load_and_authorize_resource" but I'm not sure how else to get CanCan to secure the controller. Any tips on using CanCan without a model?
Or you simply use the activerecord-tableless gem, which does the same basically ;)
Hi Ryan,
There is one issue.
When you are redirecting to PayPal sandbox for Payment, you are not showing the amount which User is going to PAY ?
How can we show the AMOUNT on PayPal site which user is going to PAY ?
Thanks,
Bijesh
Thx from newbee`s. :)
here is lot of console trip n trick in rails
http://madhukaudantha.blogspot.com/2009/12/ruby-on-rails-part-3-console-tips.html
ROLES.index(role) mabye return nil,so:
def roles=(roles)
self.roles_mask = roles.inject(0) do |bit, role|
1 << (ROLES.index(role) || -1) | bit
end
end
def roles
ROLES.select { |role| 1 << ROLES.index(role) & self.roles_mask > 0 }
end
named_scope :with_role, lambda { |role| {:conditions => "roles_mask & #{1 << (ROLES.index(role.to_s) || -1)} > 0"} }
also check out bitmask_attributes: http://github.com/amiel/bitmask_attributes
I like the idea of declarative authorization and I plan to implement it on my front-end application. However I feel that CanCan makes one incorrect and oversimplifying assumption: that (for example) the :update action applied to an object in one controller is the same as :update applied via a different controller.
Of course I am talking about the case of MyObjectsController vrs Admin::MyObjectsController.
I am sold on using separate Admin:: controllers due to vast differences in the interface for admin/non-admin usage. That leaves me needing to authorize actions based not just on the model and user (as CanCan seems to do,) but also on what controller is selected.
Am I missing something? Have I overlooked a simple way to use CanCan's ability definitions to limit actions by controller?
So what's the point for this? Simply encapsulating validations in a model? In that case, wouldn't it be easy to just no call the save method and that's it? It's surely less code.
Woops... didn't read all the comments. The original author already pointed this out.
Or you could use:
http://github.com/remvee/active_form
Which is the same thing sitting conveniently in your /lib
plus its properly tested!
thanks for the episode.
great!!!(:
As far as validations, would Rails 3 improve this type of code?
Something like this perhaps?
class Recommendation
include ActionModel::Validations
attr_accessor :from_email
validates_presense_of :from_email
end
An overview of some Rails 3 things (like the new routing) might be nice. There has been a frenzy of commits recently. Maybe they are gearing up for a RC, one year exactly from the announcement of the merge...
Thanks for the great screencast, Ryan.
Note:
From Cucumber 0.4.5 and onwards you will also need to install the 'cucumber-rails' gem, or else 'script/generate cucumber' will fail.
@zizo: whatever object you're calling is nil, try adding something like:
@user = User.new
to your controller. That helped me when I had the same error with my @user object.
Hey, I love your site, and the tutorials are so helpful.
I'm trying to implement this project, but I'm running into error after error. I'm just a newbie, could you help me?
Here's the error I'm currently stuck on:
Authlogic::Session::Activation::NotActivatedError in HomepageController#home
You must activate the Authlogic::Session::Base.controller with a controller object before creating objects
Any suggestions?
@Ryan:
Thanks for the episode!
Still, I believe this may soon become obsolete with the work being done in the ActiveModel project, which extracts validations, callbacks, etc. from ActiveRecord and ActiveModel.
Generally, I prefer a plain Ruby class whenever I need a tableless model. It's also good practice if you want to move towards NoSQL design and storage.
@Bjarki:
A good reason to store searches in your database might be logging, especially of empty searches (i.e. those returning no results).
Also, you could investigate collaborative filtering and provide automated recommendations based on previous searches.
Another plus comes form the url generated when creating a search. This url could be emailed and reused and you'd know how those visits are all related.
Hope that makes sense.
Ryan - another great screencast - thanks!
I thought I'd point out James Golick's latest tool - FriendlyORM.
It's similar in concept to what you cover here, but packaged up neatly with a few additional features.
Check it at http://github.com/jamesgolick/friendly
Nice quick tip.
very useful screencast. thanks.
I get : Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id.
I can't find how solve this problem.
Ryan, we are waiting for MongoDB railscast :) Please make us happy!
Thanks for covering this, Ryan. Another great episode :-) Keep up the good work!
Hello Ryan
great episode as always! :)
I am doing an application that requires multi-field search, you said in the episode that you always store user submitted information in the database. What would be the reason for storing searches in a database? I am asking because I am struggling with the concept of having table-less search or not.
Almost exactly the same but also does the before and after callbacks:
http://github.com/remvee/active_form
:member => {:recommend => [:any]}
No need for table, model, controller. Just a little action to the articles controller.
Hi there,
Great cast again!
Like Ryan, I also researched the topic on table-less models about two months ago. While there are other solutions, I too chose the one Ryan liked most. Here's my implementation:
# Define an abstract base class for Tableless ActiveRecord models:
# and then use it like that:
# class Foo < TablelessModel
# column :bar, :string
# validates_presence_of :bar
# end
class TablelessModel < ActiveRecord::Base
def self.columns
@columns ||= [];
end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
# Override the save method to prevent exceptions.
def save(validate = true)
validate ? valid? : true
end
end
I use it in a bit different way though: I have a base model class called TablelessModel and inherit from it whenever needed.
I needed table-less models because in my applications I frequently have some more complicated reports, which need more complex SQL queries. Since the SQL queries etc belong in the models, I started implementing them as (class or instance) methods in the models. But I didn't like cluttering my models with code that sometimes doesn't belong there, like some find_by_sqls needed by some report. So I implemented my models to deal with the DB tables/resources and wherever needed, I implemented table-less models to hold the report SQL queries and other logic.
I'm writing this as a possible use case of this techinque, although my own table-less models often do have to deal with the database, just not with an existing table.
Very cool. I'm playing with mongodb on a new project at the moment, any chance you plan on looking into any NoSQL stuff?
Thanks again Ryan!
Realy a great cast !
Why not updated your cast #124 (Beta invitation) for authlogic ? :)
And what's about a other onem "How to add a validation email for authlogic" ? Would be great.
So any way, thanks a lot for your cast !
"Not to mention removing the coupling between the database and the code."
You keep mentioning this over and over, but I don't see how the bitmask approach removes the coupling. All it does is introduce a different kind of coupling, one which is much harder to see than going to a join model and roles table: the precise number that contains the bitmask is COMPLETELY coupled with the array entries inside the ROLES constant.
Changing the latter breaks everything, unless you never remove an entry and only strictly append new entries to the end (you mention that).
This is one of those "clever" solutions that will only cause you pain later on when you've forgotten what you did and why (or your teammates will break it for you :-).
What I want to know is if the action name is "update_article" instead of "update", the following code can still work?
<% if can? :update_article, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
hi i wanna ask that
in this program can we show user's article..what i mean when we login can we just see the article who logins..if its possible how we can do it
Ryan B has a set of sample code for this on github:
http://github.com/ryanb/complex-form-examples
This goes into more detail including show, index, edit, etc.
hi ryan,
first thanks for the cancan.
question, in your example there are multiple blogs/subdomains, can i set up cancan where a user can have different roles depending on the group/blog/subdomain he/she is a member of?
to brute force this, i would have a user, group, and groupmembership table where groupmembership table would contain user_id, group_id, and role_id. can cancan make this easier?
thanks!
Ok, sorry. After spending some time going through the source I found that I can just define permission_denied on my controller and it will be called and I can do whatever I want! Problem solved!
Surely there are much better ways than this:
class ApplicationController < ActionController::Base
around_filter :authorize_redirect
def authorize_redirect
yield
if response.body == "You are not allowed to access this action."
response.redirect('/login', 550)
end
end
end
but the authorization magick has already rendered, so I cannot render or redirect :(
Hi Ryan!
Thanks for doing a screencast on this. I haven't had the time to dig deep into CanCan but from what I saw earlier it seemed very nice. Now, after watching this video it will definitely be my main authorization tool! I really like it's simplicity, productivity and approach to handling authorization.
I tried it out and it works fantastic. I have one question though. I noticed the ability.rb file could become quite long, depending on the amount of roles and models you want to authorize. Do you have any recommendation (or would you not recommend it) to put each "role" in it's own file? Like maybe: lib/roles/user.rb moderator.rb admin.rb etc. and then load them in? If you would separate them, how would you organize this? (just looking for some conventions) ;)
Thanks again.
I am looking forward to using this in my future applications!
Is there a way to customize the message or do a redirect instead of just sending "You are not allowed to access this action." if authorization fails?
Before considering PayPal, consider this:
http://blog.apparentsoft.com/business/124/is-paypal-good-for-your-microisv-business-a-short-paypal-horror-story/
Before considering PayPal, consider this:
http://blog.apparentsoft.com/business/124/is-paypal-good-for-your-microisv-business-a-short-paypal-horror-story/
Before considering PayPal, consider this:
http://blog.apparentsoft.com/business/124/is-paypal-good-for-your-microisv-business-a-short-paypal-horror-story/
Before considering PayPal, consider this: http://blog.apparentsoft.com/business/124/is-paypal-good-for-your-microisv-business-a-short-paypal-horror-story/
Hi, for those who have still problem with paperclip on windows and are still getting error:
"not recognized by the 'identify' command." and the solution: http://blog.jonathanhinson.com/2009/04/27/getting-paperclip-working-in-windows/ does not work:
I've reinstalled ruby with "http://rubyforge.org/frs/download.php/66871/rubyinstaller-1.8.6-p383-rc1.exe", uninstall imagemagick and install imagemagick 6.5.8-6 q16 and nothing more and it works! No more errors.
Hope it helps..
H.
Okay, you made me fall in love with Declarative Authorization, and I got it working. So I have three questions about CanCan.
1.) It strikes me that CanCan is very similar to DA. What are the key 2 differences between CanCan and DA? What does 'heavy' mean?
2.) You showed us two controllers: comments & articles. I would love to see the users controller and see if you are able to use the current_user method there. I had to turn off the auto-model-loading functionality in my user controller when using DA.
3.) In comment 29 of episode 188 Jochen Kempf shared a way to 'control non-action related content'. Does CanCan have a solution for this?