Using collection_radio_buttons on an object array in rails - ruby-on-rails

I have an array of objects and i want to be able to display them using a collection_radio_button but it seems like collection_radio_buttons only works on arrays or ActiveRecord Objects. Is there any way to build a collection_radio_button using an array of objects?
This is my array of objects
[{:image_url=>"https://assets.braintreegateway.com/payment_method_logo/visa.png?environment=sandbox", :card_type=>"Visa", :last_4=>"0004", :expiration_month=>"10", :expiration_year=>"2019"}, {:image_url=>"https://assets.braintreegateway.com/payment_method_logo/visa.png?environment=sandbox", :card_type=>"Visa", :last_4=>"0004", :expiration_month=>"11", :expiration_year=>"2019"}]
This is the code i tried writing but it doesnt work
<%= collection_radio_buttons("cards", :card, #payment_methods, item_wrapper_tag: false) do |b|
b.label { b[:last_4]}
end %>
Any help is appreciated

The collection_radio_buttons helper is looking for an array of objects that will respond to the text_method input - which is then used for the radio button label generated.
The quick'n'dirty way to get your code working would be to turn your array of hashes into an array of objects that respond to methods named after the keys, IE we can turn them into OpenStructs with:
#payment_methods = #payment_methods.map { |pm| OpenStruct.new(pm) }
Passing this new array of OpenStructs should now print out what you're looking for, without the extra block:
<%= collection_radio_buttons(:cards, :card, #payment_methods, :last_4, :last_4) %>
You may want/need to alter the other inputs - :card, :cards or :last_4 - to get the desired result that'll work with the form you're building.
Another option would be to simply build the radio buttons yourself, without using the built in collection_radio_buttons helper... something like:
<% #payment_methods.each do |pm| %>
<%= radio_button_tag 'cards[card]', pm[:last_4] %>
<%= label 'cards[card]', pm[:last_4] %>
<% end %>

Related

Using acts-as-taggable-on in a collection_select form

I am having a model Movie that has tags, using the gem acts_as_taggable_on.
I can do this in the form:
<%= form.text_input :tag_list %>
and it works - it shows the tags associated with the movie, and I can add tags, separated by commas, all fine.
I am now trying to use a collection_select helper, and I had two ideas: using ":tag_ids" as first parameter, which makes DISPLAYING the tags assigned to movies properly (as selected), but not updated, or using ":tag_list" which makes tag updates work but not displaying...
<%= form.collection_select(:tag_list, #all_tags, :id, :name, { }, { class: 'font-size-m', id: 'tag-select', multiple: true }) %>
(I define #all_tags in the controller as follows):
#all_tags = ActsAsTaggableOn::Tag.all
Not sure how to use a collection_select with these tags... any help appreciated!
The problem actually was that I used :tag_list as permitted parameter and not tag_list: [].
Turns out that depending on how you use acts-as-taggable-on - you either deal with a string (with comma separated values) or with an array. I am still not quite sure how exactly that works but - whenever tags are not saved now during my development, I first try to switch the permitted parameters :)

Storing an array of integers with ruby on rails

I'm trying to take in an array of numbers through the use of a form. In my database I have the variable as:
t.integer "home_goal_min", default: [], array: true
In my form I have:
<%= f.label :minutes_of_home_team_goals %>
<%= f.fields_for 'home_goal_min[]', [] do |p| %>
<%= f.number_field :home_goal_min %>
<%= f.number_field :home_goal_min %>
<% end %>
In my controller I also added in the parameter as an array but this still hasn't solved my problem:
def result_params
params.require(:result).permit(:home_result, :away_result, {:home_goal_min => []}, {:away_goal_min => []})
end
However, when I use the form and enter data, I then proceed to check the database through the console but it still appears empty and I just get:
home_goal_min: []
I'm wondering what I need to do to get the numbers entered in the form to be saved in the database?
Also is there a quick way to have the form part for home_goal_min as a text field and allow the user to enter the numbers split by comma, for example as: "23,45,52" would populate home_goal_min with the array [23,45,52]
You have <%= f.number_field :home_goal_min %>
Shouldn't it be <%= p.number_field :home_goal_min %>?
Edit:
I don't think you can submit Arrays through forms without using javascript. Here's the simplest solution:
In the form:
<%= f.text_field :home_goal_mins_list, placeholder: "A comma-separated list of times of the goals" %>
In the model:
def home_goal_mins_list=(value)
self.home_goal_mins = value.split(",").map(&:strip)
end
def home_goal_mins_list
self.home_goal_mins.map(&:to_s).join(", ")
end
HOWEVER
If I were you, I would just make this data into its own table. Generally, it's a bad practice to use array fields unless your database is already storing a lot of unstructured data
Firstly, you can pass in array through a form.
It is done by appending [] to the end of the name of the inputs.
For example, your form contains:
<input name='home_goal_min[]' value='100'>
<input name='home_goal_min[]' value='200'>
<input name='home_goal_min[]' value='300'>
Upon form submission, your params will look like:
params[:home_goal_min] => ['100', '200', '300']
Docs here:
http://guides.rubyonrails.org/v3.2.9/form_helpers.html
Section 7.1 Basic Structures
However, reading through your situation, I don't think you need to pass in an array. As Ben noted in his answer, you can parse a single field before saving it. I would suggest doing it in the form object, as model has nothing to do with parsing form data.

Rails output polymorphic associations

I want to implement a search functionality in my Rails app by using the pg_search gem. I've set up everything like it says in the documentation. Then I've set up a search controller with a show action:
def show
#pg_search_documents = PgSearch.multisearch(search_params)
end
The search itself works but I have a really annoying problem in my view. Whatever I do, it always outputs an array of PgSearch::Document objects. Even when I only write this in my view:
<%= #pg_search_documents.each do |document| %>
<% end %>
I get this (I've shortened it):
[#<PgSearch::Document id: 2, content: "…", searchable_id: 28, searchable_type: "Vessel">, #<PgSearch::Document id: 3, content: "…", searchable_id: 27, searchable_type: "Vessel">]
I know that pg_search sets up a polymorphic association which I've never dealt with before — could that be the problem?
Thanks in advance
<%= #pg_search_documents.each do |document| %>
<% end %>
This is a classic error, one I remember being puzzled over when I first started learning Rails. The mistake is using <%= %> with each. The return value of each is the array that you're iterating over (in this case, #pg_search_documents), and by using <%=, you're telling Rails to create a string from that array and insert it into your view. That generally isn't what you want: you want the view to be generated by the code inside the block you're passing to each.
Use <% #pg_search_documents.each do |document| %> instead (omitting the =) and you'll avoid the dump of the array's content.
You may also need to use .searchable as #blelump suggests, but I wanted to answer the other half of your question, as it's a common pitfall.
To get back to the original source model, searchable call is needed on these search result records, e.g:
<% #pg_search_documents.each do |document| %>
<%= document.searchable %>
<% end %>
You can also switch back to the source model within your controller, e.g:
#pg_search_documents = PgSearch.multisearch(search_params).collect(&:searchable)
Then, the #pg_search_documents will contain Vessel elements.

Rails nested form with a "select" form element giving me "undefined method `merge' for #<ActiveSupport::SafeBuffer:0xb50d34b8>"

Background: My goal is for a view to display a list of "condition" has_many objects, which are themselves STI subclasses of a StateDescription. I want a user to be able to pick what type of state description they are from a drop down menu (which will conditionally display a different type of form, eventually)
Inside of my main forms, I am doing a nested form like this:
<%= f.fields_for :conditions do |e| %>
<li>
<%= e.select(:type, StateDescription.subclasses.collect{|x| x.to_s}, options_for_select(StateDescription.subclassSelectForms)) %>
<br>
<%= e.label :title %>
<%= e.text_field :title %>
</li>
<% end %>
This works just fine with the text field at the bottom there (I can change values and save them, etc). But when I try to do a select statement, it explodes.
Specifically, if I don't use e.select and just do:
<%= select(:type, StateDescription.subclasses.collect{|x| x.to_s}, options_for_select(StateDescription.subclassSelectForms)) %>
it renders just fine, but doesn't actually change any values as it is not associated with a model.
If I get rid of trying to have it display a value different than it submits and just do
<%= e.select(:type, StateDescription.subclasses.collect{|x| x.to_s}) %>
Then it works just fine(I can submit, the value is saved to the database, I can retrieve it, etc).
I can LEAVE it like this, but I had wanted to have my more human readable string display instead of a rails class thing (which might look like gibberish to a non-programmer end user).
So, my question is: Why do options_for_select break when nested and associated with a form, but dont' seem to when not associated with a form? Is it just a known bug? Am I doing something wrong?
Edit:
.subclasses is a standard rails calls which returns a list of subclasses for an object.
.subclassSelect forms goes through each subclass, and turns it into a hash of the form:
{subclass.to_s => subclass.human_readable_string} and compiles all of them into an array.
I know this array of hashes works, because if I do NOT put "e" on the front, it displays correctly and works "right" for what I have done (i.e. the subclass is returned correctly based on which human readable string I select from the drop down menu, but since it's not actually associated with any form, it doesn't get set in the controller).

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