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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With