are controllers necessary to send flash messages in rails? - ruby-on-rails

this is kind of a newbie question, sorry but...if a model has no controllers, how could i perform a
flash[:notice]?
for example in
https://github.com/tute/merit
i noticed that it just has models and no controllers. i know that it would be wise to put the flash message inside a controller as opposed to the methods that get executed in the models, but.... how can i do this if there is no controller?
i could try to create one but then doesn't each action in the controller correspond to a page in the view?
certain methods are being executed in the models and i want to be able to add a flash[:notice] whenever they get executed but...how would i do this?
thank you

You would still set flash messages in a controller (or anywhere else the session can be accessed, technically). Merit is just an add-on for Rails, not a replacement. You would still use controllers in your application to handle requests from the user.

Related

Rails: should I create a new controller when I need actions similar to new, update, destroy?

I found this but it didn't answer my question.
Say I have a Payment model, and PaymentConroller. I have the ability to create one payment, edit it, update etc...
I also have a method payment_wizard. This method spreads payment according to parameters given in 'payment_wizard' form.
But, I want a clean form when I spread new payments, to be able to update an existing collection of payments, and destroy all of them at once.
This is making me think that the "right" thing to do would be to create a new controller PaymentWizardController which does all that.
Is this the right way to do this?
The best approach in my opinion is to keep all your controllers RESTful. Managing a collection of payments could be done by creating a PaymentCollectionController (or however you call it) with update and destroy actions.
Just as is mentined in the question you linked, you don't need a model for every controller you have. Keeping them RESTful is following a convention which makes your code more readable for other users.
Think about controller as a handler of actions which are available for user to visit on your site. Do you really need this payment_wizard controller? Try to create some functions in service for PaymenController to keep it slim.

How should I be updating data with AJAX?

I am making a rails MVC style application.
When I am loading the pages, the controller gets the data from the model and forwards it to the view and the view renders itself.
However, I am wondering what the appropriate way is to interact between javascript and my database.
Say the user is playing a game and he has a bunch of clues on the screen. Clicking a clue will move it to his clue box and needs to update the UserClues model to add the clue.
The user also needs to be able to remove clues where the clue gets removed etc...
This needs to happen via AJAX.
I am wondering what the appropriate approach is.
Say he got his page from /Investigation which loaded the page using the InvestigationController.
Should the InvestigationController be the one calling the model to add/remove the clues, or should some sort of data controller do it.
For example:
/Investigation/AddClue
or another controller
/User/Clues/Add
The reason I am asking is I have a lot of data on my pages that is created/added/modified and I am wondering if my routes/controllers should be separate for data manipulation and pages, or if I should have a controller for each page and it also manages what the user can do on that page (like add / remove clues to and from a ClueBox)
Thanks
Ideally you will want to have a separate controller for each resource. Even though your current view is in the context of the Investigations, controller, dealing with clues should have its own resource. Otherwise things can get complex. If the clues are investigation specific, then you can scope them under the Investigation URL.
resources :investigations do
resources :clues
end
This will give you something like /investigations/1/clues/1, but this maybe not be necessary, and I would avoid nesting unless required.
The controller can then respond in the correct format. In this case Rails UJS provides you with the tools you need. You can render a create.js.erb or destroy.js.erb templates to handle user actions. The templates would have the required JavaScript and dynamic code to update the screen state.
If at all possible, try to use Rails' RESTful routes. In this case, that probably means line in your routes file that looks something like:
resources users do
resources clues
end
In your users/clues_controller.rb file, put in actions for the different AJAX requests, like create to add a clue to a user (via a POST request), destroy action to remove a clue from user (via a DELETE request, might need to simulate with POST + "_method=delete" parameter).

Accessing POST params in routes.rb

I have a system with a web UI that works as normal, and an API endpoint at /receiver_api. Users send emails which are parsed by Mailgun, who then submit a POST to this endpoint. There are a lot of possible actions that we may want to take, depending on the values of these params (create new post, create new reply, add subscription, delete subscription etc.), and when writing the handler it felt like we were doing a kind of routing again!
So we would like to choose the controller that we direct the request to based on what the POST params are. We are directing /receiver_api to a ReceiverApi#receiver controller/method at the moment, which inherits from ApplicationController. It currently effectively routes requests to other "fake" controllers that don't inherit from ApplicationController (since redirecting from one Rails controller to another wouldn't work). We would like to be ultimately routing to Rails controllers so we can use before_filter and all the other magic in them.
Anyway, one possibility that springs to mind is a method in routes.rb that accesses the POST params and returns the Rails controller/method that should be directed to. 2 questions:
Is this possible? Can you access POST params in routes.rb?
Is there a better way of doing this? We had thought about moving up a level into Rack, and will probably do this at some point, but would rather just get something out of the door if this will take a while.
Thanks!
Choosing a controller based on params is not a good thing to do.
A better alternative is to refactor your code (in those fake controllers) to methods in your model, and call model methods based on the params from your controller.
You cannot access params in your routes.rb, because it is run at initialization.
If you really want to call controllers based on params, there is a way of doing this, by redirecting to another controller. This is explained in http://www.railsonwave.com/2008/10/25/how-to-call-a-controller-s-action-from-a-different-controller/ [bad link], but do note that it is very much a hack.

Ruby on Rails simple website layout

