Creating a specialised view filtering form in Rails - ruby-on-rails

G'day guys, I have a current set of data, and I generate multiple analyses of this data (each analysis into its own active record item called a pricing_interval) using a helper function at the moment.
Currently to analyse the set of data, you need a start time(using datetime_select) an integer (using text_field) and a name (using text_field)
I would like on submission of the form to be redirected to the index page of my pricing_interval, as the values will be re-generated. Manually generating a range proves that my helper methods work.
How would I build a form that on submit would send parameters to a function in the form of (date,integer,name) so that it could immediately begin work whilst redirecting the user to server/pricing_intervals
Anything at all would help, I've spent hours over the past few days trying to get the rails form syntax working properly to no avail, a really straightforward guide to what I would implement to get this working would be amazingly appreciated.
I've looked through the form guides, as I'm not creating an object, but merely parsing params, there's got to be an easy way to do this, right?

You can use the rails form helper hidden_field_tag to put in whatever form fields you want. They are added to the params hash that your controller will see. You don't have to only send form fields that correspond to an ActiveRecord model.

Related

A way to make use of form automagic for a controller without a model

I have a controller without a model that handles a very cyclical task.
The user is basically filling out a form, sending it up to the server for some minor analysis, and then the server regurgitates nearly the same thing back to the user.
The user makes some adjustments, and the process starts over again.
There is nothing to save or store from this process, so it doesn't have a model.
The form i am working with has a large number of fields to deal with. Is there a way I can pass the params hash back into the view with the least amount of mess getting the fields repopulated?
Basically, I would want to tweak a couple of values in the params hash, but more or less pass the hash back so that it can repopulate the view nearly exactly how it was when it was submitted.
The old way of using OpenStruct seemed ideal.
Will this help?
In controller action, just initialize a variable like #params (or some thing like this), so that can be able to use all the values in the params can be available in that view page.
Maybe an ActiveForm is good for your application. It use to manage (new/create/validate/...) forms with no or several models.
https://github.com/realityforge/rails-active-form

Handling forms in rails

I am a little confused with forms in RoR.
I have a contacts page with a corresponding method in my controller. What I am trying to do is have a form so people can leave a message. I will then be emailing that message to myself.
I have the form and everything created. However, I am a little confused on how I would actually get the data from the form once they hit the submit button. would it just be accessible through my contacts method in my controller using params[:message]?
Also, what if I had multiple forms on one page? Would I just be doing params[:message1], params[:message2], etc., in the contacts method in my controller?
Take a look at this answer for details on what exactly the params hash is. When you reference params[:message], this implies that you are POST'ing to your controller action with, say, "message[subject]=abc123", which Rails helpfully turns into a hash with a key like: params[:message]['subject'].
If you're looking to send an email, check out mail_form, which simplifies creating a non-database-backed model that get's turned into an email.
Lastly, about having multiple forms on a page: each form POST's to its action and includes all of the form elements that are children of that form in the DOM. So, only the children of that message will actually be included in the params[:message] hash. You can use fields_for to have multiple models within a single form.

Need some advice on doings things the Rails way

I've built a Rails app that's pretty simple... you send a request to a certain web page, it automatically generates a report and saves it to a file locally on the server. The report that generates is by default created for the current day. What I would like to do is allow the user to enter the date in the url which they would like to have the report generated for turning my little one trick pony into something a little more useful.
As it stands right now I've built all of the useful report generation code into the index action of the the home controller but can't help but feel that it really belongs in a model instead of the controller, but I'm not quite sure how to make that transition.
Any advice from you seasoned rails vets would be greatly appreciated.
Thanks.
The code in my index action....
Basically the index action get's called and my program figures out what day it is, then uses the date to make a request to another API which then returns the necessary information in the form of an object. I then simply go through the object, gather the info I need and generate a text file with that information. The view for the home controller just prints a message saying the report has been generated and provides the path to it.
I would like to stress that I would like to use a url like mysite.com/report/20110803 to provide my controller with the information about the date the report should be run for.
You are thinking correctly that this code belongs to a model. Ideally, the Report model. A controller should generally just feed the view with instance variables, handle flash messages and so on. The logic should be in the model.
That said, i would do it like this: Create a model method that generates the report you want. Then, execute that method in the controller and get back the report you want based on the timestamp that is passed into the model method.
Then, would have this in the controller:
redirect_to new_report_url, :stamp => the_stamp_value
I think you get the idea. You just need to have a simple route that expects a stamp value and you are good to go :)

Rails Form Validations for Multi-Model Forms

