How to call methods defined in ApplicationController in models
Why would you need such thing? The model should not know about its controllers. Maybe a redesign of your system will be more appropriate in this case.
Here is a link to similar thread.
How to call controller method in model
You should not access to this data inside the model (it is violating the MVC). You would be better to pass it as an argument to the scope:
scope :user_groups,
lambda { |user| where(arel_table(:user_id).eq(user.try(:id) || user) }
And call it like this:
User.user_groups(@current_user) # or you can pass @current_user.id, still works
Note: You can pass either an id (Integer) or a User Object to the user_groups
lambda.
Rails: Calling methods in a model in a different controller
Finally, I got it to work.
I needed to implement service objects using Plain Old Ruby Objects.
For each for the actions, I placed them in a separate service, and then called them in the controllers.
The steps are
- Create a folder under the app directory of the application named
services. - Create individual services for each of the controller actions.
- Call each service that you want on the controller.
That's all.
Calling a method from another controller
You could technically create an instance of the other controller and call methods on that, but it is tedious, error prone and highly not recommended.
If that function is common to both controllers, you should probably have it in ApplicationController
or another superclass controller of your creation.
class ApplicationController < ActionController::Base
def common_to_all_controllers
# some code
end
end
class SuperController < ApplicationController
def common_to_some_controllers
# some other code
end
end
class MyController < SuperController
# has access to common_to_all_controllers and common_to_some_controllers
end
class MyOtherController < ApplicationController
# has access to common_to_all_controllers only
end
Yet another way to do it as jimworm suggested, is to use a module for the common functionality.
# lib/common_stuff.rb
module CommonStuff
def common_thing
# code
end
end
# app/controllers/my_controller.rb
require 'common_stuff'
class MyController < ApplicationController
include CommonStuff
# has access to common_thing
end
How to call ApplicationController methods from ApplicationHelper
Use helper_method
.
By default, methods in ApplicationController
are only accessible inside the Controllers.
Add a method to the ApplicationController
and expose it as a helper method with helper_method
:
class ApplicationController < ActionController::Base
helper_method :foo
def foo
"bar"
end
end
Now the foo
method is accessible to both Controllers and Views.
Rails equivalent of ApplicationController for models
Put the reusable method in some module next to your Dvd class. You can move it in a separate file later.
# app/models/dvd.rb
module CaseInsensitiveSearch
def case_insensitive_search(field, value)
# searching field for value goes here
end
end
class Dvd
end
After extending a class with the module you can use case_insensitive_search on the class. Including the module will make case_insensitive_search an instance method which is not what you want.
class Dvd
extend CaseInsensitiveSearch
end
Dvd.case_insensitive_search("title", "foo")
And of course you can use it inside Dvd class.
class Dvd
def self.search(query)
case_insensitive_search("title", query)
end
end
Dvd.search("foo")
Now when you made sure it works, you will probably want to move it in a separate file and use it across multiple classes. Place it in lib/case_insensitive_search.rb and make sure you have this line in config/application.rb:
config.autoload_paths += %W(#{config.root}/lib)
Now you can require it anywhere you want to use it:
require 'case_insensitive_search'
class Dvd
extend CaseInsensitiveSearch
end
The last thing I'd like to suggest. Create multiple modules with meaningful names. So instead of CommonModel have CaseInsensitiveSearch and so on.
Calling a method from a controller in Rails?
Firstly, let me say that your approach is not that wrong imho. Introducing an extra method which is just an alias for Page.all
is not really needed, or not really an improvement.
But there are definitely better approaches.
I would fix this as follows: in ApplicationController
I would add the method
def get_all_pages
@pages ||= get_all_pages
end
This will make sure that any controller knows that method.
Then, if you are sure, you need it on every page, you can just a before_filter
in your ApplicationController
, but generally, I prefer to write it in the controller itself.
E.g.
class IdeasController < ApplicationController
before_action :get_all_pages
... the rest of your controller ...
end
Also, I would extract your list of pages into a partial, store in under app/views/shared/_pages_list.html.erb
or app/views/pages/_pages_list.html.erb
and then in your application.html.erb
just call to render the partial instead.
The method we called sets the instance variable @pages
, it will be available in the view, so your partial would like:
<ul>
<% @pages.each do |page| %>
<li><%= link_to page.name, page_path(page) %></li>
<% end %>
</ul>
Lastly, for completeness, let me answer how you can make a controller-method available in the view. In a controller write
def get_pages
# ..do something
end
helper_method :get_pages
This will make the method get_pages
available in the view, but only for a controller that was responsible for loading/rendering that view. So if you want it for all views, define this in ApplicationController
. E.g. this is what we generally do when defining current_user
method.
Further improvements/alternatives
if you start to get some more code, extract the code related to the page-list-fetching-and-rendering into a separate module, and include that into your
ApplicationController
. This makes yourApplicationController
more readable.- Note: this is exactly what
concerns
were introduced for, so you can use that, if you are on rails 4
- Note: this is exactly what
a
Page
is its own resource, so you could always create a separatePagesController
and make sure it is responsible for rendering the list, and use ajax to fetch on the pages where it is needed. This is a really nice solution, but also a bit more work (overkill?). But very nicely structured.- This problem, where you have different areas on a page, which each should have their own Controller-Model-View, is exactly what the cells gem gem solves in a very clean way. There is a very good example of rendering a shopping-cart on the page I linked, so you could always check that out.
Rails - helper method in controller available in the model?
You can do something like this to access the instance variable declared in controller from model
class User < ActiveRecord::Base
cattr_accessor :current_user
end
class ApplicationController < ActionController::Base
before_filter :current_user
def current_user
@current_user ||= User.find(session[:user_id])
User.current_user = @current_user
end
end
end
Related Topics
Ruby, Generate a Random Hex Color (Only Light Colors)
How to Make a Ruby Script Using Trollop for Command Line Parsing
Setting a Global Within a Proc
Rotate Bits Right Operation in Ruby
Is There a More Concise Way to Call an Outside Method on a Map in Ruby
Rails Query Timestamp Between Two Hours
Selenium2 Webdriver Ruby => How Click on a Hidden Link
Ruby: Cannot Install Watir Gem on Windows
Is There a Groovy Equivalent of the Ruby Timeout Module
Product Orders Between 2 Users
What Does This Mean in Ruby Language
How to Create a Custom Method for the Rails Console
How to Pass Content to Jekyll Default Converter After Custom Conversion
Fast-Stemmer Installation Problems
How to Change Ruby to Version 1.9.3 (Again) with Rvm
Ruby or Rails Sort on Two/Multiple Date Fields