Include helper in a helper subclass keeping controller context functions - ruby-on-rails

Actually, this is my problem. I have a rails app with a MainController, a HttpHelper and a ServiceHelper.
main_controller.rb
class MainController < ApplicationController
include ServiceHelper
def my_method
Service.make_stuff
end
end
service_helper.rb
module ServiceHelper
class Service
include HttpHelper
def self.make_stuff
http__foo
end
end
end
Service = ServiceHelper::Service
http_helper.rb
module HttpHelper
def http__foo
#stuff
params[:bar].nil?
end
end
If everything work well, this code should tell me if the :bar param exist, but I have a problem. Firstly, this code doesn't work, it tells me that http__foo is not defined, certainly because the include HttpHelper in Service doesn't work.
My second probleme is that if the include works, there will probably be a problem with the params variable. If I call this method (http__foo) in the controller, it will be fine, but I call this from a subclass, then I'm not sure it's be reliable.

make_stuff is a class method. http_foo is an instance method. Hence, when you call http__foo from your make_stuff, it is like calling Service.http_foo() which is not defined. What is defined is Service.new.http_foo().
I don't know what you want to do but in my humble opinion, by watching your code, it does not seem you are really familiar with Rails MVC concept and creating a MainController (why not use ApplicationController?), as well as the way you use your helpers is weird to me. It might be a good idea to restart from scratch.

oldergod is correct about the class vs. instance methods issue. Additionally, params is a method defined in ActionControllor, which is somewhere above the inheritance tree of all your controllers. The params method will NOT be available in the Service (which is where it ends up when you include HttpHelper in Service), unless you make it a subclass of ActionController or ApplicationController, which would be a little strange since it isn't a controller.

Related

Is there any advantage to using memoization in my Rails controller show method?

I'm using Rails 5.1. I'm wondering if there's any advantage to using memoization in my controllers. For example, I have the below show method ...
class PartsController < BaseController
def show
#part = Part.find(params[:id])
end
I could make this
def show
#part ||= Part.find(params[:id])
end
but since a new instance of a controller is created by a request (keep me honest on that assertion), it doesn't seem like my "#part" would ever get reused. Am I wrong? Should I be using memoization th improve performance here?
No, there is no benefit here. You could maybe write tests for it in a way so only one instance of a controller class is used but I've never seen anybody doing this for a controller class - probably because it's not how they are used in real life.

Check if class have skip before action for test in Rails

It is possible to check if a controller have a skip_before_action for one specific action?
For example:
class AuthenticationController < ApplicationController
skip_before_action :authenticate_user
...
end
And then check with something like this:
AuthenticationController.has_skip_before_action(:authenticate_user)?
I want to do this check for my controllers tests. If RSpec has anything like this, I can use. I am using Rails 5.1.
Should you? No. Similar to what Veridian Dynamics wrote, you want to test behaviour not necessarily the existence of a method.
That said, is it possible to do so? Yes. Here's a toy example that'll work for you:
class AuthenticationController < ApplicationController
skip_before_action :authenticate_user
def index
end
end
# authentication_controller_spec.rb
test "should get index" do
# Have to make a request first to instantiate the controller variable
get authentication_url
# Convert this to a clearer method in your real code
result = controller.__callbacks.first.last.map(&:filter).include?(:authenticate_user)
# Assert on result ...
end
To explain the code, you're using the instance of AuthenticationController and digging into the private methods of that instance to get the list of callbacks. Then you can look for the presence or absence of your specific callback.
This is not a good solution, and I would shudder to see these in a codebase! This test relies on internal functionality of the Rails framework which could change at anytime. That makes a test like this brittle and it can fail during framework upgrades. Any colleague checking this code in would require a very specific explanation on why this was an absolute necessity to have in our codebase.
No, but you can check to see if :authenticate_user is working as expected by validating that it either does or does not do what you intend.
As with all unit tests, it's not about "does this method exist?", it's about "does this method do what we expect?" If the method does not exist, we do not check for that because we do not care. We want the behavior to match our expectations, not the code. If our code does not match our expectations, we must investigate, read, refactor, etc. But that is a human job, not an RSpec job.
I assume that you're just trying to be DRY and avoid checking authentication if "skip_before_authentication" already exists, but that's a really bad idea even if it were possible.

