I'm new to Ruby on Rails and trying to implement a search function with simple form to filter out availabilities results. After I press search button, it still stays on the same page and not running the search function in the controller. The permitted is false. I'm wondering why this might occur. Is there anything wrong with the search_params I wrote?
Rails version is 6.0.2.1.
views/availabilities/_searchform.html.erb
<form>
<div id="aDiv">
<%= simple_form_for :search, :url => search_rides_result_path, :method => :get do |f| %>
<div class="form-row">
<div class="form-group col-md-2">
<%= f.input :start_city, label: 'Start City', class: "form-control", error: 'Start address is mandatory, please specify one' %>
</div>
<div class="form-group col-md-4">
<%= f.input :start_street_address, label: 'Start Street Address', class: "form-control" %>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-2">
<%= f.input :end_city, label: 'Destination City', class: "form-control" %>
</div>
<div class="form-group col-md-4">
<%= f.input :end_street_address, label: 'Destionation Street Address', class: "form-control" %>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<%= f.input :trip_time, as: :datetime, inline_label: 'Yes, remember me', class: "form-control" %>
</div>
<div class="form-group col-md-2">
<%= f.input :lowest_acceptable_price, label: 'Expected Price', class: "form-control" %>
</div>
</div>
<%= f.submit "Search", class: "btn btn-primary" %>
<% end %>
</div>
</form>
routes.rb file.
get 'search_rides', to: "availabilities#index"
get 'search_rides_result', to: "availabilities#search"
availabilities_controller.rb
def index
#availabilities = Availability.unmatched
end
def search
#availabilities = Availability.unmatched.search(search_params[:start_city])
end
def search_params
params.require(:search).permit(:start_city, :start_street_address, :end_city, :end_street_address, :trip_time, :lowest_acceptable_price)
end
models/availability.rb
class Availability < ApplicationRecord
has_many :users, :through => :posts
has_one :request
scope :unmatched, ->{ where(matched_request_id: -1) }
def self.search (params)
puts "start searching"
results = city_matches(start_city, end_city, params[:start_city], params[:end_city])
return nil unless results
results
end
Instead of using 2 different methods for search, try combining both in index method. Your index method will now look as follows:
def index
if params[:search]
#availabilities = Availability.unmatched.search(search_params[:start_city])
else
#availabilities = Availability.unmatched
end
end
Change the form url to search_rides_path. This way search results will be rendered in same view upon form submission.
Related
In my _form.html.erb I have nested fields, where for an Offer I would like to save multiple Discount types with values:
<%= f.fields_for #offer.discounts do |discount| %>
<% I18n.t(:discount_type).each do |type| %>
<div class="form-group row discount-list">
<label class="col-sm-8 control-label">
<%= discount.label I18n.t("discount_type.#{type[0]}") %><br/>
</label>
<div class="col-sm-4">
<%= discount.hidden_field :discount_type, value: type[0] %>
<%= discount.number_field :value,
value: (#offer.new_record? ? '0.00' : discount.value),
class: "form-control allow_numeric" %>
</div>
</div>
<% end %>
<% end %>
At the moment my form is populated correctly as I would like it to be, however values are not saving since:
in my params I see only 1 of 3 discount types like this:
"seller_discount"=>{"discount_type"=>"special", "value"=>"5"}
there is error Unpermitted parameter: :seller_discount
records are not saving
My Seller::Offer model looks like this:
has_many :offer_discounts, class_name: "Seller::OfferDiscount"
has_many :discounts, class_name: "Seller::Discount", through: :offer_discounts, inverse_of: :offers
accepts_nested_attributes_for :discounts, allow_destroy: true
My controller is simple as:
def new
#offer = Seller::Offer.new
end
private
def offer_params
params.require(:seller_offer).permit(
:company_id, :name, :base_price,
discounts_attributes: [:id, :discount_type, :value, :_destroy]
)
end
So far I've been trying different ideas from Rails docs, however no luck. Probably in my specific case, twist is where I try to iterate over I18n.t(:discount_type) an create input field for each discount type (buy key).
I'll be happy for any hint how to solve this. Thank you!
Since you're iterating over discount_type I think that needs to be an array type in your offer_params method.
def offer_params
params.require(:seller_offer).permit(
:company_id, :name, :base_price,
seller_discounts_attributes: [:id, :discount_types => [:discount_type, :value], :_destroy]
)
end
But what happens if you try to use fields_for helper?
<%= f.fields_for #offer.discounts do |discount| %>
<%= f.fields_for I18n.t(:discount_type) do |type| %>
<div class="form-group row discount-list">
<label class="col-sm-8 control-label">
<%= discount.label I18n.t("discount_type.#{type[0]}") %><br/>
</label>
<div class="col-sm-4">
<%= discount.hidden_field :discount_type, value: type[0] %>
<%= discount.number_field :value,
value: (#offer.new_record? ? '0.00' : discount.value),
class: "form-control allow_numeric" %>
</div>
</div>
<% end %>
<% end %>
So, to have my form working for both New and Edit actions, final solution is this:
<% if params[:action] == 'new' %>
<div class="col-md-7 col-sm-7">
<!-- Discounts for new form !-->
<% I18n.t(:discount_type).each do |type| %>
<%= f.fields_for :discounts, #offer.discounts.build do |disc| %>
<div class="form-group row discount-list">
<label class="col-sm-8 control-label">
<%= disc.label I18n.t("discount_type.#{type[0]}") %><br/>
</label>
<div class="col-sm-4">
<%= disc.hidden_field :discount_type, value: type[0] %>
<%= disc.number_field :value, value: '0.00',
class: "form-control allow_numeric" %>
</div>
</div>
<% end %>
<% end %>
</div>
<% elsif params[:action] == 'edit' %>
<div class="col-md-7 col-sm-7">
<!-- Discounts for edit form !-->
<%= f.simple_fields_for :discounts do |d| %>
<div class="form-group row discount-list">
<%= d.input :discount_type, as: :hidden %>
<label class="col-sm-8 control-label">
<%= d.label I18n.t("discount_type.#{d.object.discount_type}") %><br/>
</label>
<div class="col-sm-4">
<%= d.input :value, label: false, input_html: { id: d.object.discount_type+"_discount",
class: "form-control allow_numeric" } %>
</div>
</div>
<% end %>
</div>
<% end %>
Edit action is done with simple_form_fields_for
Obviously not shiny solution, but looks like this works.
Ok I've been trying to figure this out for awhile... I wan´t to render a partial in the views/users/show.html.erb
This is the form code in the partial that I want rendered
<%= form_for #addon, :html => {:class => "form-horizontal center"} do |f| %>
<div class="form-group">
<%= f.label :addon_1, "1.Addon:", class: "col-md-4 control-label" %>
<div class="col-md-8">
<%= f.text_field :addon_1, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :addon_2, "2.Addon:", class: "col-md-4 control-label" %>
<div class="col-md-8">
<%= f.text_field :addon_2, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :addon_3, "3.Addon:", class: "col-md-4 control-label" %>
<div class="col-md-8">
<%= f.text_field :addon_3, class: "form-control" %>
</div>
</div>
<%= f.submit "Submit", class: "btn btn-default btn-primary" %>
I have an addon.rb model and user.rbmodel
this is the addon.rb model
class Addon < ActiveRecord::Base
belongs_to :user
end
And this is the user.rbmodel
class User < ActiveRecord::Base
has_many :addons
end
And in the users_controller.rb I have, this in the showaction
def show
##addon = current_user.addons.build
#addons = current_user.addons
end
I've tried to both use #addons and #addon it both gives errors.
If I use #addons rails gives back this error First argument in form cannot contain nil or be empty
and if I try to use #addon rails gives back this error :unknown attribute 'user_id' for Addon
Am I missing something here, I can't see why this shouldn't work, can anyone please advise.
I think you are not logged in, so there is no current_user & #addon.
I'm building an RailsApp were the User can declare their :buisness_type via f.selectin the views/profiles/_form.html.erb.
And then in the views/users/show.html.erb the current_user can enter values for car travels in an input_field.
What I want to be able to do is to let the current_user filter out other users based on their :buisness_type. So the current_user can see in the views/users/show.html.erb the Average for other users car_trip in the same :business_type.
In the views/profiles/_form.html.erb I have this code which get saved in the Profile.rbmodel:
<div class="form-group">
<%= f.label :buisness_type %>
<%= f.select(:buisness_type, grouped_options_for_select(Profile::BUISNESS_TYPES),{ :class => 'form-control' })%>
</div>
And in the views/users/show.html.erb I´m rendering this partial:
<%= form_for #transport, html: {class: 'form-horizontal'} do |f| %>
<div class="control-group">
<%= f.label :Transport_type, class: 'control-label' %><br>
<div class="controls">
<%= f.select(:transport_type, options_for_select(Transport::TRANSPORT_TYPES)) %>
</div>
</div>
<div class="control-group">
<%= f.label :Trip_length_km, class: 'control-label' %><br>
<div class="controls">
<%= f.number_field :transport_km %>
</div>
</div>
<div class="control-group">
<%= f.label :Number_of_trips, class: 'control-label' %><br>
<div class="controls">
<%= f.number_field :transport_num_of_trips %>
</div>
</div>
<div class="control-group">
<%= f.label :Recycled_fuel, class: 'control-label' %><br>
<div class="controls">
<%= f.number_field :transport_km_recycled_fuel %>
</div>
</div>
<div class="control-group">
<div class="controls">
<%= f.submit class: 'btn btn-xs btn-warning' %>
</div>
</div>
<% end %>
<%= link_to 'Back', transports_path %>
</div>
I´m also rendering this column Chart in the views/users/show.html.erb This is a Chartkicks Chart.
<div class="col-md-6 chart-box">
<%= column_chart [
{name: "CarTrips #{current_user.profile.name}", data: current_user.transports.group(:transport_type).sum(:transport_km)},
{name: "CarTrips Everyone Median", data: Transport.group(:transport_type).average(:transport_km)}], { stacked: true, height: "300px", xtitle: "CarTrips", ytitle: "Km/CarTrips"} %>
</div>
As you can see I'm able to show the average car trip for Every User no matter in what kind of business they are in. How can I let the Current_user only see the Average for Car trips of other users in the same business type they are in??? Is that even possible.
In the users_controller.rb I've this in the showmethod
def show
#user = User.find(params[:id])
#users = User.order('created_at DESC').paginate(page: params[:page], per_page: 30)
#transport = current_user.transports.build
end
ADDED Models
this is the user.rb model
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
def average_transport_types
self.transports.group(:transport_type).sum(:transport_km)
end
end
this is the profile.rbmodel
class Profile < ActiveRecord::Base
belongs_to :user
end
Just add a where onto the part that pulls out the users eg:
#users = User.where(:business_type => current_user.business_type).order('created_at DESC').paginate(page: params[:page], per_page: 30)
Title kinda says it all, Basically i have this form
<% provide(:title, "Edit user") %>
<h1>Editing event:
<%= #newevent.id %></h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= simple_form_for #newevent do |f| %>
<div class="form-group">
<%= f.label :eventname %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :eventname, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<%= f.input :event_type, :collection => ['Concert','Festival','Sports','Theatre'] %>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :eventdesc %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :eventdesc, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :eventshortdesc %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :eventshortdesc, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :pagetitle %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :pagetitle, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :metatag %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :metatag, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :eventvenuename %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :eventvenuename, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<%= f.input :time, type: "time", :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<%= f.input :date, type: "date", :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :eventimage %>
<div class="row">
<div class="col-md-6">
<%= f.text_field :eventimage, :autofocus => true, class: "form-control" %>
</div>
</div>
</div>
<%= f.submit "Save changes", class: "btn btn-info" %>
<%= link_to "Delete", event_path(#newevent), :method => :delete, class: "btn btn-danger" %>
<% end %>
</div>
</div>
Here is what it loads from.
def edit
#newevent = Event.find(params[:id])
end
However its different now. I am wanting the stuff to load form the Master table (so the fields are populated from Master) However i have an update method that looks like this
def update
#newevent = Event.find(params[:id])
if #newevent.update_attributes(event_params.merge createdby: current_user.id)
flash[:success] = "Profile updated"
redirect_to "/events"
else
flash.now[:alert] = 'Error updating event'
end
end
Do i need to change something in the eventparams to get this to work (and make change from Event to Master) The fields are different in both tables, So would i need to make the value of the fields be something like this?
value: "<%=Master.name%>"
Thanks
Sam
If you're trying to load "defaults", you'd be better doing it in the model layer:
#app/models/event.rb
class Event < ActiveRecord::Base
before_create :set_defaults
private
def set_defaults
default = Master.first
self.attributes.except("id", "created_at", "updated_at").each do |field|
self[field] ||= default.send(field)
end
end
end
The above will pull a record from the Master model, populate any of the attributes in your Event model which have not been populated.
However, I believe your pattern to be inefficient.
The idea you are pulling "default" data from another model/table directly contradicts the DRY and modular principles of software development.
Not to say that if you wanted to create "dynamic" defaults for a model, your pattern might work. If you're trying to store exactly the same data in different models, you've got a problem.
I would do the following:
#app/models/event.rb
class Event < ActiveRecord::Base
##defaults: {
x: "y",
y: "z",
z: "0"
}
before_create :set_defaults
private
def set_defaults
self.attributes.except("id", "created_at", "updated_at").each do |field|
self[field] ||= ##defaults[field]
end
end
end
Update
After a discussion, it became apparent that there was more context required to understand the issue/solution fully.
The app works by importing a series of CSV data into the Master table. Whilst I don't know what data this is, the OP said that each Event would be built around the data in Master.
He mentioned he needed 3 fields definitely from Master whilst the others could be inputted by the user into Event.
This means that you could tie the two together with a has_many / belongs_to relationship:
#app/models/master.rb
class Master < ActiveRecord::Base
has_many :events
end
#app/models/event.rb
class Event < ActiveRecord::Base
belongs_to :master
end
This is a standard ActiveRecord association, which means you'll be able to call #master.events & #event.master -- accessing values from each table:
#app/controllers/events_controller.rb
class EventsController < ApplicationController
def new
#event = Event.new
end
def create
#event = Event.new event_params
#event.save
end
private
def event_params
params.require(:event).permit(:master_id, ...)
end
end
#app/views/events/new.html.erb
<%= form_for #event do |f| %>
<%= f.collection_select :master_id, Master.all, :id, :name %>
<%= f.submit %>
<% end %>
--
The reason why this will be much better than your current pattern is that each time you create a new event, you'll be able to access the master attributes:
#event.master.url #-> "url" from master record
In Rails in general you create bound form inputs by using a model and passing it to form_for (or simple_form_for).
In this case if you really need to have dynamic user editable default the most obvious solution would be to use Master to seed the new Event.
In most cases however defaults should be a developer concern which are handled on the model layer as suggested by Rich Peck.
Also setting defaults only really makes sense for a new record - why would you want to override the users choices when updating?
def new
#master = Master.last
#event = Event.new(#master.attributes.except("id", "created_at", "updated_at"))
end
<%= simple_form_for #newevent do |f| %>
<%= f.input :eventname %>
<% end %>
I have a model with a method called date_string. The point of this method is to return a formatted date string when being used in a share view. Here is the view code.
<div class="field control-group">
<div class="control-label">
<%= f.label :business_hour , :date_string %>
</div>
I am expecting the f.label call to function like in this api doc, with :business_hour being the object, and :date_string being the method. However, the only thing that is rendered to the view is the string 'Date string' or 'date_string'.
Any help on getting a view class to call a method, not a property, on a model is greatly appreciated.
Business_Hour code
class BusinessHour < ActiveRecord::Base
attr_accessible :business_hourable_id,
:business_hourable_type,
:close_time, :day, :open_time,
:order , :business_date
belongs_to :business_hourable , :polymorphic => true
def date_string()
if business_date.nil?
return ''
else
return_string = business_date.strftime( '%a %b\ %e , %Y' )
end
end
end
Here is the full partial code(shared/business_hours):
<div class="field control-group">
<div class="control-label funkiness">
<%= F.label :business_hour , :date_string %>
</div>
<div class="controls">
<%= f.select :open_time, available_hours, :include_blank => true %>
</div>
<div class="control-label">
<%= f.label :open_time, 'Close Time' %>
</div>
<div class="controls">
<%= f.select :close_time, available_hours, :include_blank => true %>
</div>
</div>
Here is the pertinent part of the _form
<%= form_for (#some_show), html: {class: "form-horizontal pull-left"} do |f| %>
...
<%= f.fields_for :business_hours do |operating_time| %>
<%= render :partial => 'shared/business_hours',
:locals => {:f => operating_time} %>
<% end %>
And finally, here is the edit action of the controller
# GET /some_shows/1/edit
def edit
#some_show = SomeShow.find(params[:id])
end
So the solution that worked for me was to take the date_string off of my model, and implement it in a helper. Then, I modified my partial view so it looks like this:
<div class='field control-group hour_dropdown_2'>
<div class='field control-group'>
<div class="control-label">
<label><%= get_business_hour_string(f) %></label>
</div>
<h4 class='no-break-h'>From</h4>
<%= select :open_time, available_hours, :include_blank => false %>
<h4 class='no-break-h'>To</h4>
<%= select :close_time, available_hours, :include_blank => false %>
</div>
</div>
My select tags are still busted and I don't know why for my _address partial I get an f.whatever, but for the BusinessHour partial I get nothing in the way of form helpers.