Creating common method in application ontroller

hi, guys, I would like to define a common method in the application controller because the other resources will use this method.

Scenario: I have 2 resources: Posts (for blogs) and Coupons.

Common method: is_owner_or_admin( object )

I have defined this method within the application controller as I figured it's akin the base class that the controllers for the resources will inherit from. I'm just testing the syntax call so, please don't look at this from a process design point of view :slight_smile:

application_controller.rb

Scenario: I have 2 resources: Posts (for blogs) and Coupons.

Common method: is_owner_or_admin( object )

I have defined this method within the application controller as I figured it's akin the base class that the controllers for the resources will inherit from.

You might find it makes more sense as a method on the objects themselves - it's a bit more in the spirit of OO this way too, whereas the "common method" in application_controller is a bit imperative.

So you can do stuff like:   coupon = Coupon.new     if coupon.is_owned_or_administered_by(current_user) # no need to put the result of "get_common_user" in an instance variable - and "common_user" is a bit more commonly used     # do your stuff here...   end

So, in posts_controller.rb , I do:

class PostsController < ApplicationController before_filter :authenticate_user!, :except => [:index, :show, :send_message, :get_subcategories]

def show @post = Post.find(params[:id]) :is_owner_or_admin(@post)

Looks like you're reinventing authorization processes - it would save you some time if you looked at Aegis, CanCan and the like...

/home/ct9a/projects/port_over_to_rails3/app/controllers/ posts_controller.rb:20: syntax error, unexpected '(', expecting keyword_end :is_owner_or_admin(@post)

well yes - symbols aren't method calls.

You should really be looking at either doing:   @post.is_owner_or_admined_by(current_user) or   current_user.owns_or_administers(@post) which way round is your choice, and either way can be utilised in the permissions model of your chosen authentication gem.

hi there, Michael,

Good evening :slight_smile:

I'm just trying to figure out how to make functions in the base class (application controller) such that resources/objects inheriting from the base class will be able to use them.

1. I've actually got an existing application which has the method implemented individually (ie. is_owner_or_admin() is being implemented in posts_controller.rb and coupons_controller.rb). 2. the purpose of this method is to return true if the current object is being accessed by its owner/creator OR by an admin user. Hence, I wanted to extract that functionality into a base class (ie. the application controller) and pass that method an object to evaluate. 3. I am trying to port over a rails 2.3.8 application into rails 3. In rails 2.3.8, i was using authlogic but in my attempt to port it over to rails 3, i am using devise. I do not think device would have any functionality as described in the previous point (2) but i might just look at Aegis, CanCan and some others for reference. 4. Your reply on "symbols aren't method calls" is so right :slight_smile:

I think I might have figured out how to solve my initial problem :slight_smile:

Thank you :slight_smile:

Gordon Yeong

hi there, Michael,

Good evening :slight_smile:

I'm just trying to figure out how to make functions in the base class (application controller) such that resources/objects inheriting from the base class will be able to use them.

well, you've done that already - any method you write in application_controller is available to any class that inherits from it.

1. I've actually got an existing application which has the method implemented individually (ie. is_owner_or_admin() is being implemented in posts_controller.rb and coupons_controller.rb).

But what happens when you're not using a controller; maybe when you're at the console, or in a script? - then these methods wouldn't be available. They relate to the objects - so they should (on balance) live there. If you think they should be in the application_controller (or any individual controller) that's probably the old procedural programming habits showing their heads :slight_smile:

3. I am trying to port over a rails 2.3.8 application into rails 3. In rails 2.3.8, i was using authlogic but in my attempt to port it over to rails 3, i am using devise. I do not think device would have any functionality as described in the previous point (2) but i might just look at Aegis, CanCan and some others for reference.

Devise is for authentication (logging in), Aegis & CanCan are for authorization (can a user, logged in or not, do this thing...) - they're very different problem domains.

But what happens when you’re not using a controller; maybe when you’re

at the console, or in a script? - then these methods wouldn’t be

available. They relate to the objects - so they should (on balance)

live there. If you think they should be in the application_controller

(or any individual controller) that’s probably the old procedural

programming habits showing their heads :slight_smile:

yeah, in some ways, that has shown some procedural programming trait (my day job sees me coding in both procedural and OO environments and my arguments to totally be rid of procedural programming have been knocked back strongly :frowning: ).

Yes, that is a valid point but given that the resources I deal with can only work in the web domain as the app i have here is very simple albeit I do deal with applications that have deal with data on and offline (xml file transfers and etc) :slight_smile:

Devise is for authentication (logging in), Aegis & CanCan are for

authorization (can a user, logged in or not, do this thing…) -

they’re very different problem domains.

Yep, you’re right, Michael :slight_smile:

For my own app, I have just simplified it to have 2 types of users (ie. ‘admin’ and ‘regular’ types).

Hence, I done away with using authorization gems as it’s a simple application :slight_smile:

Sweet. Nice discussion. Thank you :slight_smile:

Loving rails since ver 2.3.x and finding sanity in it,

Gordon Yeong :slight_smile:

You don't fix that by still using procedural methods when you're working in Rails :wink:

Demonstrate the efficiencies of following OO methods, and there's no argument. There's very few occasions when a procedural approach is better. The smaller the app, the more important following the design standards is, so you can change it quickly later - no client likes hearing "we'll have to rewrite the whole thing to do that..." when they ask for a little extra functionality to a 'simple' site (I know... I've had to say it in the past! :smiley:

Regards,

Yep, agreed. Using rails and domolicious just reinstates my sanity (ie OO methodology) which I work with after my day job.

Seems what I have done in my rails 2.3.8 application was right all along as in, i declared the method for each resource and called the method within the resource’s object (ie. post.is_owner_or_admin and coupon.is_owner_or_admin) :slight_smile:

Cheers :smiley:

Out of curiosity what should one do if one wants to have a method inherited by all models? Does rails already have a file for adding methods to the model base class? Or do we just ram our methods into ActiveModel and call it a day? I have run into almost the opposite scenario as the thread starter. Mainly with certain integrity checks I’ve needed to perform.

Out of curiosity what should one do if one wants to have a method inherited by all models?

You can monkey patch Object or Class if you really want...

# patch in environment.rb class Object   def your_method     puts "my method is here"   end end

# console

o = AnyObject.new

=> #<AnyObject id: etc>

o.your_method

my method is here => nil

String.your_method

my method is here => nil

Monkey patches are evil.

Can one derive a class for ActiveModel, put the common methods in there, and then derive the models from that? I have not tried it.

Colin

"Evil" is a bit strong :slight_smile:

They can have a place. I've found it invaluable in the past to add a patch for ActiveRecord::Errors to merge two error objects' messages together.

Google seems to indicate that one may simply mixin (Is that the correct Ruby terminology.) parts of ActiveModel into any class as one sees fit. For example:ActiveModel: Make Any Ruby Object Feel Like ActiveRecord If memory about the way inheritance works in Ruby serves me we should be able to do something like that, without even needing to derive from ActiveModel directly. Though in the case of a Rails application one would probably just create a stub class that derives from ActiveRecord::Base stick the common methods in there and then subclass that class since ActiveModel does not include the database related functionality.

hi, Michael:)

they are evil when you have to decommission some gems that are no longer supported and change from one rails 2.3.x-1 to rails 2.3.x. I had that in the past about a year plus… Madness lol