Using a Decorator, (rails) Could not infer a decorator for ActiveRecord::Base

I'm having trouble using a decorator. I've never used one before and I've been trying to use one with regards to something that I've been doing for breaking up some emails.
However because I've never used one before, I've been having trouble even doing very simple things with my decorator and I'm thinking there is some form of setup issue with it. I do know that everything outside of my little feature (aka the gemfile and such) are all up to date and proper.
The error I am getting is simply,
Could not infer a decorator for ActiveRecord::Base.
Now I have a controller that is almost empty, but inside it, I have the active record portion saved like so.
class Admin::ReceivedEmailsController < Admin::ApplicationController
With my view being titled,
_receive_email.html.haml
All I am doing in my view as of right now is so:
%td= received_email.decorate
My decorator
class Admin::ReceivedEmailsDecorator < Admin::ApplicationDecorator
def received_email
if can? :update, #customer
received_email.content
else
"You need to have the correct admin access to view the email"
end
end
I feel like this would have to be such an elementary thing for me to be missing, but I'm not sure what it is. Would anybody have any idea what I'm missing?
After much further research, reverse engineering further decorators and reading more documentation. I learned that a model or a helper is needed for a decorator to be properly used. Which due to my partial I did not have one specific model or helper to use.

How to include explicitly a controller method in its helper file so it is possible to include that helper in another controller and use that method?

I am using Ruby on Rails 3 and I would like to include a controller (accounts_controller.rb) method explicitly in its related helper file (accounts_helper.rb) so that I can include that helper in another controller and use its methods. I need that because I can move out in helper the method code stated in accounts_controller.rb, but I need to use that method in others controllers.
Since this question is also related to this other question, I thinked to solve the latter this way:
(1) in accounts_controller.rb I state
def method_name
...
end
(2) in accounts_helper.rb I can include the method_name... how to do this?
(3) in posts_account.rb I can include accounts_helper.rb... how to do this?
Is it a good approach? If so, how can I code the steps 2 and 3?
If you want to use the method across controllers and views/helpers you can declare it as a helper_method
In your application_controller
helper_method :some_method
def some_method
// some common stuff
end
This will make the method available across controllers and views
One idea -- put the helper method in application_controller.rb then you can declare when to expose it to the view in a per controller basis - or globally in the application_controller.rb.
If you need to use the method in multiple controllers then I'd suggest it's reasonable to put it in application_controller.rb

using helpers properly in ruby on rails

It looks like you cannot use a helper in a controller even if both of them belong to the same class. For example: XYZHelper and XYZController...
I was under the impression that if the prefix is the same "XYZ" then the method in the helper can be used in the controller and in the view, but I think this is not the case.
So how do I remove some common functionality from a controller and place it in a helper. I want to place that piece of code in a helper because other controllers may be using it. What is the best way to approach this.
Thanks,
Jai.
There are a few ways you could share some code between controllers:
Application controller: If the code in question is an action/method which ought to be in a controller, but could be used by several controllers (or all of them), then this might be a place to put it.
the 'lib' directory. just a general purpose place to put code which should be shared.
Put it in the model. This may or may not be applicable, but its worth taking a good look at the code you're trying to move and thinking about whether it is something which makes sense on a model (instead of a controller or random class/module in lib).
Follow Pete's guidelines. If you still need to expose the methods then do the following:
Add the methods to ApplicationController class and register the methods as helper methods by calling helper_method.
class ApplicationController < ActionController::Base
helper_method :foo, :bar
private
def foo
"foo"
end
def bar
"bar"
end
end

Resources