Send an extra parameter through a form in rails 3 - ruby-on-rails

Is there a way to send an extra parameter through a form in rails 3?
For example:
<%= form_for #post do |f| %>
<%= f.hidden_field :extraparam, :value => "22" %>
<% end %>
but lets say :extraparam isn't part of the post model..
I have an unknown attribute error in the create method of the controller when I try this, any ideas?
(I want to use the param value itself in the controller for some extra logic)

Call hidden_field_tag directly. See: http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-hidden_field_tag
These helpers exist for all the major form field types, and are handy when you need to go beyond your model's methods.

The following worked for me in passing extra parameters from the view back to the controller that were a part of my model and not part of my model.
<%= hidden_field_tag :extraparam, value %>
Example usage
<%= hidden_field_tag :name, "John Smith" %>

Ya Paul is right. Hidden_field is associated with your model whereas the extra _tag fields are not. I'm not sure of your needs but It's generally recommended in the RoR community to avoid passing a ton of hidden_fields like you might do in a php application.
Ive seen some code where ids were getting passed around in hidden fields which rails takes care on its own if you know the best practices and take full advantage of the framework. Of course I'm just saying this as general info as there are sometimes better ways at accomplishing the same functionality. Good luck on your apps.

Related

Why is my Rails form helper written improperly?