I'm learning RoR, I've read some tutorials (railstutorial for the first one),
but I've a problem to define the logic layout of the my first simple website.
The structure is:
When you go to mysite.com you see a welcome page with the signup form or the link for login.
If you signup or you login into the site, you are at mysite.com/dashboard and you see a list of your messages.
You can go to mysite.com/$username and you see a page with a form where you can write a message for the $username.
Stop. That's it. It's very simple, I know, but is for learning.
The problem is this: I'm new to MVC paradigm and I don't know how structure the logic layout of my app. Of course there'll two models: User and Message. But for controllers? And which functions in any controllers? Should I use scaffolding?
Please give me a help, I'm very confused.
Thank you.
Controllers are the logic for the data, so to login/sign-up is really validating/creating a user, if you need to view the users dash board, well that's a look up on the user data so he goes there as well.
The messages, that will be a separate controller that can create/view messages!
As others have pointed out, your controllers contain the logic for your code and invoke views based on that logic by rendering or redirecting to pages. You can define whatever actions you want in your controllers, and then use routes to map a particular URL to a controller action. That being said, Rails gets a lot easier if you "go with the flow" and make some simple assumptions about the actions that could happen. Both your users and your messages represent rows in their respective database tables. There's no much you can do to a row in a database table - you can Create it, Read it, Update it, or Delete it (CRUD). If you define your actions in terms of these four logical actions, Rails lets you generate some easy routes.
You can back into any URL schema that you want, but what you are describing is:
Read the messages that are for a user on the dashboard
Create a message for a user when you go to another page (mysite/username)
Each of these maps to a CRUD action that you should be defining in your controllers.
Agreed also with other advice to simply do a few more tutorials that will probably clear this up.
If you haven't already, read Getting Started with Rails. Look out for the discussion on MVC and scaffolding. Playing around with scaffolding can help you learn where things go and is a great place to start for beginners.
Also, I highly recommend this book: Agile Web Development with Rails. It is very hands on and an easy read.

ActionMailer best practices: Call method in the model or the controller?

Sending an email is usually called after an action on a model, but the email itself is a view operation. I'm looking for how you think about what question(s) to ask yourself to determine where to put the action mailer method call.
I've seen/used them:
In a model method - bad coupling of related but seperate concerns?
In a callback in the model (such as after_save) - best separation as far as I can tell with my current level of knowledge.
In the controller action - just feels wrong, but are there situations were this would be the smartest way to structure the code?
If I want to know how to program I need to think like a programmer, so learning how you go about thinking through particular programming solutions is worth months of coding on my own in isolation. Thank you!
Late answer, but I want to rationalize on the subject:
Usually, in a web app, you want to send emails either as a direct reaction to a client. Or as a background task, in case we're talking about a newsletter/notification mail sort of thing.
The model is basically a data storage mapper. Its logic should encapsulate data-handling/communication with data storage handling. Therefore, inserting logic which does not relate to it is a bit tricky, and in most cases wrong. Let us take the example: User registers an account and should receive a confirmation email. In this case one could say, the confirmation email is a direct effect of the creation of a new account. Now, instead of doing it in the web app, try to create a user in the console. Sounds wrong to trigger a callback in that case, right? So, callback option scratched. Should we still write the method in the model? Well, if it's a direct effect of a user action/input, then it should stay in that workflow. I would write it in the controller after the user was successfully created. Directly. Replicating this logic in the model to be called in the controller anyways adds unnecessary modularity, and dependency of an Active Record model from Action Mailer. Try to consider sharing the model over many apps, in which some of them don't want Action Mailer for it. For the stated reasons, I'm of the opinion that the mailer calls should be where they make sense, and usually the model is not that place. Try to give me examples where it does make.
Well, depends.
I've used all of those options and your point about 'why should I put this where?' is good.
If it's something I want to happen every time a model is updated in a certain way, then I put it in the model. Maybe even in a callback in the model.
Sometimes you're just firing off a report; there's no updating of anything. In that case, I've normally got a resource with an index action that sends the report.
If the mailer isn't really related to the model that's being changed, I could see putting it in a callback. I don't do that very often. I'd be more likely to still encapsulate it in the model. I've done it, just not very often.
I'm aware it's been a while but best practices never die, right? :)
Email is by definition asynchronous communication (except for confirmation email, but even this one it should be a best practice to leave a delay before having to confirm).
Hence in my opinion, the most logical way to send it is :
in a background action (using Sidekiq or delayed_job)
in a callback method : "hey this action is successfully done, maybe we can tell the world now?"
Problem in Rails is that it is not too many callbacks (as in JS for instance): I personnaly find it dirty to have code like:
after_save :callback
def callback
if test_that_is_true_once_in_the_objects_life
Mailer.send_email()
end
end
So, if you really want to think like a programmer, the idea would be to set up some custom callback system in your app.
Eg.
def run_with_callback(action, callback_name)
if send(action)
delay.send(callback_name)
end
end
Or even creating an event system in your app would be a decent solution.
But in the end those solutions are pretty expensive in time so people end-up writing it inline after the action
def activate
[...]
user.save
Mailer.send_mail
respond_to
[...]
end
which is the closest fashion to callback in synchronous programming and results having Mailers call everywhere (in Model and in Controller).
There's several reasons why controllers are a good place for the mailers:
Emails that have nothing to do with a model.
If your emails depend on several models that dont know about each other.
Extracting models to an API should not mean reimplementing mailers.
Mailer content determined by request variables that you dont want to pass to the model.
If your business model requires a lot of diferent emails, model callbacks can stack.
If the email does not depend on the result of model computations.

Resources