Find account name

I have an accounts table
ACCOUNTS
id
company_name

and a users table
USERS
id
username
password
account_id

I want a page where I display the company_name for the user. So far, I
managed to get the user_id from the session...
<%= session[:user_id] %>

Now, I guess I can use the user_id, to find it's account_id, and then
match the account_id and get the company_name.

I don't know, maybe I'm overcomplicating things. I just managed to get
the user_id and I'm now stuck.

I have an accounts table
ACCOUNTS
id
company_name

and a users table
USERS
id
username
password
account_id

I want a page where I display the company_name for the user. So far, I
managed to get the user_id from the session...
<%= session[:user_id] %>

Now, I guess I can use the user_id, to find it's account_id, and then
match the account_id and get the company_name.

If you have a user in current_user for example then the company is
current_user.company, so the name is current_user.company.name. Such
is the magic of Rails. Watch out for the cas when the user does not
have a company, in which current_user.company will be nil. Check out
the rails guide on ActiveRecord relationships to see how this all
works.

Colin

If you have a user in current_user for example then the company is
current_user.company, so the name is current_user.company.name. Such
is the magic of Rails. Watch out for the cas when the user does not
have a company, in which current_user.company will be nil. Check out
the rails guide on ActiveRecord relationships to see how this all
works.

Thanks! This is what I did...

CONTROLLER
    current_user_id = session[:user_id]
    @current_user = User.find(current_user_id)

TEMPLATE
  <h2><%= @current_user.account.name %></h2>

Seems soo simple but it's not to us newbies.

Simplified it even more...

CONTROLLER
@current_user = User.find(session[:user_id])

TEMPLATE
<h2><%= @current_user.account.name %></h2>

Simplified it even moreeeee for the designer...

CONTROLLER
@company_name = User.find(session[:user_id]).account.name

TEMPLATE
<h2><%= @company_name %></h2>

OK, but did you take heed of my warning in my first reply? Can you
guarantee that a user will always have a company (even in unusual
circumstances)? Add into your automated tests one where the user does
not have a company and see what happens. (Hint, find returns nil if
it cannot find what you are asking for).

Another point, it might be worth providing a method somewhere called
current_user (possibly in application_controller) that does the find,
then you will not need to keep typing the find everywhere you want
current_user.

Colin

OK, but did you take heed of my warning in my first reply? Can you
guarantee that a user will always have a company (even in unusual
circumstances)? Add into your automated tests one where the user does
not have a company and see what happens. (Hint, find returns nil if
it cannot find what you are asking for).

Every time an user is created, the account_id is recorded on its row
too. But sure it's good to have a safety net.

Another point, it might be worth providing a method somewhere called
current_user (possibly in application_controller) that does the find,
then you will not need to keep typing the find everywhere you want
current_user.

Aight! DRYer and DRYer

Another point, it might be worth providing a method somewhere called
current_user (possibly in application_controller) that does the find,
then you will not need to keep typing the find everywhere you want
current_user.

I'm trying to do exactly that, but the app doesn't seem to find the
session if placed on the application controller.

ACCOUNTS_CONTROLLER (works fine)
User.find(session[:user_id]).account.name

APPLICATION_CONTROLLER (error!)
User.find(session[:user_id]).account.name

ERROR
Couldn't find User without an ID

Found something very weird, the log trace reads...

EPRECATION WARNING: Disabling sessions for a single controller has been
deprecated. Sessions are now lazy loaded. So if you don't access them,
consider them off. You can still modify the session cookie options with
request.session_options. (called from
[..]/app/controllers/application_controller.rb:6)

Can you show us the code around the error and how you are calling it?

Colin

Ok, so I made this change: I used find_by_id instead of just find.

APPLICATION CONTROLLER
@company_id = User.find_by_id(session[:user_id]).account.id

ERROR
Routing Error
undefined method `account' for nil:NilClass

I'm not good at routing, but will read about it right now. If you got a
suggestion is very much welcomed.

Colin Law wrote in post #950191:

APPLICATION_CONTROLLER (error!)
User.find(session[:user_id]).account.name

ERROR
Couldn't find User without an ID

Can you show us the code around the error and how you are calling it?

mmm... I think I need some tweaking on the routes file. This is all the
code in my application controller

class ApplicationController < ActionController::Base
  before_filter :authorize

  protect_from_forgery

  @company_name = User.find(session[:user_id]).account.name

  protected

    def authorize
      unless User.find_by_id(session[:user_id])
        redirect_to login_url, :notice => "Please log in"
      end
    end

end

You might be searching for a user before a session is established, as such the session[:user_id] is nil. You may need to revise the position of this statement: @company_id = User.find_by_id(session[:user_id]).account.id in your application_controller. Remember that often the application controller the first to load even when you are just open your application. You may need to add a condition. Something like:
@company_id = User.find_by_id(session[:user_id]).account.id if session[:user_id]

A General Note:

Personally, I would not recommend writing User.find_by_id(session[:user_id]).account.id although Rails natually allows for this short cut. For testing sake (or whether you call it bug hunt), I would find the user first and search for the user’s account. In that way I will be able to test for the avaliabilty of the user and the availability of the account separately. I should say, despite that “every time an user is created, the account_id is recorded on its row too”, bugs are are bugs, they always bug. Anything can happen midway. So consider revising that statement. This is a personal preference, based on my experience. It is subject to comments and criticisms.

Happy coding.

For testing sake (or whether you call it bug hunt),
I would find the user first and search for the user's account. In that way
I will be able to test for the avaliabilty of the user and the
availability of the account separately.

Thanks, ok, so I did this...

APPLICATION CONTROLLER
class ApplicationController < ActionController::Base
  before_filter :authorize

  protect_from_forgery

  @user_id = User.find_by_id(session[:user_id])
  @account_id = @user_id.account.id

  protected

    def authorize
      unless User.find_by_id(session[:user_id])
        redirect_to login_url, :notice => "Please log in"
      end
    end

end

ERROR
Routing Error
undefined method `account' for nil:NilClass