I know I've written it wrong, but I'm looking at the documentation and can't figure out how.
My model is Quote and has three fields, body, attribution, and work, all strings. The form is intended to add a new quote to a page of quotations.
on main/index.html.erb
<%= form_for(:quote, url: {action: 'create'}) do |f| %>
<%= f.text_field :body %>
<%= f.text_field :attribution %>
<%= f.text_field :work %>
<%= submit_tag "Submit" %>
<% end %>
in main_controller.rb
def create
Quote.create(body: params[:body], attribution: params[:attribution], work: params[:work])
end
The form submits, and an entry is saved to the database -- but it's a totally blank entry. I'm not sure why. Help would be appreciated!
Three things:
The way rails forms are supposed to work, you're not meant to get body, attribution, etc independently, they should be wrapped up into a quote object. But...
In your form, your not properly binding an object to the form the way rails expects. You can read more in the documentation here: http://guides.rubyonrails.org/form_helpers.html#binding-a-form-to-an-object. You could also generate a fake scaffold rails generate scaffold HighScore game:string score:integer to generate a fake model and see an example of how it's supposed to work. The default scaffolding even has simple examples of how to deal with save errors.
Finally, as #Paven suggested, when you get confused, be sure to look at what's going on in your log - i.e. what params are being posted to your create action. That is always helpful and a good way to diagnose problems quickly.
Your form does't need the action argument. The form_for helper uses ActiveRecord objects to determine the path, meaning as long as you build your object correctly, you won't need to determine your path individually:
<%= form_for #quote do |f| %>
Secondly, you'll want to look at your create method:
#app/controllers/quotes_controller.rb
def new
#quote = Quote.new
end
def create
#quote = Quote.new(quote_params)
end
private
def quote_params
params.require(:quote).permit(:body, :attribution, :work)
end
The problem is you're not sending an ActiveRecord object to your form_for helper. You can read the explanation here:
In Rails, this is usually achieved by creating the form using form_for
and a number of related helper methods. form_for generates an
appropriate form tag and yields a form builder object that knows the
model the form is about. Input fields are created by calling methods
defined on the form builder, which means they are able to generate the
appropriate names and default values corresponding to the model
attributes, as well as convenient IDs, etc. Conventions in the
generated field names allow controllers to receive form data nicely
structured in params with no effort on your side.
In order to get the form working correctly, you need to be able to provide a valid ActiveRecord object (#variable), which the helper can use to determine the url etc
My code above helps you provide a new ActiveRecord variable, and allows you to use it in the form. This should allow the form_for method to send your data to the create method, which will then create & save an object in the db for you

What is the best way to display form data in rails?

I am very new to Rails.
I am looking for the most common and 'rails-like' way to display the output of form data. I know that Simple form and Formtastic are good options to write concise code and display input fields in a user friendly manner. However, I am looking for something slightly different, I want to display the data from these forms as output, and I want to do it in a similar and concise manner. I haven't been able to find anything the last few days that I have been searching around so I figured I should ask Stack Overflow.
What do you normally do:
Write custom helpers to be able to write concise code and display the output data?
Use Simpleform/Formtastic, disable the fields, and modify the css to
make it look the way you want?
Is there a common gem that does this? Or perhaps another way I haven't thought about.
First, thanks for the initial responses. I thought I should clarify my question. Since the answers don't quite hit the mark. I already have a show method in the controller, as well as a view template for it. Currently I am displaying each field individually in the form for about 12 fields using form_for. See example snippet below:
<%= form_for(#event) do |f| %>
<div class="row-fluid">
<div class="span6">
<%= render 'shared/error_messages' %>
<%= f.label :title %>
<%= f.text_field :title, :disabled => true %>
<%= f.label :start_date %>
<%= f.date_field :start_date, :disabled => true %>
</div>
</div>
<% end %>
I guess maybe a better question would be, is their an equivalent to form_for method that display data for users, not to edit it but just to read it? It seems like their would be a a standard way to do it that I haven't discovered.
The easiest way to build forms is to use rails g scaffold Example name:string This would generate the Model, Views, Controller, and the necessary database migrations for a Model named Example with a Name attribute that is a string.
You would then use html and css to style the view how you want.
There is a ton of useful info for you on the rails guides here.
Although this question is rather ambiguous, you must appreciate that this functionality is exactly what Rails is built for (submit data & be able to display / manipulate it somewhere else)
Data
The data in an MVC application is bound by one very important factor - a database
If you're submitting data through a form, your goal is to store it in your database, and display it in other views / controller methods
Therefore, the blunt question to your answer is to abide by MVC processes, and save your data to a central repository (database or other), which you can call later:
View
To get your data into your data store, you first need to submit it
The view part of MVC is where you can display your UI, and consequently is where you can put your form. There is a whole tutorial about how to design this here, but for demonstrations' sake, here's an example of how you'd use your form:
#app/views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
Controller
The data you input into your view will be sent to your controller on save
The data is sent via the HTML POST method to be read by Rails as a params[] hash. This hash contains all the sent items from your HTML form, and can be used like this:
#app/controllers/posts_controller.rb
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
end
private
def post_params
params.require(:post).permit(:title, :body)
end
Model
The .save method on your newly created Post object, basically tells your model to put the data into your database (or other data store), which you can then pull later (using the .find method or similar)
#app/models/post.rb
Class Post < ActiveRecord::Base
#stuff here
end
It's important to note your models don't store your data, they simply provide an interface (API if you will) to save the data into some sort of data store (namely, a DB)
Models are super important because they allow you to structure & relate your data, creating the ability to deploy really deep & powerful applications

Serialized attributes not evaluating properly with form helpers

I'm rendering a form with serialized attributes. The attribute serialization works fine under normal usage, but now i'm trying to serialize a hash. The view code looks like the following
<%= #item.seasonality_of_sales_pct.each do |key, value| %>
<%= eval("f.label :'seasonality_of_sales_pct[:#{key}]'") %>
<%= eval("f.text_field :'seasonality_of_sales_pct[:#{key}]'") %>
<% end %>
The error I'm getting is undefined method 'seasonality_of_sales_pct[:January]' for #<Item:0x007f01083edd38>. However, the line that is throwing the error is the second eval. The first eval evaluates just fine. I'm baffled as to why this might be happening.
In the controller, I am setting up an attribute like the following
#item.seasonality_of_sales_pct = {January: nil, February: nil, March: nil, September: nil}
Another question that could maybe be answered in the comments is: How bad does this code smell? I'm not sure how the rails community feels about metaprogramming like this. It hurts me a bit to do it, but seems to work most of the time
When you use form_for and then use f.text_field :some_attribute_name then the object you are building the form for (in your case #item) mush have an attribute named some_attribute_name.
You get this error because #item has no attribute or method named seasonality_of_sales_pct[:January]
I also would point out that there is no reason to use eval in your form, it is a serious security risk, as code can be injected.
I wanted to be a bit more thorough than Khaled's answer, which was sort of right. The reason that the first eval statement didn't cause the error was because f.label doesn't care what you give it. <%= f.label :fake_stuff %> will just create a label called Fake Stuff. I'm still not quite sure why the attribute didn't work. If I had f.text_field :seasonality_of_sales_pct, I got a text box full of my hash. Also, I got the labels to display the correct values.
I absolutely did not need to use evals here (I can hope it was only a moment of weakness). Just do
<%= f.text_field :'seasonality_of_sales_pct[:"#{key}"]' %>

What is the proper use of the check_box form helper?

I have two models - Client & Topic, with a HABTM relationship between them.
I am trying to generate a series of checkboxes of the topics, on the Client form partial.
This is what I am doing:
<% Topic.all.each do |topic| %>
<% checked = #client.topics.include?(topic) %>
<%= f.label(:name, topic.name) %> <%= f.check_box #topics, topic.id %>
<% end %>
This is the error I get:
undefined method `merge' for 1:Fixnum
I know one solution is to use check_box_tag, but that forces me to do the record updating of the associations manually.
So I would rather use the form_helper for the checkbox tag. The docs are a bit confusing to me.
How can I get this to work with f.check_box.
Thanks.
The code confuses me. What #topics contains? If it's a collection of of Topic then why you are directly accessing Topic model in the view? It would be:
#topics.each.do
rather than you
Topic.all.each
Moreover, you are using #topics as collection inside a loop. How check_box will generate checkbox from a collection?
Please look at the following things:
accepts_nested_attributes_for. you will need this to set in Client model in addition to Client has_many Topic association
fields_for Otherwise, rails will not have any idea that you want to update topic model from this same form.
Check this screencasts to get an idea how you can make it work
For whatever reason, the form helper doesn't work with check_box.
So, this is the code that works:
<%= check_box_tag "client[topic_ids][]", topic.id, checked %>
According to other answers for similar questions, the helper f.check_box is model bound and the value supplied to the checkbox is implicit from the model on the form. The issue is, I can't figure out how to get the implicit value of the form_helper to produce the correct tag - i.e. client[topic_ids][], so I have had to resort to check_box_tag.

Rails: Fields_for without a scope?

Is there a way to use fields_for with in a form without having a scope?
For example:
<% fields_for "user[]" do |x|
<%= x.text_field :name %>
<% end %>
Without the user model being loaded in memory?
I got it working using territory[user][][name], but I would like to keep it in ERB.
I think the answer would be 'no', since those form_for and fields_for would try to determine default value from that given instance variable.
However, I think if you want to lower memory usage from loading that model, you might try to create a mock-up model to return nil values, and create a instance object from that one instead.
is there any specific reason you need to use form_for specifically? Its really designed to be used with an instantiated model object.
Alternatively, why don't you just use the regular form helper tags. You can define it as follows:
<%form_tag :my_form do %>
<%= text_field_tag :foo, :bar %>
<%end%>
You may want to check the documentation for action view to see how it all works.

Resources