Rails: How to pass params of multiple checkbox to the model - ruby-on-rails

i built this form that generate me some chebox with value like "U6", "U8" eccc
<%= form.label "Seleziona Categorie" %>
<% TeamCategory::NAMES.each do |category| %>
<%= check_box_tag 'categories_selected[]', category -%>
<% end %>
Now i have to pass the value of selected check_box to a method in my model.
Now is:
def create_tournament_team_categories
TeamCategory::NAMES.each do |name|
team_category = TeamCategory.where(name: name).first_or_create
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
I would like to replace the TeamCategory::NAMES.each do with "selected check_box each do" and TeamCategory.where(name: name) with the value selected.
Thank you in advance

I am a newbie with Rails. What I see is that you took the part of the form to create the team, right?
For your code straight forward it could be:
<%= form.label "Seleziona Categorie" %>
<% TeamCategory::NAMES.each do |name| %> #you are looping through team category NAMES constant
<%= check_box_tag 'category_names_selected[]', name %>
<% end %>
Your form as is allows more than one category to be selected.
For the method:
def create_tournament_team_categories(category_names_selected)
category_names_selected.each do |name|
team_category = name
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
you will probably use this method in your teams_controller.rb. In the controller, you should be able to retrieve from params a freshly created array of selected names with something along the lines with this.
#category_names_selected = params[:category_names_selected]
I do not know how complicated your app is so it might also be nested under ["team"][:category_names_selected] or ["team"]["category_names_selected"] in your params hash.
To see the exact structure of the params hash and adjust the equation above you can add for example require 'pry' at the top of your controller file and then but the binding.pry just after the part where your method is executed. When you restart the server and the app hits this part of the controller you should be able to see the exact structure of your params hash in the terminal.
You can then pass the array to the method that you can call in the controller. Do not forget to add :category_names_selected to the strong params in the controller. I hope this helps.

Controller on line 30
def create
#tournament = Tournament.new(tournament_params)
#tournament.sport_club = current_user.sport_club
#category_names_selected = params[:category_names_selected]
if #tournament.save
redirect_to tournaments_path, notice: 'Torneo creato con successo'
end
end
Method create_tournament_team_categories in the model
after_create :create_tournament_team_categories
def create_tournament_team_categories(category_names_selected)
#category_names_selected.each do |name|
team_category = name
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end

Related

How to pass a variable from a controller, to a view, to the controller again, in Rails?

If I have the #mis_clases array variable in the controller:
bloques_controller
def new
#bloque = Bloque.new
#mis_clases = Array.new
end
And I try to pass it to view, to fill it with clases:
form.html.erb
<div class="card-body">
<%= form.fields_for :clases do |clase| %>
<%= render partial: 'clase_fields' %>
<% #mis_clases << clase %>
<% end %>
</div>
And access it back in the controller:
bloques_controller
def create
#bloque = Bloque.new(bloque_params)
#mis_clases.each do |clase|
# Do something
end
...
end
I want to access the variable again when I save the form, but it throws this error:
The naming instance variable might be little misleading, but you need to remember that every new request to controller goes to new instance of Controller Class, so even if you create #mis_clases in #new, when reaching #create there is new instance without any variables set, and having nothing in common with recent one but class name.
You should pass variables as field values in form.

In Ransack update ranackers dynamically when a model gets updated

I have Company Customer and CompanyCustomerField models. Customers store the hstore values in a column "properties" - the keys are from the CompanyCustomerField#name field. When a new CompanyCustomerField get created i need to add the #name to ransack to make them searchable.
When a new CompanyCustomerField gets added and I go to the search form I get
undefined method `*_cont' for #<Ransack::Search:0x00007ff670100978>
because the new field is not available for searching. If i shutdown my fails server and reboot it works because it gets it into ransack.
I don't know how to dynamically add the functionality into ransack. Any ideas greatly appreciated.
Customer.rb. this puts all the searchable fields into ransack but doesnt update it when new ones get added. because this only gets called once.
class Customer < ApplicationRecord
# ['favorite_color', 'receive_email_marketing' etc etc]
CompanyCustomerField.pluck(:name).each do |name|
ransacker name.to_sym do |parent|
Arel::Nodes::InfixOperation.new('->', parent.table[:properties], Arel::Nodes.build_quoted(name))
end
end
end
here is the search form:
#customers/index.html
<%= search_form_for #search, remote: true do |f| %>
<% current_company.customer_fields.each do |field| %>
<%= render "customers/search_fields/#{field.field_type}", f: f, field: field %>
<% end %>
<% end %>
#customers/search_fields/text_field
<%= f.label (field.name + "_cont").to_sym, field.name.humanize %>
<%= f.text_field (field.name + "_cont").to_sym %>
....
Even if moving reloading to controller, still same result.
CustomersController.rb
def index
Customer.reload_ransacker
#search = current_company.customers.includes(:owner).ransack(params[:q])
#customers = #search.result.page(params[:page])
end
Customer.rb
def self.reload_ransacker
puts "==="
puts "reload ransacker"
puts "==="
CompanyCustomerField.pluck(:name).each do |name|
ransacker name.to_sym do |parent|
Arel::Nodes::InfixOperation.new('->', parent.table[:properties], Arel::Nodes.build_quoted(name))
end
end
end
ActionView::Template::Error (undefined method `foo_cont' for #<Ransack::Search:0x00007fba3c05d5b8>):
SOLUTION:
needed to override:
module Ransack
module Adapters
module ActiveRecord
module Base
def ransacker(name, opts = {}, &block)
#ransackable_attributes = nil
self._ransackers = _ransackers.merge name.to_s => Ransacker
.new(self, name, opts, &block)
end
end
end
end
end
#ransackable_attributes needs to be reset to nil so in def ransackable_attributes(auth_object = nil) the instance var is nil and can reload
should be considered a bug in ransack.