I am trying to build a Rails app with multiple models in a single form, and multiple forms on a single page. To make that work (according to my limited knowledge), I have to drop out of the scaffold code and the "form_for :model" helper and use "form_tag" instead. However when I do that, I lose the ability to automatically catch and report form validation errors in the view (with the error message in the flash[:error] and have the invalid fields highlighted.
If I have a controller method for a form that has to validate data from multiple models, how to I pass the validation errors back to the form? What do I have to do to get the invalid fields highlighted?
(For the longest time I didn't "get" Rails forms, because I thought they were useless Ruby wrappers for HTML code. Now that I am working in a non-Rails environment, I realize how much hard work they save because validation is tied to ActiveRecord validaions, and if a validation fails, the form can be reposted with the invalid fields hightlighted and a useful message in flash[:error]).
To add multiples models to a simple form, after rails 2.3 you just have to add accepts_nested_attributes_for in your model, the model that will be connected with your controllers and views, change the views to support information from another models (with field_for) and maybe build the reference objects in your controllers. Check these links:
http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes.
http://github.com/alloy/complex-form-examples

Rails best practice for having same form on multiple pages

I am developing an Rails 2.3.1 Web site. Throughout the Web site, I need to have a form for creating Posts on various pages (Home page, Create Posts page, Post listing page, Comment listing page, etc. -- suffice to say this form needs to be on many pages served by a variety of controllers). Each of these pages displays a wide variety of other information that is retrieved in the corresponding controller/action. Ex, the home page lists latest 10 posts, content pulled from the DB, etc.
So, I've moved the Post creation form into its own partial, and included this partial on all the necessary pages. Note that the form in the Partial POSTs to /questions (which routes to PostsController::create -- this is default rails behavior).
The problem I am running into is when the the Posts form is not completed correctly, by default the PostsController::create method render's questions/new.html.erb, even if the form was submitted from the home page (/home/index.html.erb).
I tried changing the form in the partial to submit the "submitting_controller" and "submitting_action", and in PostsController::create, when #post.save? == false, I render action => "../submitting_controller/submitting_action" (Which is slightly hacky, but lets you render actions from non-PostsController's).
This seemed to work OK on the surface. The incomplete form was rendered in the view that submitted it with all the correct #post.errors message, etc. The problem was ALL the other data on the pages didnt show up, because the actual submitting_controller/submitting_action methods weren't called, just the associated view. (Remeber, I did a render which preserves instance objects, rather than a redirect_to which does not preserve the #post instance object which has all the error messages and submitted values.)
As far as I can see I have two options:
1) I can store the #post object in the session when #post.save? fails in PostsController::create, redirect_to submitting_controller/submitting_action, at which point i pull the #post object out of the session and use it to re-populate the form/error messages. (As far as I understand, storing objects in the session is BAD practice in rails)
2) I can move all the logic used to pull non-post creation form data from the various submitting_controller/submitting_action, put it in the ApplicationController, create a giant switch statement in PostsController::create for submitting_controller/submitting_action and call the methods in the ApplicationController to grab all the extra data needed for each submitting page's render.
Thoughts on the best way to do this within Rails?
By any chance is your Post model in a belongs_to relationship with each model who's controller you'll be using to render your form? Are you doing any special processing in the Post controller beyond Post.create(params[:post])?
If you answered yes to the first question and no to the second, you could get by with minimal mangling by adding accepts_nested_attributes_for to each of the controllers on which a user can create a post.
Regardless, Robertpostill is correct in that this is probably when to start looking at AJAX, to just replace the section of the page. The only problem is what to do if a user has javascript disabled. Personally I like to do design for the non-javascript case and add convenience methods.
As for thoughts on what you consider your two options,
1) I've used this method to store a shallow copy of an object in the flash hash. Preserving it across redirects. However this might not work for you given the variable nature of posts. As you can only send about 4K worth of data, and that includes other information in addition to your shallow copy.
2) See robertpostill's response
This is about the point that you move from full page updates to updating sections of a page through the use of AJAX. There are a bunch of things you should consider but the most rails-esque approach would be to split the response between an AJAX response and a plain HTML response. Check out this ONLamp article, this register article or the awesome agile web development with rails book. Essentially your controller renders a new div replacing the old div containing the result of submitting the partial.
In your question you mention two approaches and so I'll try and give you some pointers on why and why not here:
Option 1) Ths option is not so bad with a couple of tweaks. The main tweak is is to store the object in a serialized form in the DB. Then simply pass around the ID of the serialized object. Your upsides are that the session data gets persisted so recovering a a session is neater and your session stays light. The downside of this is that having a bucket of session cruft in your DB will pollute your app and you'l need to do some thinking as to how you expire unused session cruft from the DB. I've never seen this end well...
Option2) Eeek not inside the application_controller! :) Seriously, keep that as your weapon of last resort. You can pop things insde the helpers though and get access to those methods inside your controllers and views. However the testing of that stuff is not so easy so be careful before choosing that route. Switch statements can be replaced in OO apps with a little thinking, certainly in his case you can use option hashes to get a railsy way of having some smarts about the state of the app at the time the request is made.

Resources