I am trying to display different options for users to select in the show.html.erb, when the provider chooses to offer sets.
The problem is that the provider has multiple options, 1 bottle, 3 bottles, 6 and 12 bottles.
My _form.html.erb abstract:
<% if #wine.is_1 == true %>
<%= f.select :bottles, [["1 bottle", "1"]], id: "bottle", prompt: "Select...", class:"form-control" %>
<% end %>
<% if #wine.is_3 == true %>
<%= f.select :bottles, [["3 bottles", "3"]], id: "bottle", prompt: "Select...", class:"form-control" %>
<% end %>
<% if #wine.is_6 == true %>
<%= f.select :bottles, [["6 bottles", "6"]], id: "bottle", prompt: "Select...", class:"form-control" %>
<% end %>
Is there any alternative using the Reservations Controller to make the code minimal ? And how would I get the total amount to pay ?
Reservations Controller
class ReservationsController < ApplicationController
before_action :authenticate_user!
def create
wine = Wine.find(params[:wine_id])
if current_user == wine.user
flash[:alert] = "You cannot book your own wine!"
else
start_date = Date.parse(reservation_params[:start_date])
#reservation = current_user.reservations.build(reservation_params)
#reservation.wine = wine
#reservation.price = wine.price
#reservation.total = wine.price * #bottles
#reservation.save
flash[:notice] = "Booked Successfully!"
end
redirect_to wine
end
you could use some helpers to avoid all that logic in the view. An example:
module ApplicationHelper
def wine_quantity(wine)
case
when wine.is_1 then [["1 bottle", "1"]]
when wine.is_3 then [["3 bottles", "3"]]
when wine.is_6 then [["6 bottles", "6"]]
when wine.is_12 then [["12 bottles", "12"]]
else
end
end
end
and in your _form.html.erb it could be reduced to this:
<%= f.select :bottles, wine_quantity(#wine), id: "bottle", prompt: "Select...", class:"form-control" %>
Related
I have the following form:
<div class='panel' id='panel-advanced-search'>
<%= form_tag contacts_path, method: :get do %>
<div>
<div class='advanced_search'>
<div>
<%= label_tag "Contact Type" %>
<%= select_tag(:contact_type, options_for_select(Contact::TYPES, selected: params[:contact_type]), prompt: 'Any', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Prospect Strength" %>
<%= select_tag(:prospect_strength, options_for_select(Contact::PROSPECT_STRENGTHS, selected: params[:prospect_strength]), prompt: 'Any', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Customer" %>
<%= collection_select(:customer_account_id, :customer_account_id, Customer.order(:name), :id, :name, { prompt: '' }, class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Supplier" %>
<%= collection_select(:supplier_account_id, :supplier_account_id, Supplier.order(:name), :id, :name, { prompt: '' }, class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Company Name" %>
<%= text_field_tag :company_name %>
</div>
<div>
<%= label_tag "Name" %>
<%= text_field_tag :name %>
</div>
<div>
<%= label_tag "Job Title" %>
<%= text_field_tag :title %>
</div>
<div>
<%= label_tag "Postcode" %>
<%= text_field_tag :postcode %>
</div>
<div>
<%= label_tag :created_at, 'Created From' %>
<div class="date-picker">
<%= text_field_tag :created_at, nil, class: 'date-picker-select' %>
<span class="date-picker-btn">
<span class="icon-calendar" aria-hidden="true"></span>
</span>
</div>
</div>
<div>
<%= label_tag :updated_at, 'Created To' %>
<div class="date-picker">
<%= text_field_tag :updated_at, nil, class: 'date-picker-select' %>
<span class="date-picker-btn">
<span class="icon-calendar" aria-hidden="true"></span>
</span>
</div>
</div>
<div>
<%= label_tag "Tags" %>
<%= collection_select(:tag_list, :tag_list, #tags.order(:name), :name, :name, {}, { class: 'select2', multiple: true }) %>
</div>
<div>
<%= label_tag "Assignee" %>
<%= collection_select(:assigned_to, :assigned_to, User.all, :id, :name, { prompt: 'Any' }, class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Obsolete?" %>
<%= select_tag(:obsolete, options_for_select(['Obsolete', 'All'], selected: params[:obsolete]), prompt: 'Not obsolete?', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Send Results To" %>
<%= select_tag(:subsequent_action, options_for_select([
['Report', 'report'],
['CSV Export', 'csv_export'],
['New Event', 'new_event']
]), prompt: 'None', class: 'customSelect') %>
</div>
</div>
<div class="advanced_search_btns">
<%= submit_tag submit_text %>
<%= link_to secondary_btn, contacts_path, class: 'btn-medium' %>
</div>
</div>
<% end %>
</div>
and the following method in the model
def self.advanced_search
Contact.where('
contact_type LIKE :search OR
prospect_strength LIKE :search OR
customer_account_id LIKE :search OR
supplier_account_id LIKE :search OR
company_name LIKE :search OR
name LIKE :search OR
title LIKE :search OR
postcode LIKE :search OR
created_at LIKE :search OR
updated_at LIKE :search OR
tag_list LIKE :search OR
assigned_to LIKE :search OR
obsolete LIKE :search
', search: "%#{search}%"
)
end
How do I go about using this method so the user can use this search form with multiple params? I already have the following in the index method for a basic search so I need to have both search forms
def index
#per_page = params[:per_page] || 20
#tags = ActsAsTaggableOn::Tag.all
if params[:search].present?
#contacts = Contact.search(params[:qs], params[:search]).order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: #per_page)
else
#contacts = Contact.all.order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: #per_page)
end
end
Edit Updated the form above to the complete form, ideally, I would like the forms functionality to be entirely in the model.
Edit #2
This is the basic search:
model
QUICK_SEARCH_FIELDS = {
name: {
column_names: 'contacts.name'
},
customers: {
joins_table: :customer,
column_names: 'contacts.name',
filters: { contact_type: 'customer' }
},
suppliers: {
joins_table: :supplier,
column_names: 'contacts.name',
filters: { contact_type: 'supplier' }
},
tags: {
tagged_with: true
}
}.with_indifferent_access
def self.search(field, query)
field = QUICK_SEARCH_FIELDS[field]
contact = all
contact = contact.joins(field[:joins_table]) if field[:joins_table]
contact = contact.where(field[:filters]) if field[:filters]
contact = contact.where("#{field[:column_names]} LIKE ?", "%#{query}%") if field[:column_names]
contact = contact.tagged_with(query) if field[:tagged_with]
contact
end
form
<div class='panel' id='panel-search'>
<%= form_tag contacts_path, method: :get do %>
<div class='l-inline-row-block'>
<div class='l-inline-col width_120px'>
<%= select_tag(:qs, options_for_select(Contact::QUICK_SEARCH_FIELDS.keys(), selected: params[:qs]), class: 'customSelect') %>
</div>
<div class='l-inline-col'>
<%= search_field_tag :search, params[:search] %>
</div>
<div class='l-inline-col' style='width: 100px;'>
<%= submit_tag submit_text %>
</div>
</div>
<% end %>
</div>
you may need to make view adjustments and you cannot just use the search term/query for all fields:
1.make sure the fields inside the form in your view are all the same names of the columns in the Contact model that need to be searched
2.add a hidden field inside each form so you can determine which search this is (there is another option but this one is less work)
3.change the collection_select where user can only select one field to select_tag in order to not mess up query building
every field that is filled will pass a value- you can build a hash including column/form-field entered and their value e.g { contact_type: "value1", prospect_strength: "value2" }
after that, you would need to build a query using that hash and query the DB
this would look like so:
In your view:
add this in the advanced search form
<%= hidden_field_tag :search_type, :advanced %>
and in your normal search add this
<%= hidden_field_tag :search_type, :normal %>
In your model:
def self.advanced_search(values_by_column_name) # values_by_column_name is a hash passed from the controller
tag_list = values_by_column_name.delete("tag_list")
sql_query = values_by_column_name.keys.map { |column| "#{column} LIKE :#{column}" }
sql_query = sql_query.join(" OR ")
values_by_column_name = values_by_column_name.transform_values { |value| "%#{value}%" }.symbolize_keys
relation = Contact.where(sql_query, values_by_column_name)
relation = relation.tagged_with(tag_list) if tag_list
relation
end
in your controller:
ADVANCED_SEARCH_FIELDS = [
:contact_type,
:prospect_strength,
:customer_account_id,
:supplier_account_id,
:company_name,
:name,
:title,
:postcode,
:created_at,
:updated_at,
{tag_list: []},
:assigned_to,
:obsolete,
]
def index
#per_page = params[:per_page] || 20
#tags = ActsAsTaggableOn::Tag.all
if advanced_search?
#contacts = Contact.advanced_search(advanced_search_params)
elsif normal_search?
#contacts = Contact.search(params[:qs], params[:search])
else
#contacts = Contact.all
end
#contacts = #contacts.order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: #per_page)
end
def advanced_search?
params[:search_type] == "advanced" && advanced_search_params.any?
end
def normal_search?
params[:search_type] == "normal" && params[:search].present?
end
def advanced_search_params
#_advanced_search_params ||= params.permit(ADVANCED_SEARCH_FIELDS).select { |_, v| v.present? }.to_h
end
My user has selected a product.
Now he is in his shopping cart and he finally wants two of this item
So in the cart there is a form to increase the quantity
order_items/index.html.erb
<% #items.each do |item| %>
<%= image_tag(item.product.attachments.first.url, class: "tiny_image") %>
<%= link_to item.product.title, clients_product_path(item.product_id), class: "title_in_tab" %>
<%= item.quantity %>
<%= number_to_currency_euro item.product.price %>
<%= item.size.size_name %>
<%= form_for edit_clients_order_item_path(item), method: :patch, remote: true do |f| %>
<%= f.hidden_field :id, value: item.id %>
<%= f.hidden_field :product_id, value: item.product.id %>
<%= f.hidden_field :size_id, value: item.size.id %>
<%= f.select :quantity, [1,2,3,4,5] %>
<%= f.submit "Modifier" %>
<% end %>
<%= link_to clients_order_item_path(item), method: :delete, remote: true ,data: {confirm: "Voulez vous vraiment supprimer cet article?"} do %>
<i class="fa fa-trash"></i>
<% end %>
in the shopping_car.rb
I have this method to inscrease the quantity
def inscrease_item(id:, quantity:1, product_id:, size_id:, user_id:, order_id:)
#size = Size.find_by(id: size_id)
#order_item = order.items.find_by(product_id: product_id, size_id: size_id)
#order_item.quantity = quantity.to_i
#order_item.save
update_sub_total!
#size.quantity -= quantity.to_i
#size.save
end
in order_items_controller.rb
I have:
def edit
#item = OrderItem.find(params[:id])
end
def update
binding.pry
#item = current_cart
current_cart.inscrease_item(
id: params[:id],
order_id: params[:order_id],
product_id: params[:product_id],
quantity: params[:quantity],
user_id: params[:user_id],
size_id: params[:size_id])
end
private
def order_item_params
params.require(:order_item).permit(:id, :product_id, :user_id, :quantity, :size_id, :order_id)
end
I added a break point in the update method:
#item returns nil and I don't know what is wrong...
this is what returns binding pry
30: def update
31: binding.pry
=> 32: #item = OrderItem.find(params[:id])
33: #item.inscrease_item(
34: order_item_params
35: )
36: end
[1] pry(#<Clients::OrderItemsController>)> #item
=> nil
[2] pry(#<Clients::OrderItemsController>)> params
=> <ActionController::Parameters {"utf8"=>"✓", "_method"=>"patch", "/clients/cart/items/111/edit"=>{"id"=>"111", "product_id"=>"19", "size_id"=>"41", "quantity"=>"4"}, "commit"=>"Modifier", "controller"=>"clients/order_items", "action"=>"update"} permitted: false>
#item isn't set yet because the arrow on the side points to the next statement to execute. Therefore #item = OrderItem.find(params[:id]) has not been executed yet. Move the break point one line lower or step one statement further.
Furthermore you're passing a wrong argument to the form_for helper. The first argument should be an record or symbol/string representing the object. You might want to use the form_with helper instead using the :url option.
Last but not least, as you can see in your params (from your pry output), currently the data is present, but nested inside the params hash.
{
"utf8" => "✓",
"_method" => "patch",
"/clients/cart/items/111/edit" => {
"id" => "111",
"product_id" => "19",
"size_id" => "41",
"quantity" => "4"
},
"commit" => "Modifier",
"controller" => "clients/order_items",
"action" => "update"
}
The data should also be accessed like such.
params['/clients/cart/items/111/edit'][:id] #=> "111"
# ^ this is due to the wrong first argument
# of the form_for helper
I am using Rails 5.2 and building an ecomm site.
My new.html.erb page has a simple_form with a combination of Product fields as well as other params which are handled outside the strong params and the creation of the new instance.
One of the features of the form is a eventListener which creates the :sku automatically based on four input values. The product number, the sku and the live status are hidden.
Here is the simplified version of the html.erb:
<%= simple_form_for #new_product do |f| %>
<%= f.error_notification %>
<%= f.input :name%>
<%= f.association :size, collection: #all_sizes.map{ |s| [s.name, s.id, {'data-code-num' => s.code_num}]}, input_html:{class: 'sku-suffix-component'} %>
<%= f.association :color, collection: #all_colors.map{ |s| [s.name, s.id, {'data-code-num' => s.code_num}]}, input_html:{class: 'sku-suffix-component'} %>
<%= f.association :pattern, collection: #all_patterns.map{ |s| [s.name, s.id, {'data-code-num' => s.code_num}]}, input_html:{class: 'sku-suffix-component'} %>
<%= f.input :product_number, as: :hidden, input_html:{ value: #new_product.product_number, class: "sku-suffix-component" } %>
<%= f.input :sku,as: :hidden, html:{id: "new-product-form-sku-input"} %>
<%= f.input :live_status, as: :hidden, :input_html => { :value => #new_product.live_status } %>
<%= f.input :description, as: :text %>
<%= f.association :brand%>
<%= f.association :style %>
<%= f.input :price %>
<%= f.input :quantity, input_html:{value: 1}%>
<%= f.association :segment %>
<%= f.association :main_category %>
<%= f.association :category %>
<%= f.association :country, class: '' %>
<!-- Here are some inputs for adding records to a material join table -->
<!-- And the names of the inputs are dynamically created -->
<% 5.times.with_index do |_, i| %>
<% num = i + 1 %>
<label class="form-control-label integer" for="material_percent_id_<%= num < 10 ? "0" + num.to_s : num.to_s %>">Percent</label>
<input class="form-control numeric integer required" type="number" step="1" name="material_percent_<%= num < 10 ? "0" + num.to_s : num.to_s %>" id="material_percent_id_<%= num < 10 ? "0" + num.to_s : num.to_s %>">
<label class="form-control-label select" for="material_id_id_<%= num < 10 ? "0" + num.to_s : num.to_s %>">Material Component #<%= num %> </label>
<select class="form-control select" name="material_id_<%= num < 10 ? "0" + num.to_s : num.to_s %>" id="material_id_id_<%= num < 10 ? "0" + num.to_s : num.to_s %>">
<option value=""></option>
<% #all_materials.each do |material| %>
<option value="<%= material.id %>"><%= material.name %></option>
<% end %>
</select>
<% end %>
<!-- Here are some inputs for adding multiple photos to the products using active_storage -->
<% (1..8).each do |i| %>
<%= f.label "Photo [#{i}]" %>
<%= f.file_field :photos, multiple: true %>
<% end %>
<%= f.button :submit %>
<% end %>
Creating new products using this simple_form works fine, along with instances in the join table, through the create method, shown here:
def create
#all_sizes = Size.all
#all_colors = Color.all
#all_patterns = Pattern.all
#new_product = Product.new(product_params)
#all_materials = Material.all
if #new_product.save
5.times.with_index do |_, i|
if params["material_id_0#{(i + 1)}"] != ""
ProductMaterial.create!(product_id: #new_product.id,
material_id: params["material_id_0#{(i + 1)}"].to_i,
percent: params["material_percent_0#{(i + 1)}"].to_i)
else
break
end
end
redirect_to #new_product
else
render :new
end
end
Using nearly the exact same form (some code added to dynamically render the join table inputs and the photos inputs correctly), but all inputs present; and using the exact same strong params in the controller; going through the update method in the controller produces an argument error. Here is the update method:
def update
#product = Product.find(params[:id])
#product = Product.update(product_params) # here is where the error happens
#all_sizes = Size.all
#all_colors = Color.all
#all_patterns = Pattern.all
#all_materials = Material.all
if #product.save
5.times.with_index do |_, i|
if params["material_id_0#{(i + 1)}"] != ""
ProductMaterial.create!(product_id: #product.id,
material_id: params["material_id_0#{(i + 1)}"].to_i,
percent: params["material_percent_0#{(i + 1)}"].to_i)
else
break
end
end
redirect_to #product
else
render :edit
end
end
Here is the exact syntax of the error as seen in the server:
ArgumentError (wrong number of arguments (given 1, expected 2)):
app/controllers/products_controller.rb:72:in `update'
Here
#product = Product.update(product_params)
you're trying to call instance method update on the Product class itself. new is a class method, so it works good in create action. How it should be:
def update
#product = Product.find(params[:id])
# here you define different #all instances
# you don't need to update and save separately, because instance is saved already
# if you call update on it and update goes well
if #product.update(product_params)
# here goes the rest controller code
When I try to create an "Action" I get this error.
My Actions controller:
class ActionsController < ApplicationController
def new
#match_set = MatchSet.find(params[:match_set_id])
#fixture = #match_set.fixture
#teams = Team.where("id = " + #fixture.home_team_id.to_s + " OR id = " + #fixture.away_team_id.to_s)
#players = Player.where("team_id = " + #teams.ids.first.to_s + " OR id = " + #teams.ids.last.to_s)
#action = #match_set.actions.new
end
def create
#match_set = MatchSet.find(params[:match_set_id])
#action = #match_set.actions.new(action_params)
if #action.save
redirect_to match_set(#match_set)
else
render "actions/new"
end
end
private
def action_params
params.require(:action).permit(:team_id, :player_id, :position, :action_type, :action_result)
end
end
It is submitted from this form in views/actions/new.html.erb:
<%= form_for [#match_set, #action] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<!-- Team -->
<%= f.label :team_id %>
<%= f.collection_select :team_id, #teams,:id, :name, {include_blank: "Select team..."}, {class: "form-control"} %>
<!-- Player -->
<%= f.label :player_id %>
<%= f.collection_select :player_id, #players,:id, :last_name, {include_blank: "Select player..."}, {class: "form-control"} %>
<!-- Position -->
<%= f.label :position %>
<%= f.select :position, options_for_select(['1', '2', '3', '4', '5', '6']), {include_blank: "Select position on court..."}, class: "form-control" %>
<!-- Action Type -->
<%= f.label :action_type %>
<%= f.select :action_type, options_for_select(['Attack', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Action Result -->
<%= f.label :action_result %>
<%= f.select :action_result, options_for_select(['Score', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Submit Button -->
<%= f.submit "Add Action", class: "btn btn-primary" %>
<% end %>
Also the relevant routes:
resources :fixtures, shallow: true do
resources :match_sets, shallow: true do
resources :actions
end
end
I'm getting an error on this line in the controller:
params.require(:action).permit(:team_id,:player_id,
:position,:action_type,:action_result)
I have also noticed that my parameters seem to be disappearing but again have no clue as to the cause.
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"BqbEOfL7hEA8XSMXDvMW2qQ2uR74Egp5
jJvtQlsuyV2TikZJ+6hTIEMH05gy8TM6r3ZglFDRUFBl7ScZD1czCQ==",
"commit"=>"Add Action", "match_set_id"=>"15"}
Any help is appreciated.
action is a reserved word in rails. You will need to change your model name.
Rails provides a few params on each request such as:
params[:controller] # maps to your controller name
params[:action] # maps to an action with your controllers
http://api.rubyonrails.org/classes/ActionDispatch/Routing.html
I'm starting in rails and I have this error that I'm not able to solve..
Error - param is missing or the value is empty:
personas_x_tipos_persona
Controller
class PersonasController < ApplicationController
def create_cliente
#cliente = Persona.new(persona_params)
#personas_x_tipos_personas = Persona.new(tipos_personas_params)
if #cliente.save
redirect_to show_clientes_path
else
render :new_cliente
end
end
private
def persona_params
params.require(:persona).permit(:nombre, :apellido, :direccion, :ruc, :contacto, :email)
end
def tipos_personas_params
params.require(:personas_x_tipos_persona).permit(:linea_credito)
end
end
view
<div>
<%= form_for :persona ,:url => add_cliente_path, :html => {:method => :post} do |f|%>
<% #cliente.errors.full_messages.each do |message| %>
<div class="alert alert-danger" margin-top:10px">
* <%=message%>
</div>
<% end %>
<%= f.text_field :nombre, placeholder: "Nombre del Cliente"%>
<%= f.text_field :apellido, placeholder: "Apellido del Cliente"%>
<%= f.text_field :direccion, placeholder: "Direccion del Cliente"%>
<%= f.text_field :ruc, placeholder: "RUC del Cliente"%>
<%= f.text_field :contacto, placeholder: "Contacto del Cliente"%>
<%= f.email_field :email, placeholder: "Email del Cliente""%>
<%= f.fields_for :personas_x_tipos_persona do |pxp|%>
<%= pxp.number_field :linea_credito, placeholder: "Linea de Credito del Cliente"%>
<% end %>
<%= f.submit 'Guardar'%>
<% end %>
</div>
param is missing or the value is empty: personas_x_tipos_persona
The problem is with this line #personas_x_tipos_personas = Persona.new(tipos_personas_params)(actually this is not needed) which is calling tipos_personas_params.
From the docs of require(key),
When passed a single key, if it exists and its associated value is
either present or the singleton false, returns said value
Otherwise raises ActionController::ParameterMissing
So, in your case the require is expecting :personas_x_tipos_persona, while this is missing in the params, so is the error.
Actually, the form object is :persona not :personas_x_tipos_persona. Also as I can see that you are using fields_for, so you need to whitelist :personas_x_tipos_persona_attributes inside persona_params and the tipos_personas_params method is not needed. The below code should get you going.
class PersonasController < ApplicationController
def create_cliente
#cliente = Persona.new(persona_params)
#this is not needed
##personas_x_tipos_personas = Persona.new(tipos_personas_params)
if #cliente.save
redirect_to show_clientes_path
else
render :new_cliente
end
end
private
def persona_params
params.require(:persona).permit(:nombre, :apellido, :direccion, :ruc, :contacto, :email, personas_x_tipos_persona_attributes: [:id, :linea_credito])
end
end