I have two different helper files (photos_helper & comments_helper) w/ that have a method named actions_for. How can I explicitly call which helper method that I need? I know that I could just rename one of them but I would prefer to keep them the same. I tried PhotosHelper::actions_for but that doesn't seem to work.
In Rails 3 all helpers are always (in Rails 3.1 a patch exists to selectively allow helpers again) included. What's happening behind the scenes:
class YourView
include ApplicationHelper
include UserHelper
include ProjectHelper
...
end
So depending on the order Rails includes them, any of your actions_for methods will be used. There is no way you can explicitly chose one of them.
If you would have to explicitly call ProjectHelper.action_for, you could also name your methods project_action_for - simplest solution.
Make both of them a Class Method
module LoginsHelper
def self.your_method_name
"LoginsHelper"
end
end
AND
module UsersHelper
def self.your_method_name
"UsersHelper"
end
end
Then in View
LoginsHelper.your_method_name #Gives 'LoginsHelper'
AND
UsersHelper.your_method_name #Gives 'UsersHelper'
Related
Is there a proper place for helper methods for models in Rails? There are helper methods for controllers and views, but I'm not sure where the best place to put model helper methods. Aside from adding a method to ActiveRecord::Base, which I'd prefer not to.
UPDATE: It seems Concerns make a lot of sense. Here's an example of what I want. Certain models can never be deleted, so I add a callback that always throws an exception:
before_destroy :nope
def nope
raise 'Deleting not allowed'
end
With concerns, I could do something like this?
class MyModel < ActiveRecord::Base
include Undeletable
end
module Undeletable
extend ActiveSupport::Concern
included do
before_destroy :nope
end
def nope
raise 'Deleting not allowed'
end
end
Is this the Rails way of doing this?
If you want to use a helper_method my_helper_method inside a model, you can write
ApplicationController.helpers.my_helper_method
If you need a bit more flexibility, for example if you also need to override some methods, you can do this:
class HelperProxy < ActionView::Base
include ApplicationController.master_helper_module
def current_user
#let helpers act like we're a guest
nil
end
def self.instance
#instance ||= new
end
end
and then use with
HelperProxy.instance.my_helper_method
If you have strong nerves, you can also try to include the ApplicationController.master_helper_module directly into your model.
via : makandracards's post.
For your reference: http://railscasts.com/episodes/132-helpers-outside-views
If what you are asking is where to put code that is shared across multiple models in rails 4.2, then the standard answer has to be to use Concerns: How to use concerns in Rails 4
However, there are some good arguments (e.g. this) to just using standard rails module includes, and extends as marek-lipka suggests.
I would strongly recommend NOT using ApplicationController helper methods in a model, as you'll be importing a lot unnecessary baggage along with it. Doing so is usually a bad smell in my opinion, as it means you are not separating the MVC elements, and there is too much interdependency in your app.
If you need to modify a model object by adding a method that is just used within a view, then have a look at decorators. For example https://github.com/drapergem/draper
Pretty simple, I want to use the polymorphic_path method inside a Rails 4 model. Yes I know it's poor separation of concerns. And I know about Rails.application.routes.url_helpers, but polymorphic_path isn't in there.
Try including also PolymorphicRoutes:
include ActionDispatch::Routing::PolymorphicRoutes
include Rails.application.routes.url_helpers
def link
polymorphic_path(self)
end
I know the OP specified Rails 4 but in case someone else ends up here looking for the answer using Rails 5 like I did, here are two ways to access polymorphic_path in a model in Rails 5:
class Something
# The following line is enough, no need for ActionDispatch::Routing::PolymorphicRoutes in Rails 5
include Rails.application.routes.url_helpers
end
Or, if you want to avoid including all methods, just add a private method that wraps the call and you're good to go!
class Something
def do_stuff
polymorphic_path(a_resource)
end
private
def polymorphic_path(resource)
Rails.application.routes.url_helpers.polymorphic_path(resource)
end
end
Notice that the class doesn't need to inherit from ApplicationRecord, both methods work with POROs (Plain-Old Ruby Object).
Real simple.
class Template
def stuff_i_want
stylesheet_link_tag('my_stylesheet')
end
class << self
include ActionView::Helpers::TagHelper
include ActionView::Helpers::AssetTagHelper
end
end
And this returns..
undefined local variable or method `config' for Template:Class
from /Users/elephanttrip/.rvm/gems/ruby-1.9.3-p385#shasta/gems/actionpack-3.1.12/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb:137:in `stylesheet_link_tag'
From the stylesheet_tag_helpers.rb in Railtie :
def stylesheet_link_tag(*sources)
#stylesheet_include ||= StylesheetIncludeTag.new(config, asset_paths)
#stylesheet_include.include_tag(*sources)
end
Config isn't instantiated in that file anywhere, so I'm assuming its' required from somewhere else.. I have no idea where, or how.
Anyone know how to inject/pass a config into my helper? I've never needed to do this before.
It looks like you're actually including your helpers into Object - and then defining your Template class. I've no idea why it's asking for config, but try putting the includes inside your class definition and see if the problem goes away.
You probably shouldn't be randomly including helpers into things over than your views though - that's not what they're for.
Why not use view_context instead.
So instead of including the helper modules you can do this:
class Template
def stuff_i_want
view_context.stylesheet_link_tag('my_stylesheet')
end
end
This should work fine.
And if you want to include you helpers then use the below code:
class Template
include ActionView::Helpers::TagHelper
include ActionView::Helpers::AssetTagHelper
def stuff_i_want
stylesheet_link_tag('my_stylesheet')
end
end
Ideally you should not include helpers in ur controllers as they are not intended for that.
Hope that helps
I have a kind of social network website.
I have a logic to create the path for the user, and select an avatar for each user described in UsersHelper methods user_path(user) and user_avatar(user).
Instead I want to have methods like user.path and user.avatar, but I don't want to have that code inside the model file.
I tried extending the User class inside the helper:
module UsersHelper
class User
def avatar
...
end
end
end
That doesn't work - the method I added aren't recognized (I'm guessing Rails dynamically generates the ActiveRecord class on demand so my methods don't apply?)
I'd really appreciate ideas
First, there's a reason helpers are separated from models. According to the MVC pattern your model shouldn't know anything about your helpers, and not vice versa either (the latter is usually ignored in Rails, though).
But, if you want to do this, you need to do class ::User in model UsersHelper, or the following:
module UsersHelper
end
class User
end
The reason for this is that Ruby namespaces classes. So you defined UsersHelper::User, while your model is called User. Calling the class ::User or defining it outside the module forces it into the root namespace.
However, as I said, this is not the "correct" way to do it. A better way would be how you're already doing it, or maybe using a decorator pattern.
Draper is an awesome little gem that does an excellent job of achieving the functionality you're looking for (adding view / presentation specific code while still making it "feel" like the model you're working with). We've removed almost all of our model-specific helpers after starting to use draper.
Basically, it works by defining decorators, which work like a wrapper around your model. A decorator looks and feels like the model it's decorating, but can have additional functionality defined on top of it. In addition, you can restrict access to certain fields and lock stuff down if you like.
For your example, adding a decorator would be as simple as:
(in app/decorators/user_decorator.rb)
class UserDecorator < ApplicationDecorator
decorates :user
def avatar
# your implementation
end
(in your controller)
def index
respond_with UserDecorator.decorate(User.all)
end
(in your views)
<div class='avatar'><%= user.avatar %></div>
<div class='name'><%= user.name %></div>
Helpers are intended to use with the views, not with the models.
If you wish to have something like user.avatar, you have to add it to your model.
If you want to stick it in the helpers, then in the UsersHelper add a user_avatar method.
I have a couple of controllers with associated helper modules. I got some helper methods that should behave similarly across different modules, meaning:
module UserHelper
..
def destroy(user)
link_to t(:destroy_user), user ...
end
end
module PhotosHelper
..
def destroy(photo)
link_to t(:destroy_photo), photo ...
end
end
I didn't know (realize) that all of these helper modules are included by default, (which is ok, I guess,) and it doesn't matter what view you're calling the helper method from.
What is the best way to separate the rest of the helpers from my current controller/view so that, when controller_name == 'photos', only Photos and Application helpers are used?
The concept of Helpers is not really clear to me. Why not just have a single ApplicationController if all helpers are already mixed in? Is it just for "logical separation"?
I mean, of course, there's a number of workarounds. But is it just me, or it really feels like there's no reason to include all of the helpers globally?
If you called clear_helpers at ApplicationController class, they won't share among different helper classes
clear_helpers()
Clears up all existing helpers in this class, only keeping the helper with the same name as this class.
ref: http://api.rubyonrails.org/classes/AbstractController/Helpers/ClassMethods.html#method-i-clear_helpers
You could put the common methods on the ApplicationHelper and pass the resource as a parameter.
So then use the specific helper resource for specific methods only.
Methods (helpers) that you can share anyway, goes to ApplicationHelper file.