Reputation: 667
Hi I'm hacking around Rails the last 8 months so don't truly understand a number of things. I've seen and used helper methods that set the current_user etc. and am now trying to replicate something similar.
I'm trying to set a global value in the application controller for the current company the user is in. I know I'm doing it wrong but I can't quite figure out how to solve it or even if I'm approaching it correctly. I want it so that when the user clicks on a company, the global variable is set to the id of the company they are in. Then in any other sub-model, if I want info on the company, I use the global variable to retrieve the company object with that id.
The code that's causing the problem is in my navbar in application.html.erb
<li><%= link_to "Company", company_path, :method => :get %></li>
This works when I'm using the companies controller etc. But when I try use any other controller I'm getting the error
ActionController::UrlGenerationError in Employees#index
No route matches {:action=>"show", :controller=>"companies"} missing required keys: [:id]
which as I understand it means it can't render the url because no company id parameter is being passed?
I was trying to hack a helper method I used in another project (for getting the current_user) but have realised that it uses the session to extract the user.id to return a user object. Here's my attempt at the helper method in application_controller.rb
def current_company
@company = Company.find_by_id(params[:id])
end
I'm not able to get the current company from the session so my method above is useless unless the company id is being passed as a parameter.
I've thought about passing the company id on every sub-model method but
So my question is am I approaching this correctly? What's the optimal way to do it? Can I create a helper method that stores a global company id variable that gets set once a user accesses a company and can then be retrieved by other models?
I probably haven't explained it too well so let me know if you need clarification or more info. Thanks for looking.
Edit 1
Made the changes suggested by Ruby Racer and now I have:
application.html.erb
<%unless current_page?(root_path)||current_page?(companies_path)||current_company.nil? %>
<li><%= link_to "Company", company_path, :method => :get %></li>
This is not displaying the link in the navbar, I presume because current_company is nil (the other two unless statements were fine before I added current_company.nil?
I'm setting the current_company in
companies_controller.rb
before_action :set_company, only: [:show, :edit, :update, :destroy, :company_home]
def company_home
current_company = @company
respond_with(@company)
end
application_controller.rb
def current_company=(company)
session[:current_company] = company.id
puts "The current_company has been assigned"
puts params.inspect
end
def current_company
@company = Company.find_by_id(session[:current_company])
puts "The current_company helper has been called"
puts @company
puts params.inspect
end
Am I doing something wrong?
Edit 2
I have no idea why this isn't working. After the above edits, it appears as though the session[:company_id]
is not being assigned so the current_company
helper method is returning nil. I've tried printing the session paramaters puts session.inspect
and can't find any company_id information. Anyone any idea why it isn't assigning the value?
Edit 3
Can't for the life of me figure out what's going wrong. I've tried multiple things including moving the current_company = @company
into the set_company
method in companies_controller.rb
which now looks like this:
def company_home
puts "Test the current company"
puts "#{@company.id} #{@company.name}"
puts params.inspect
end
private
def set_company
@company = Company.find_by_id(params[:id])
if @company.nil?||current_user.organisation_id != @company.organisation.id
flash[:alert] = "Stop poking around you nosey parker"
redirect_to root_path
else
current_company = @company
end
end
The company_home
method is being given a company object (I can see this in the console output below) but the current_company
assignment is just not happening. Here's the console output for reference
Started GET "/company_home/1" for 80.55.210.105 at 2014-12-19 10:26:49 +0000
Processing by CompaniesController#company_home as HTML
Parameters: {"authenticity_token"=>"gfdhjfgjhoFFHGHGFHJGhjkdgkhjgdjhHGLKJGJHpDQs6yNjONwSyTrdgjhgdjgjf=", "id"=>"1"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 6 ORDER BY "users"."id" ASC LIMIT 1
Company Load (0.3ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = 1 LIMIT 1
Organisation Load (0.3ms) SELECT "organisations".* FROM "organisations" WHERE "organisations"."id" = $1 LIMIT 1 [["id", 6]]
Test the current company
1 Cine
{"_method"=>"get", "authenticity_token"=>"gfdhjfgjhoFFHGHGFHJGhjkdgkhjgdjhHGLKJGJHpDQs6yNjONwSyTrdgjhgdjgjf=", "controller"=>"companies", "action"=>"company_home", "id"=>"1"}
Rendered companies/company_home.html.erb within layouts/application (0.1ms)
Company Load (0.6ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" IS NULL LIMIT 1
The current_company helper has been called
{"_method"=>"get", "authenticity_token"=>"gfdhjfgjhoFFHGHGFHJGhjkdgkhjgdjhHGLKJGJHpDQs6yNjONwSyTrdgjhgdjgjf=", "controller"=>"companies", "action"=>"company_home", "id"=>"1"}
CACHE (0.0ms) SELECT "organisations".* FROM "organisations" WHERE "organisations"."id" = $1 LIMIT 1 [["id", 6]]
Completed 200 OK in 280ms (Views: 274.0ms | ActiveRecord: 1.7ms)
As per above, under the line The current_company helper has been called
, there's a blank line where puts @company
should be outputting something. This means the current_company method is returning nothing.
Also, in the company_home
method in the companies_controller, if I change puts "#{@company.id} #{@company.name}"
to puts "#{current_company.id} #{current_company.name}"
an error gets thrown.
Has anyone any idea why the def current_company=(company)
isn't assigning a session parameter? Thanks
Final Edit
I've no idea why, but it appears the problem related to this:
def current_company=(company)
session[:current_company] = company.id
puts "The current_company has been assigned"
puts params.inspect
end
It looks as though this never gets called. I don't understand why as I've never used something like this before.
I'll put my fix in an answer.
Upvotes: 4
Views: 14815
Reputation: 667
Instead of using a helper method to assign a value or search for a company, I've assigned a session variable in the set_company
method in companies_controller.rb
. This can then be accessed around the application
companies_controller.rb
private
def set_company
@company = Company.find_by_id(params[:id])
if @company.nil?||current_user.organisation_id != @company.organisation.id
redirect_to root_path
else
session[:current_company] = @company
current_company = @company
end
end
Upvotes: 0
Reputation: 5740
Ok, you need to do two things.
First thing, you need to assign your company.id
to a session variable
def current_company=(company)
session[:company_id]=company.id
end
Second, your helper method for current_company will be as follows:
def current_company
Company.find_by_id(session[:company_id])
end
This can be nil if there is no session[:company_id]
or if it corresponds to no company. That's ok...
Next, it is quite unlikely to get it working without an id, if you use /companies
both for your index and your show actions.
Now, for your first task. Setting the variable:
controller:companies_controller.rb
def show
# assuming you have a before_action, something like set_company, no need to redo it
current_company=@company # this will set the session variable
end
If you want your navbar to lead to your current_company
, you will need to write:
<% unless current_company.nil? %>
<li><%= link_to "Company", current_company, :method => :get %></li>
<% end %>
I don't know what you want to do if there is no current company, so I just leave it out.
Upvotes: 6