RAILS: Accessing the current controller from inside a lib class - ruby-on-rails

In my controller I have:
#list = ListView.new()
The template contains:
= #list.render
And in lib/list_view.rb I have:
class ListView
def render
controller_name.inspect
end
end
When I run this code I get a undefined local variable or method 'controller_name' error. I'm still new to Rails but I'm sure there's a way to do this as will_paginate does it here: https://github.com/mislav/will_paginate/blob/master/lib/will_paginate/view_helpers/action_view.rb#L92
It does appear that will_paginate might be a module and not a class? I'm missing something...

You probably want to do something like:
class ListView
def initialize(controller)
#controller = controller
end
def render
controller_name.inspect
end
private
def controller() #controller end
def controller_name
controller.controller_name
end
end
Then in your controller, do:
#list = ListView.new(self)
I'm guessing that you're going for the presenter pattern. If so, you'll want to watch Ryan Bates great RailsCast on the subject where you'll learn how to get your presenter to actually render something.

Related

Decorator/Presenter/Exhibits and helpers

I have read:
Concerns, Decorators, Presenters, Service Objects, Helpers, Help me Decide
and trying to figure out the difference between presenters, view objects, decorators, exhibits, and helpers.
I have multiple active record models that I need to display in a view using the show method.
Examples of what I need to display are:
ClassModule SomeTypeOfPattern
def name
User.name
end
def car_name
User.car.listing.car_name
end
def car
User.car
end
def car_marketing
User.car.marketing
end
# AND 20 to 30 other similar delegations/methods from 4 related tables
end
So if I delegate these relationships, what should the class/module be called? A presenter? Decorator? View Object? I am so confused by all these terms, but want to follow convention.
The example you are showing looks like a Presenter to me.
A presenter is an object that presents other information with its own interface.
If you changed what you have just a little, you could use it like this:
presenter
class UserCarPresenter
attr_reader :user
def initialize(user)
#user = user
end
def name
user.name
end
def car_name
user.car.listing.car_name
end
def car
user.car
end
def car_marketing
user.car.marketing
end
end
controller
class CarsController < ApplicationController
def show
#user = UserPresenter.new(user)
end
end
view
<h1><%= #user.name %></h1>
<h2><%= #user.car_name %></h1>

undefined method `content_for' in presenter rails

I am using a presenter for a view in rails to display data which is saved in a yml file. (i18n gem)
This is the controller-
class DocumentsController < ApplicationController
def index
#presenter = DocumentPresenter.new
end
end
This is my view-
= #presenter.viewname
and this is my presenter-
class DocumentPresenter
def viewname
content_for :secondary_nav_title do
t('Documents')
end
end
end
The error says:
undefined method `content_for'
Why doesn't rails recognize content_for in the presenter?
the content_for helper method should not be used in your model as this violates the MVC pattern.
if you must use it, though this is not reccomended, you can add this at the bottom of your model.
def helpers
ActionController::Base.helpers
end
Then to call content_for you would use
class DocumentPresenter
def viewname
helpers.content_for :secondary_nav_title do
t('Documents')
end
end
end

Undenfined local variable or method when the view call a method

