I am learning rails and I have a question
How can I call an action from another in the same controller?
def new
new_method()
end
private
def new_method
...
end
This would be the right way?
The parenthesis is optional in Ruby. But, one action receive a call from client and respond one output. Your private "action" is only a function or method.
class User
def create
make_something(params)
end
private
def make_something(params)
#some implementation
end
end
Related
I'm trying to move some business logic out of one of my controllers, StoreController and into a new Store::CreateService service object. Learning about services recently, it doesn't seem to be much of an established pattern for implementing them. I'm running into an error trying to call a protected method. I can obviously move the logic from those protected methods directly into execute but my understanding was that this should be okay to Rails.
undefined local variable or method `find_and_set_account_id' for #<Store::CreateService:0x00007f832f8928f8>
Here is the Service object
module Store
class CreateService < BaseService
def initialize(user, params)
#current_user, #params = user, params.dup
end
def execute
#store = Store.new(params)
#store.creator = current_user
find_and_set_account_id
if #store.save
# Make sure that the user is allowed to use the specified visibility level
#store.members.create(
role: "owner",
user: current_user
)
end
after_create_actions if #store.persisted?
#store
end
end
protected
def after_create_actions
event_service.create_store(#store, current_user)
end
def find_and_set_account_id
loop do
#store.account_id = SecureRandom.random_number(10**7)
break unless Store.where(account_id: account_id).exists?
end
end
end
You have an extra end after def execute..end. That end closes the CreateService class. This means your protected methods are defined on the Store module.
Hence the missing method.
I have the following controller
class V1::LpDeveloperReferralsController < V1::BaseController
def create
add(a, b).delay
end
def add(a, b)
end
end
I want to be able to call the add method in create method but run it as a delayed job.
At the moment, it doesnt do that.
Do you want to queue this Api call to make external call or to another endpoint?
You can try below if this helps u..
send_request - > can be your own method to make API call to external
object -> your controller instance
class ExampleRequestJob
def initialize(object)
#object = object
Delayed::Job.enqueue self
end
def perform
#response = #object.send_request().with_indifferent_access
end
def after(job)
# want to reattempt if failed
end
def error(job, exception)
#failed
end
def success(_job)
# your success
end
end
I am trying to call 'checking' action from post model.
class Post < ApplicationRecord
after_commit :testing
def testing
#id = "#{self.id}"
puts #id
checking # call action to controller
end
end
posts_controller.rb
def checking
puts "not Working"
end
I am trying to achieve the above, whereas it is not getting called.
You can do this by instantiating the controller.
SomeController.new.some_action
However it is Not Recommended as your model logic should be independent of your controller logic. Your model should follow Single-responsibility Principle.
A class should have only a single responsibility.
You might need some common logic for controller and models or some service!!!!
As it was said: the models should not know about controller.
Depending on the reason,
you can define checking in model and from Controller just call this method for current Post.
if something should be set from Controller and checked in Model , you can use the approach defined here
As many (or all) other said, you shouldn't call a Controller action from a Model. If you are saving/destroying and object from a Controller and you want to check is commit was called, you can do it in the controller, after saving or destroying.
posts_controller.rb
def create
#post = current_user.posts.build(post_params)
if #post.save
checking
end
end
def checking
puts "Is is working"
end
If this is not what you want, because you are specifically interested in the commit callback, you can change the code to this:
posts_controller.rb
def create
#post = current_user.posts.build(post_params)
#post.save
if #post.commmited?
checking
end
end
def checking
puts "Is is working"
end
And add some logic to your Model:
class Post < ApplicationRecord
attr_accessor :commit_performed
#unset the commit_performed attribute on first callbacks
before_destroy :unset_commit
before_validation :unset_commit
#set the commit_performed attribute after commit
after_commit :set_commit
def unset_commit
#commit_performed = false
end
def set_commit
#commit_performed = true
end
def commited?
#commit_performed
end
end
You should not be calling a controller action from a model. That's not how even controller methods are called. If you want to trigger an action, it should be either written as a target of a view form or input method, or as a redirect through another controller method itself. If you really want this action to be triggered (if you want the message after a record is saved to a listener url), I'd suggest using a lib such as HTTP::Net or a gem like HTTParty to trigger a call to the action, with its url or rails url_helper. That too, is not suggested, and/or is not the way to operate things in rails.
is it necessary to mention the private methods in controller as helper_methods in controller?
Like
class PostsController < ApplicationController
helper_method :check_something
def new
check_something
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
private
def check_something
redirect_to(root_path) and return if something
end
end
Is the statement : helper_method :check_something required ? if so why ?
And when i call a private method from a controllers action method is the params hash accessible in the private or the helper method ??
I think you have misunderstood the 'helper_method' concept.
helper_method is used to make your controller method to act as a method as its in your helper modules
So inside your controller, you can always access your private method without the 'helper_method' section
and if you add a controller method as a helper method, as you have already done, in your view you can simply call it
and for your second question, yes params hash is accessible via controllers private methods
HTH
No it is not necessary. You can always call private methods of your controller within your controller.
Also, params would be available automatically for the private methods within controller.
No need to mention a private method as helper method in your controller. You can directly call them from another methods from the same controller by passing parameters like params, or any thing.
class ContorllerName < ApplicationController
def index
private_method(params)
end
private
def private_method(vals)
vals
end
end
I'm new with RoR and I have a controller (UsersController) where I wish to verify the existence of a certain session before anything. Since the session verification code is the same for several methods and I don't want to repeat myself, I decided to make a new method in my controller to check the sessions:
class UsersController < ApplicationController
def index
end
def show
end
def new
if self.has_register_session?
# Does something
else
# Does something else
end
end
def edit
end
def create
end
def update
end
def destroy
end
def self.has_register_session?
# true or false
end
end
And when I run the page /users/new, I got this error:
undefined method `has_register_session?' for #<UsersController:0x1036d9b48>
Any idea?
self when you define the method refers to the UsersController class object, but within the instance method new, self refers to the instance of UsersController.
You can either make your method an instance method:
def has_register_session?
# code
end
You can then get rid of the self when calling has_register_session? in new as well.
Or call the method on the class:
if UsersController.has_register_session?
# code
end
instead of referencing UsersController explicitly you could do self.class.
Note that you likely want the first solution: making has_register_session? an instance method.
By doing def self.blah you've created a class method whereas you want an instance method.
You might also want to make the method protected - all public methods are exposed as actions by default.