Like the error reads, I think I need to do something on the routes file.
I'm not sure what 'cause I'm a newbie but I'm searching for the answer.

Doing it like that means that it will get executed when the controller
loads, which in production will be only once. You need to put it in a
method of application_controller then call it from your code when you
want to know the result.

Are you using authlogic? If so I am sure the examples of how to use
it include how to do a current_user method.

Colin

Colin Law wrote in post #950219:

protect_from_forgery

@user_id = User.find_by_id(session[:user_id])
@account_id = @user_id.account.id

Doing it like that means that it will get executed when the controller
loads, which in production will be only once. You need to put it in a
method of application_controller then call it from your code when you
want to know the result.

Are you using authlogic? If so I am sure the examples of how to use
it include how to do a current_user method.

So you mean doing something like this in the application controller?
  def current_user
    User.find_by_id(session[:user_id])
  end

I use the user id, the account id, the account name and the account id
in several parts of the application. Everytime I need to access the data
I have to add something like this on each controller method...

class AccountsController < ApplicationController
  # GET /accounts
  # GET /accounts.xml
  def index
    @accounts = Account.all

    @company_id = User.find(session[:user_id]).account.id
    @company_name = User.find(session[:user_id]).account.name
    @company_address_one =
User.find(session[:user_id]).account.address_one
    @company_address_two =
User.find(session[:user_id]).account.address_two
    @company_city = User.find(session[:user_id]).account.city
    @company_state = User.find(session[:user_id]).account.state
    @company_zip = User.find(session[:user_id]).account.zip
    @company_web_address =
User.find(session[:user_id]).account.web_address
    @company_phone_number_office =
User.find(session[:user_id]).account.phone_number_office
    @company_phone_number_fax =
User.find(session[:user_id]).account.phone_number_fax

How can I make the company name available to all views with something
like this... @company_name

Leonel *.* wrote in post #950292:
[...]

So you mean doing something like this in the application controller?
  def current_user
    User.find_by_id(session[:user_id])
  end

That's usually sensible.

I use the user id, the account id, the account name and the account id
in several parts of the application. Everytime I need to access the data
I have to add something like this on each controller method...

class AccountsController < ApplicationController
  # GET /accounts
  # GET /accounts.xml
  def index
    @accounts = Account.all

    @company_id = User.find(session[:user_id]).account.id
    @company_name = User.find(session[:user_id]).account.name
    @company_address_one =
User.find(session[:user_id]).account.address_one
    @company_address_two =
User.find(session[:user_id]).account.address_two
    @company_city = User.find(session[:user_id]).account.city
    @company_state = User.find(session[:user_id]).account.state
    @company_zip = User.find(session[:user_id]).account.zip
    @company_web_address =
User.find(session[:user_id]).account.web_address
    @company_phone_number_office =
User.find(session[:user_id]).account.phone_number_office
    @company_phone_number_fax =
User.find(session[:user_id]).account.phone_number_fax

No, you certainly don't. Since current_user is defined in
ApplicationController, and since all your other controllers inherit from
ApplicationController, all you need in your controller is

@current_user = current_user

and then do @current_user.account.whatever in the view.

How can I make the company name available to all views with something
like this... @company_name

Use a before_filter or the technique I just described.

Best,

So you mean doing something like this in the application controller?
  def current_user
    User.find_by_id(session[:user_id])
  end

That's usually sensible.

Since current_user is defined in
ApplicationController, and since all your other controllers inherit from
ApplicationController, all you need in your controller is

@current_user = current_user

and then do @current_user.account.whatever in the view.

How can I make the company name available to all views with something
like this... @company_name

I tried it, and it does work. But how can I make it work on the
APPLICATION CONTROLLER instead of on an individual controller. Several
views need the account_id, so I would have to repeat myself in several
controllers writing
@company_name = company_name

For example with this code in the application controller...

  def company_id
    @company_id = User.find_by_id(session[:user_id]).account.id
  end
  @company_id = company_id

I get this error...
Routing Error
undefined local variable or method `company_id' for
ApplicationController:Class

Still same error...

APPLICATION CONTROLLER
  @company_id = company_id
  def company_id
    output_id = User.find_by_id(session[:user_id]).account.id
  end

ERROR
Routing Error
undefined local variable or method `company_id' for
ApplicationController:Class

Why would it say the method is undefined, if it ISSSS defined? and why
would it have something to do with the routes if it's just a simple
method and a simple variable?

Leonel *.* wrote in post #955184:

Still same error...

APPLICATION CONTROLLER
  @company_id = company_id
  def company_id
    output_id = User.find_by_id(session[:user_id]).account.id
  end

ERROR
Routing Error
undefined local variable or method `company_id' for
ApplicationController:Class

Why would it say the method is undefined, if it ISSSS defined?

Obviously it wouldn't.

You're defining an instance method, and apparently trying to call it as
if it were a class method. The problem is apparently in the line
@company_id = company_id: since that's outside any method definition,
self is the ApplicationController class, not an instance. You need to
put this line inside an instance method for it to do what you want.

If this is hard to understand, review the semantic and syntactical
distinctions between class methods and instance methods in Ruby.

and why
would it have something to do with the routes if it's just a simple
method and a simple variable?

I don't think it does have to do with routes.

Best,