I'm trying give a "Welcome Message" to my users with that:
#welcome_controller.rb
class WelcomeController < ApplicationController
def hi
#current_user
if (#current_user)
#welr = '¡Bienvenido' + current_user + ' a nuestra web!'
else
#weli = "¡Bienvenido invitado, no dude en registrarse!"
end
end
end
#hi.html.erb Only the call
<%= hi %>
When I initialize my server the controller give me this message:
undefined local variable or method `hi' for
I have tried many wways of repairing this but I can't.
You need to define hi as a helper_method in your controller. Something like
class WelcomeController < ApplicationController
helper_method :hi
def hi
# your stuff here...
end
end
See http://apidock.com/rails/AbstractController/Helpers/ClassMethods/helper_method for more info
That's not how you use controller methods. In Rails, methods defined on a controller are used to 'set up' the data needed for a particular view, or to handle a given request. They're not supposed to be called directly by a view.
For what you're trying to do, you need to add a helper method to WelcomeHelper. So, assuming you want http://yourapp.dev/welcome/ to output the message above, this is what you'd need:
# app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
def index
# Explicitly defining the `index` method is somewhat redundant, given
# that you appear to have no other logic for this view. However, I have
# included it for the sake of example.
end
end
# app/views/welcome/index.html.erb
<%= greeting %>
# app/helpers/welcome_helper.rb
class WelcomeHelper
# All methods in WelcomeHelper will be made available to any views
# that are part of WelcomeController.
def welcome
if (#current_user)
# You may need to change this to something like `#current_user.name`,
# depending on what #current_user actually is.
'¡Bienvenido' + #current_user + ' a nuestra web!'
else
"¡Bienvenido invitado, no dude en registrarse!"
end
end
end
This article may help you :
Ruby on Rails: Accessing Controller Methods from Your View
Just write:
<% #controller.hi %>

Rails: How to get the model class name based on the controller class name?

class HouseBuyersController < ...
def my_method
# How could I get here the relevant model name, i.e. "HouseBuyer" ?
end
end
This will do it:
class HouseBuyersController < ApplicationController
def index
#model_name = controller_name.classify
end
end
This is often needed when abstracting controller actions:
class HouseBuyersController < ApplicationController
def index
# Equivalent of #house_buyers = HouseBuyer.find(:all)
objects = controller_name.classify.constantize.find(:all)
instance_variable_set("##{controller_name}", objects)
end
end
If your controller and model are in the same namespace, then what you want is
controller_path.classify
controller_path gives you the namespace; controller_name doesn't.
For example, if your controller is
Admin::RolesController
then:
controller_path.classify # "Admin::Role" # CORRECT
controller_name.classify # "Role" # INCORRECT
It's a bit of a hack, but if your model is named after your controller name then:
class HouseBuyersController < ApplicationController
def my_method
#model_name = self.class.name.sub("Controller", "").singularize
end
end
... would give you "HouseBuyer" in your #model_name instance variable.
Again, this makes a huge assumption that "HouseBuyersController" only deals with "HouseBuyer" models.
For namespaces working:
def resource_class
controller_path.classify.constantize
end
The accepted solution did not work for me as my controller and model was namespaced. Instead, I came up with the following method:
def controllers_model
(self.class.name.split('::')[0..-2] << controller_name.classify).join('::')
end
This is not possible if you are using the default MVC, which your code doesn't seem to follow. Your controller seems to be a model but maybe you just got a type there. Anyway, controllers and models are fundamentally separated in Rails MVC so controllers cannot know which model they are associated with.
For example you could have a model named post. This can have a controller posts_controller or could have a controller like articles_controller. Rails only knows about models when you def the actual code in the controller such as
def index
#posts = Post.all
#posts = Article.all
end
In rails standard controllers there is no way to know what the model is.

Where do I put 'helper' methods?

In my Ruby on Rails app, I've got:
class AdminController < ApplicationController
def create
if request.post? and params[:role_data]
parse_role_data(params[:role_data])
end
end
end
and also
module AdminHelper
def parse_role_data(roledata)
...
end
end
Yet I get an error saying parse_role_data is not defined. What am I doing wrong?
Helpers are mostly used for complex output-related tasks, like making a HTML table for calendar out of a list of dates. Anything related to the business rules like parsing a file should go in the associated model, a possible example below:
class Admin < ActiveRecord::Base
def self.parse_role_data(roledata)
...
end
end
#Call in your controller like this
Admin.parse_role_data(roledata)
Also look into using (RESTful routes or the :conditions option)[http://api.rubyonrails.org/classes/ActionController/Routing.html] when making routes, instead of checking for request.post? in your controller.
Shouldn't you be accessing the parse_role_data through the AdminHelper?
Update 1: check this
http://www.johnyerhot.com/2008/01/10/rails-using-helpers-in-you-controller/
From the looks of if you're trying to create a UI for adding roles to users. I'm going to assume you have a UsersController already, so I would suggest adding a Role model and a RolesController. In your routes.rb you'd do something like:
map.resources :users do |u|
u.resources :roles
end
This will allow you to have a route like:
/users/3/roles
In your RolesController you'd do something like:
def create
#user = User.find_by_username(params[:user_id])
#role = #user.roles.build(params[:role])
if #role.valid?
#role.save!
redirect_to #user
else
render :action => 'new'
end
end
This will take the role params data from the form displayed in the new action and create a new role model for this user. Hopefully this is a good starting point for you.

Resources