Triggering a controller action after new/create - ruby-on-rails

Rails 3.2.18
Ruby 2.1.5
In my controller, I have new and create methods. I have another method in the controller, let's call it post_create that I would like to automatically trigger after the create method finishes executing. This method has no view associated with it, and it's supposed to update a table.
I tried doing
after_filter :post_create, only:[:create]
But I need the parameters that were passed to the create method, and at this point I no longer have them. Any ideas?

It can be done in this way:-
def create
#code
redirect_to post_create_path(parameter)
end
def post_create
#update the table
redirect_to desired_path
end
Note:- Set the path by knowing the routes by typing in the console as rake routes.

You will get params in you after_action. If this is not the case. You can perform such action in observer. If this is something that does not affect your new view. Then you should go for observer instead of creating a after_action. For mor detail check here.

Related

Pass arguments from view/controller to model - Rails

I'm looking to pass arguments from the controller to the model, but I keep getting wrong number of arguments.
Model:
before_create :embed_info
def embed_info(embed_url)
something = embed_url
## Do some stuff
self.title = "Title" ##This works.
end
Controller:
Create action:
#post = Post.new post_params
#post.embed_info(params[:title])
if #post.save
redirect_to root_url, notice: 'post created'
else
render 'new'
end
You can not pass arguments from controller to model callback like this.
You can use attr_accessor to create a virtual attribute and then set that attribute as part of your create action from controller.
If you're manually invoking the embed_info method, you shouldn't also be invoking it automatically via a before_create callback. Remove the line before_create :embed_info as it's currently serving no purpose except to invoking embed_info with no arguments when you attempt to save your model.
It's possible that you intended to add a validation, which is different than a before_create callback. If your intent was to make sure that embed_info had been called then you should use validations to insure that whatever side effects embed_info has leave the model in a valid state.
but I keep getting wrong number of arguments.
You are getting an arguments error because of this: before_create :embed_info. You can delete that line and then explicitly call the method like you are already doing in the controller.
This is probably not best practice but I think it will get your code working.
Another thing you could do is to move the logic for deriving the title to the controller and then pass the title in with the params.
# controller
def create
#post = Post.new post_params.merge(title: embed_info)
...
def embed_info
something = params[:title]
## Do some stuff
...
You could use attr_accessor to create a virtual attribute of embed_url. Pass it in new action itself. And when you call save, before_save will be called by itself and you can use embed_url there (as its a virtual attribute).
Let me know if you need help if the explanation is not clear.

Rails Check if Controller Index Exists

Is there a way to check if there exists an index action for a controller? Something like:
Controller.indexActionExists?
I have seen posts to check if specific routes exist, but those methods aren't working for me, since some of my index actions aren't associated with routes.
The action_methods method is going to be the most expedient tool in this case, returning a Set of method names. Give the following code a shot:
# Get a set of method names belonging to a controller called 'MyController'
methods = MyController.action_methods
if methods.include? "index"
puts "MyController has an index method"
else
puts "MyController lacks an index method"
end

Can/should I customize an ActiveAdmin update action, or use a model callback instead?

My Rails app has events and users. In ActiveAdmin, an event can be edited via the form action. If the edit includes attaching a user to the event, I need to send a message to that user. I think I need to either customize the update action or trigger the message-send in an :after_update callback in my event model.
I guess it makes more sense to add a callback, but I'm curious whether it's possible to customize the update action in ActiveAdmin. Is it?
You can edit ActiveAdmin controller actions, but if the action you do after update is the same when updating form outside admin panel than it's better to use callbacks I guess. Why writing more code?
http://activeadmin.info/docs/8-custom-actions.html#modify_the_controller
ActiveAdmin.register Post do
controller do
# This code is evaluated within the controller class
def define_a_method
# Instance method
end
end
end
It's definitely possible, in your ActiveAdmin model just add :
controller do
def update_resource(object, attributes)
attributes.first[:your_attribute] = ...
object.send(:update_attributes, *attributes)
end
Hope it helps!

link to a controller function from the view

I have a function to take ownership of a job which updates the database to update the username in a table row. I want to link to this function from the view and then redirect to the appropriate page.
How do you link to a controller function or a model function from the view?
from the index i want to have another link beside show, edit, delete, which says 'take ownership'
This will then fire off an action in the application controller
def accept_job(job_type, id, username)
if (job_type == 'decom')
Decommission.update(id, :username => username)
else
end
end
You can use the instance variable #controller to get a reference to the controller. As for calling a model function, you can call Model.function to call class methods, or if you have a particular Model instance called model_instance, then use model_instance.function to call an instance method.
Edit: Okay, I think I understand what you're asking now.
You should
Create a new action in the controller, let's call it update_username:
def update_username
job = Job.find(params[:id])
job.your_method #call your method on the model to update the username
redirect_to :back #or whatever you'd like it to redirect to
end
Add your action the routes in routes.rb. See Rails Routing from the Outside In for more details.
Add your link in the view:
<%=link_to "Update my username please!", update_username_job_path%>
First you create a function in your model, say
class Decommission
def assign_permission(name)
#your update code
end
end
As I can see, you can do this in 3 different ways
1 - Create a helper method to update the permission (This can be done either in Application helper or helper related to your view)
2 - By creating a controller method (as you proposed) But if you are not using this method in other views you dont need to create this method in application controller
3 - If you want to use your method in both controllers and views, create your method in application controller and make it as helper method. By that way you can access it from controllers as well as views
cheers
sameera

rails: checking which controller method was called from within the model

Is there a way to check which controller method was called from within the model?
Example:
Say the controller create method was called:
def create
do something
end
Then in the model do something only when create in the controller was called
if create?
do something
end
I'd imagine you could examine the call stack but this is exactly what models are not for: they should now nothing about the controller.
Examining the stack:
if caller.grep /create/
# do something
elsif caller.grep /update/
#do something else
end
Should do the trick.
Just pass a create flag to the model method, or make two different methods in the model and call the appropriate one from the controller. Otherwise you are creating a rather unpleasant dependency between the controller and the model. As you noted, validation methods take a parameter to specify when they are run.
Check
if params[:action] == 'create'
Inside your model you can ask/know if the record you are handling is a new record or not
p = Post.new
p.new_record? => true
p = Post.first
p.new_record? => false
maybe that helps you enough?
Otherwise inside a model you can add callbacks, e.g. a before_create that is only called before a new record is saved. To keep your model lean, and you should have a lot of callbacks, those could be grouped inside an observer.
Hope this helps.

Resources