Why is a permitted variable throwing an undefined method error? - ruby-on-rails

Going from ruby-2.1.2#rails-3.2.18 to ruby-2.4.0#rails-5.0.2.
The following stanza throws an undefined method `reqdb' for #
<%= form_for :page, :url => {:odbinsight => :reqdb} do |f| %>
<% if #mywkbks != nil %>
<%= f.collection_select :reqdb, #mywkbks,:name, :title,
:include_blank => false, :prompt => "Workbook?" %>
<% end %>
I have also used #reqdb, same error:
The log shows data from the controller:
DEBUG:0:#reqdb = nil |#reqpg = nil|#name = nil|#mywkbks=[#<Page id: 1,
name: "NB001", title: "Something">, #<Page id: 2, name: "dev", title:
"dev prototyp workbook">]
(Note: pglmt and reqdb are not table column names, but temp variables.):
def page_params
params.require(:page).permit(:name, :title, :body,
:accs_level, :parent_id, :navlabel,
:position, :redirect,
:action_name,:controller_name, :pglmt, {:reqdb => []})
end
I have also had the stanza with just:
....pglmt, reqdb) with the same error resulting.
Thanks for your comments.

Related

Ruby on Rail Nested Attributes do not save to database

I am trying to create a form that updates 2 tables - commission_type and commission_tier.
I created the models, controller and form but when I submit it, my commission_tier table does not update. Only my commission_type table updates.
Can someone take a look at my code and tell me what I am doing wrong? I have combed through my code trying to find the mistake, and I cannot find it.
My models
class CommissionType < ApplicationRecord
has_many :commission_tiers
accepts_nested_attributes_for :commission_tiers
end
class CommissionTier < ApplicationRecord
belongs_to :commission_types, optional: true
end
My controller
class Admin::CommissionTypesController < Admin::BaseController
def index
#commission_types = CommissionType.all
end
def new
#commission_type = CommissionType.new
#commission_type.commission_tiers.build
end
def create
#commission_type = CommissionType.new(commission_type_params)
if #commission_type.save
redirect_to admin_commission_types_index_path
else
render "new"
end
private
def commission_type_params
params.require(:commission_type).permit(:name, :active, :allow_mass_update, :plan,
commission_tiers_attributes: [:id, :increment_value, :rate, :commission_type_id])
end
end
My form
<%= simple_form_for #commission_type, url: admin_commission_types_index_path, wrapper: :bootstrap2, :html => { :class => 'form-horizontal' } do |f| %>
<fieldset>
<legend>Properties</legend>
<%= f.input :name, label: 'Commission Name' %>
<%= f.input :active, as: :boolean, label: 'Active?', label_html: { class: 'padding-top' } %>
<%= f.input :allow_mass_update, as: :boolean, label: 'Allow mass update?', label_html: { class: 'padding-top' } %>
<%= f.input :plan, input_html: {id: 'dropdown'},
label: 'Commission Type',
collection: [ ['Select One..', 'select'], ['Flat', 'flat'], ['Flat +', 'flat_plus' ], ['Promotional', 'promotional'], ['Straight', 'straight'], ['Waterfall', 'waterfall'], ['Sliding Scale', 'sliding_scale'] ],
selected: 'select'
%>
</fieldset>
<fieldset id="flat">
<legend>Flat Commission</legend>
<%= f.simple_fields_for :commission_tiers do |builder| %>
<%= builder.input :rate %>
<%= builder.input :increment_value %>
<% end %>
</fieldset>
My form is displaying and working
UPDATE
Some additional details
CommissionType column values = [:name, :active, :allow_mass_update, :plan]
CommissionTier column values = [:id, :increment_value, :rate, :commission_type_id]
Also, when I submit my form, here is an example of what my params are
<ActionController::Parameters {"name"=>"asdf", "active"=>"1", "allow_mass_update"=>"1", "plan"=>"flat", "commission_tiers_attributes"=><ActionController::Parameters {"0"=><ActionController::Parameters {"rate"=>"45"} permitted: true>} permitted: true>} permitted: true>

Create multiple records in rails with collection_select

I am trying to build a messaging system where the user can select multiple recipients, and I would like to system to create a message for each of them. So far I got the controller like:
def create
#listmail = params[:recipient_ids]
#listmail.each do |v|
#message = current_user.messages.build(:title, :description, :user_id, recipient_id: v, :recipient_email, :tag_id, :industry, :strategy, :position, :aum)
#message.save!
end
if #message.save
redirect_to messages_path
else
render 'new'
end
end
The view:
<%= simple_form_for #message do |f| %>
<%= f.collection_select(:recipient_id, User.all, :id, :full_name, {}, class: "selectpicker", title: "Choose recipent", multiple: true, data: { style: "form-control", size: "20", width: "100%" }) %>
<%= f.input :title, label: "Message Title" %>
<%= f.cktext_area :description, label: "Message Body" , :input_html => {:rows => 15} %>
<%= f.button :submit, :class => 'btn-custom' %>
<% end %>
But I get the error:
/Users/apulvard/Desktop/villas/app/controllers/messages_controller.rb:40: syntax error, unexpected ',', expecting => ...ipient_id: v, :recipient_email, :tag_id, :industry, :strateg... ... ^ /Users/apulvard/Desktop/villas/app/controllers/messages_controller.rb:54: syntax error, unexpected keyword_end, expecting end-of-input
What am I not doing well please?
/Users/apulvard/Desktop/villas/app/controllers/messages_controller.rb:40:
syntax error, unexpected ',', expecting => ...ipient_id: v,
:recipient_email, :tag_id, :industry, :strateg... ...
You are passing an invalid hash to the build method. The hash must be a combination of key-value pairs. For example
Not valid:
h = {:email, :name, user: 1}
SyntaxError: (irb):4: syntax error, unexpected ',', expecting =>
h = {:email, :name, user: 1}
^
Valid:
h = {email:"", name: "", user: 1}
=> {:email=>"", :name=>"", :user=>1}
Solution:
You should change your hash to key-value pairs with the params that are coming to the create method. Usually this was the case before Rails 4. In Rails4, strong params were introduced. If you are using Rails 4+, you should define the strong params like so
def create
#listmail = params[:recipient_ids]
#listmail.each do |v|
#message = current_user.messages.build(message_params)
#message.recipient_id = v
#message.save!
end
if #message.save
redirect_to messages_path
else
render 'new'
end
end
private
def message_params
params.require(:message).permit(:title, :description, :user_id, :recipient_id, :recipient_email, :tag_id, :industry, :strategy, :position, :aum)
end
Moreover,
#listmail = params[:recipient_ids]
should be
#listmail = params[:message][:recipient_id]

Rails simple_form create form when column type is JSON

I have a model (FooBar) with three columns:
Foo -> String
Bar -> JSON
Baz -> String
I want to create a form for this model
Bar has default attributes of: {zing: {}, zaz: {}, laz: {}}
I would like to have the following inputs:
f.input :foo
f.input :zing
f.input :zaz
f.input :laz
f.input :baz
I tried to do this using fields_for and passing in each key and converting it to a symbol:
bar.each do |k,v|
f.input k.to_sym
end
but the error I'm getting is that FooBar has undefined method of :zaz
Any ideas would be appreciated, thanks.
You should be able to do it like this:
f.simple_fields_for :bar do |bar_f|
bar.each do |k,v|
bar_f.input k.to_sym
end
end
Don't forget to allow the parameters in the controller.
You can do something like this:
class User < ActiveRecord::Base
serialize :preferences, HashSerializer
store_accessor :preferences, :blog, :github, :twitter
end
And then you will have access to blog, github and twitter just as if they were normal properties in the model and your form is going to look something like this:
= simple_form_for(#user, html: { class: "form" }) do |f|
= f.input :blog
= f.input :github
= f.input :twitter
You have more info in this link! https://github.com/plataformatec/simple_form/wiki/Nested-inputs-for-key-value-hash-attributes
Hope it helps!
Set #temp variable
#temp = FooBar.new
#temp.data = {zing: "", zaz: "", laz: ""}
This code works for me
<%= simple_form_for #temp do |f| %>
<%= f.simple_fields_for :data do |data_f| %>
<% #temp.data.each do |k,v| %>
<%= data_f.input k.to_sym %>
<% end %>
<% end %>
<%= f.button :submit %>
<% end %>
Don't forget about permission params
params.require(:temp).permit(data: [:zing, :zaz, :laz])
If you don't want to define accessors, you could do something like:
= simple_form_for(#foo_bar) do |f|
= f.simple_fields_for :bar do |bf|
= bf.input :zing, input_html: { value: f.object.bar[:zing] }
= bf.input :zaz, input_html: { value: f.object.bar[:zaz] }
= bf.input :laz, input_html: { value: f.object.bar[:laz] }
You would need to initialise bar with {} in your controller

Why do I get the error `undefined method 'map'`?

In my Ruby on Rails application I am trying to display a three drop down menus in the _form.html.erb which are rendered from the file _booking_lookup.html.erb and get there data from the drop down menu methods in the models.
_form.html.erb:
<%= render(:partial => '/booking_lookup', :locals=> {:film => #film = Film.all, :showings => #showings = Showing.all, :seats => #seats = Seat.all, :my_path => '/films/booking_lookup' }) %>
_booking_lookup.html.erb:
<%= form_tag my_path, :method=>'post', :multipart => true do %>
<%= select_tag ('title_id'),
options_from_collection_for_select(#films, :id, :title_info, 0 ),
:prompt => "Film" %>
<%= select_tag ('showings_id'),
options_from_collection_for_select(#showings, :id, :showing_times, 0 ),
:prompt => "Showings" %>
<%= select_tag ('seat_id'),
options_from_collection_for_select(#seats, :id, :seats_available, 0 ),
:prompt => "Seats" %>
<%= submit_tag 'Search' %>
film.rb:
class Film < ActiveRecord::Base
has_many :showings
belongs_to :certificate
belongs_to :category
def title_info
"#{title}"
end
end
seat.rb:
class Seat < ActiveRecord::Base
belongs_to :screen
has_many :bookings
def seats_available
"#{row_letter}#{row_number}"
end
end
showing.rb:
class Showing < ActiveRecord::Base
belongs_to :film
has_many :bookings
belongs_to :screen
def showing_times
"#{show_date.strftime("%e %b %Y")} # #{show_time.strftime("%H:%M")}"
end
end
But for some reason with the line: <%= select_tag ('title_id'),
options_from_collection_for_select(#films, :id, :title_info, 0 ),
:prompt => "Film" %> I get the error:
NoMethodError in Bookings#new
undefined method `map' for nil:NilClass
The weird part is that I am using a lot of this code else where, I have a _multi_search.html.erb form:
<%= form_tag my_path, :method=>'post', :multipart => true do %>
<!-- Genre: -->
Search By:
<%= select_tag ('cat_id'),
options_from_collection_for_select(#categories, :id, :category_info, 0 ),
:prompt => "Genre" %>
<%= select_tag ('cert_id'),
options_from_collection_for_select(#certificates, :id, :certificate_info, 0 ),
:prompt => "Age Rating" %>
<%= text_field_tag :search_string, nil, placeholder: "ACTOR" %>
or
<%= select_tag ('title_id'),
options_from_collection_for_select(#films, :id, :title_info, 0 ),
:prompt => "Film" %>
<%= submit_tag 'Search' %>
<% end %>
And is used in the application.html.erb:
<%= render(:partial => '/multi_search', :locals=> {:categories => #categories = existing_genres, :certificates => #certificates = Certificate.all, :films => #films = Film.all, :my_path => '/films/multi_find' }) %>
And that works fine.
What am I doing wrong?
It looks like #films is nil. Try setting #films = Film.all (instead of #film = Film.all) in _form.html.erb.
Update:
I would recommend moving the queries to the controller action. In the Model-View-Controller pattern, Controllers should be asking Models for data, not Views.
# BookingLookupController
def new
#films = Film.all
#showings = Showing.all
#seats = Seat.all
end
You can then reference the instance variables in the view.
<%= render partial: '/booking_lookup', locals: {films: #films, showings: #showings, seats: #seats, my_path: '/films/booking_lookup' } %>
In Controller, select fields as you just want to display names in dropdown
def method_name
#films = Film.select([:id, :title_info])
#showings = Showing.select([:id, :showing_times])
#seats = Seat.select([:id, :seats_available])
end
In page
<%= render(:partial => '/booking_lookup', :locals=> {:films => #films, :showings => #showings, :seats => #seats, :my_path => '/films/booking_lookup' }) %>
In partial
options_from_collection_for_select(films, :id, :title_info, 0 ),:prompt => "Film" %>

dropdown list in ruby on rails

I want to display values to drop down list from Database.
For that in my controller class i did the following to get the values from db and its getting properly.
#value = Message.find(:all)
<Message ID: 14448, SlNo: 609">, #<Message ID: 14448, SlNo: 610">
How can i display the SlNo values to drop down list.Here is the code am using and getting error!I don't know how to set values inside a collection_select.Please help me!!
<% #value.each do |d| %>
<%=collection_select(:value, :id, #value, :id, { selected: params.fetch(:value, {})[:id].to_i, :prompt => "-Select a device" }) %>
<% end %>
Table names getting
["UniqueDeviceID", "SlNo"]
Model
class MessageDetail < ActiveRecord::Base
# attr_accessible :title, :body
set_table_name 'DeviceDetails'
set_primary_key 'SlNo'
end
instead of
<% #value.each do |d| %>
<%=collection_select(:value, :id, #value, :id, { selected: params.fetch(:device, {})[:id].to_i, :prompt => "-Select a device" }) %>
<% end %>
use
<%= collection_select :value, :id, #value, :id, :S1No, { selected: params.fetch(:device, {})[:id].to_i, :prompt => "-Select a device" } %>
UPDATE: explanations for passed parameters
:value = a symbol representation of the record you want to update, it may also not be an instance record but just a symbol that will be used in the naming convention of the select tag
:id = the column that you wish to update
#value = the collection to show the choices
:id = the method you want to use that will be passed as the value of the selected value
:S1No = the method that will be used as the label for the options of the select tag
# START
f.collection_select :id, Message.all(:order => "name"), :id, :name, :include_blank => true
# END
OR
# START
messages_arr = []
messages = Message.all(:order => "name")
messages.each do |msg|
messages_arr << [msg.name, msg.id]
end
f.select(:id, options_for_select(messages_arr), {:include_blank => 'Include All'}, {:class=>"span12"})
# END

Resources