Controller, Model, View. Confusion with passing params

I have a simple self method defined in my model.
def self.search(name, type)
#handle name
#handle type
end
My confusion is with regards to the view & controller. Passing the correct values (or using the correct syntax).
In the view, a simple form.
<%= form_tag(index_path, method: :get) do %>
<%= label_tag :type, 'Type' %>
<% type_array = ["Foo", "Foo_One", "Foo_Two", "Foo_Three"] %>
<%= select_tag :type, options_for_select(type_array, selected: params[:type]), include_blank: true %>
<%= label_tag :name, 'Name' %>
<% name_array = ["Foo", "Foo_One", "Foo_Two", "Foo_Three"] %>
<%= select_tag :name, options_for_select(name_array, selected: params[:name]), include_blank: true %>
<%= submit_tag "Filter" %>
<% end %>
Confusion One
Under options_for_select, should it be select_tag :search or select_tag :type? Should it be selected: params[:search] instead??
In the controller
def index
#foo = Foo.all
#variation 1 that i tried
#foo = #foo.search(params[:search]) if search(params[:search]).present?
#variation 2 that i tried
#foo = #foo.search(params[:name,:type]) if search(params[:name,:type]).present?
#variation 3 that i tried
#foo = #foo.search(params[:name][:type]) if search(params[:name][:type]).present?
end
Confusion Two
Variation 3 kind of makes the most sense to me. But i dont see the self.search getting called. Also it throws an error (no implicit conversion of Symbol into Integer).
I'm not sure if the error is with my forms too?
Clearly i'm not very proficient with knowing where to pass the params and "collect" them. I've tried reading the ruby documentation but had a hard time understanding it.
I think the bigger picture would be, whats the proper syntax (or way to collect arguments) in a form for a method?
Confusion 1: It doesn't matter what the select_tags are called in your case as you don't seem to have it tied to an actual model attribute, but 'name' and 'type' are quite confusing simply as there are HTML attributes name and type on input fields. Still, it will still work the way you have done it and the 'selected' options look just fine.
Confusion 2: You need to access them individually from the params hash:
#foo.search(params[:name], params[:type]) if params[:name].present? || params[:type].present?
However, you have defined it as a self method as so:
class FooClass
def self.search(name, type)
# blah
end
This means you can't access it on an instance of the class, i.e #foo.search, you would call it from the class itself:
FooClass.search(params[:name], params[:type]) if params[:name].present? || params[:type].present?
If on the other hand you didn't have the 'self', as so:
class FooClass
def search(name, type)
# blah
end
The you could do:
#foo = FooClass.new
#my_var = #foo.search(params[:name], params[:type])
First off change self.search to just search because your index method in your controller is using an instance of your Foo model. when you do self.method that is a class level method and essentially works without having to create an instance of your class, which in this case is your Foo class.

Rails: simple 'Setting' model with key, value attributes

I’m new to rails and I’ve a pretty simple situation to solve but I cannot figure out how to proceed with it.
I want to create a simple ‘Setting’ model with key, value attributes. ‘SettingsController’ may contain 2 public methods only index and update. Only index action will have a view file with a form whose fields will represent each record of the ‘Settings’ table.
I want to be able to define some permitted keys (may be using some private method) and I want the form to create or update the record of relevant fields on submitting the form to update action.
Now, I don’t know exactly what code should I use in controller for index and update actions and in the index view file for the form which can create/update multiple records at the same time and can show updated values all the time. How do I proceed with it?
Update # 1:
I've managed to write some controller actions as below (based on some tutorial):
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The form code in index view template is given below:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
This forms saves the values correctly in the database but the saved values doesn't persist in form fields.
Maybe the problem is in the index action. Setting.all returns an array of Setting record, not a hash like { key1: value, key2: value } which I think you are trying to achieve. The form, therefore, displays data improperly. You can try this:
def index
#setting = {}
pairs = Setting.pluck(:key, :value)
pairs.each { |key, value| #setting[key] = value }
#setting
end

"First argument in form cannot contain nil or be empty"

I have difficulties with ruby on rails syntax.
I got this error
First argument in form cannot contain nil or be empty
class PersonalsController
def index
end
def create
#personal = Personal.new
end
def new
#personal = Personal.new
end
def show
#personal = Personal.find([:id])
end
end
index.html.erb
<%= form_for #personal do |f| %>
<%= f.label :title %><br>
<%= f.text_field :title %>
<%= f.submit %>
<% end %>
the value of #personal is nil that's why you are getting error.
Change you code like this
def index
#personal= Personal.all
end
form_for is helper method
check with this link form_helper
The error is generated since #personal was not set in the controller. So either you add a #personal = Personal.new to the index method, or set it to a specific database entry, e.g., #personal = Personal.find(1)
However, it seems strange that you have a form displaying a single record in the index view.
More likely, you want to have the form in your new or edit views (in the former case you typically use new, while in the latter case you would use the find method to find a specific record and let the user edit it).
In the index method, you usually use the controller to select a group of records (e.g., #ps = Personal.all to get all the records) and iterate over them in the view (#ps.each do |person| .... end)
P.S. The show method should probably use Personal.find(params[:id]) instead of Personal.find([:id])

Resources