Rails dynamic field additing (multilanguage) - ruby-on-rails

I have a set of 2 fields (title, description) and some locales (English,Swedish) for translation.
When you visit the page you can only see English set fields. But, user must be able to provide additional translations (if he wants). For that purpose I use "globalize3" and "batch_translations" (https://github.com/fidel/batch_translations) gems.
Language selection is done like a dropdown list. Once you select a language, new set of fields should appear just below the previous set.
Problem itself kinda resembles the one Ryan covered in his screencasts: http://railscasts.com/episodes/197-nested-model-form-part-2
BUT, there is one major difference - forms must be translated as well.
At first, I thought that everything is OK, I won't have any problems passing a form builder reference to my controller's remote action, that is responsible for rendering the partial with selected locale and embedding it.
But, it turned out that there is no possibility to pass the reference by object_id (Garbage Collector destroy's it).
Then I found that you can instantiate the FormBuilder in controller, something like this:
f = ActionView::Helpers::FormBuilder.new(:name, #object, view_context, {}, nil)
If I do so, only first-order fields are working, like this: f.text_field
But, globalize3 and batch_translations are using nested_attributes:
<% f.globalize_fields_for locale do |g| %>
g.text_field :title
g.text_area :description
<% end %>
And for some reason (I think it is because of the incorrect view_context), system throws an error:
ActionView::Template::Error (undefined method `<<' for nil:NilClass)
Any good solution to this problem ? Thanks!

Related

How do I create a drop down in a Rails form where the user can change the default value?

I'd like to have a drop down in my Rails form where users can select an area of a city, e.g. "Marchmont", "New Town", "Baberton" etc, when adding an order. I'd like that once they have made a selection, this will then be the default selection for the following times they use the form to add an order (so that they don't have to keep selecting it) but also that they can change their selection at any time. Hope that makes sense. I'm using the Simple Form gem. Thanks in advance! :)
#Steve
I will make a couple of assumptions.
1.) you know how to create forms within the rails templating engine.
2.) you understand how to create a dropdown menu using the Simple Form gem
So you have a couple of options based on what you actually want to accomplish. Based on what you are briefly describing, it sounds like you have some kind of an e-commerce/checkout situation that you want auto-completion to make it easier for a user.
there are a couple of approaches to storing this data.
Saving the user Data.
1.) Save it right on the user model under district_of_last_order
2.) Save it right on the order model that a user has_many orders. Then you can pull the first order's city district and select that
Personally I would lean on #2 as you probably want to be able to tightly couple the order with the user and saving that information twice is redundant since you can always do something like current_user.orders.first.district or whatever,
in your ERB where you build the form you can then do something along these lines:
<%= simple_form_for(#order) do |f| %>
... other input fields
<% if current_user.orders.first %>
<%= f.input as: :select selected: current_user.orders.first.district %>
<% else %>
<%= ... your regular dropdown menu here without the default %>
<% end %>
... rest of your form
If you have the option of using gems, I have had good results with select2-rails.

Rails using child value in a nested form

So, I have a nested form where Shelter has many Cats (just using cats as an example to melt the hearts of those eager to help).
So, in my nested form I can use:
<%= f.object.shelter_id %>
which gives a value when I run the application. But, and here is the cute cat's but:
<%= f.object.shelter.name %>
doesn't work, nor does:
<%= Shelter.find(f.object.shelter_id).name %>
Above statement gives an error can't find Shelter where 'id'=
One would think the value would be passed to the query as it is displayed when the app is run? How do I access the associated values in the form? (Its only in Edit, my Show and other controllers and views work fine.)
And yes, the associations are declared in my models.

How do I add autofocus to a form field if it is the edit form?

I am new to ruby on rails and working through the Rails Tutorial book and also Rails Programming from pragmatic studio. However for my project I need to find solutions now so sad I can't spend more time on the researching.
My question is, once I am able to add, show and edit forms I am being instructed to create partials, ie _forms.html.erb and then rendering those forms on the edit, show and new pages.
On my _forms.html.erb partial, how can I implement some flow using if statements based on the page that the form is being rendered for.
For example, when _form.html.erb is being rendered for the show page I want certain form_for labels/fields to be set to readonly: true. At the bottom of the form I want submit, edit, change buttons based on the page aswell.
So far I am trying to use the parems[:action] == "new" or "edit" etc to implement the control flow as follows:
Old code under the edit.html.erb file:
<%= f.label :patform_type %>
<%= f.text_field :patform_type,autofocus: true %>
New code under the _form.html.erb file:
<%= f.label :patform_type %>
<%= f.text_field :patform_type %>
<% if params[:action] == "new" %>
<%= ,autofocus: true %>
<% end %>
My original code has been influenced by these posts:
Rails not editable text field
How to disable all form_for input fields in Ruby on Rails app?
Once I get this right then I am hoping I can use it to wrap it around other elements like the submit, edit buttons etc or other fields.
Also if someone knows a better way can you please let me know as I don't know what I don't know.
Thanks for any assistance/ideas you can provide.
You probably have to stick with a bunch of if/else statements if you need such depth of logic within the form, but I would recommend having the forms typed into their respective erb file, and not be rendered from a partial with a ton of logic.
A partial is meant for repeated code, and your code is not exactly what I would describe as repeatable. It is also not immediately understandable and will contain code that is essentially a waste of time to read:
For example, if I am reading the edit action's view and I see:
if params[:action] == "new"
It will be testing for an action that isn't even relevant to the current view, unlike logic such as:
if current_user.admin?
which will be more suitable for partial-based logic.
Hope that helps, enjoy RoR

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}"]' %>

Send an extra parameter through a form in rails 3

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.

Resources