How to Call Methods Defined in Applicationcontroller in Models

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

  1. Create a folder under the app directory of the application named
    services.
  2. Create individual services for each of the controller actions.
  3. 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 your ApplicationController more readable.

    • Note: this is exactly what concerns were introduced for, so you can use that, if you are on rails 4
  • a Page is its own resource, so you could always create a separate PagesController 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



Leave a reply



Submit