Rails form populated from one table and saving to another - ruby-on-rails

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 %>

Related

search function not working - Ruby on rails

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.

How to add in multiple options for checkbox in Ruby on Rails?

This is likely a super easy answer for a Ruby on Rails expert. I have a form and need to add in a checkbox that has multiple items. I've been messing with the following code for a lot longer than I'd like to admit:
<%= form_for :lead, url: something, html: {id: 'product-form'} do |f|%>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<%= f.label :product%>
<%= f.check_box :product, {multiple:true}, "option", "option2", :class => 'form-control'%>
</div>
</div>
</div>
<% end %>
With this code I get the error "wrong number of arguments (5 for 1..4)".
Basically I just want someone to be able to pick multiple options. I've also tried the following:
<div class="row">
<div class="col-md-12">
<div class="form-group">
<%= f.label :product%>
<%= f.check_box :option1, "Option1" :class => 'form-control'%>
<%= f.check_box :option2, "Option2", :class => 'form-control'%>
</div>
</div>
</div>
And I get the delightful "undefined method `merge' for "Option1":String". What am I missing to put the values in associated with the label?
I use Rails 5.1.6 and this is how I achieved adding multiple options for checkbox. I also placed it in a dropdown.
In the migration file:
t.string :skills
In my controller "tasks_controller.rb":
def task_params
params.require(:task).permit(:work_type, :title, :post, {skills: []})
end
In my model "task.rb" I did:
validates :skills, presence: true
serialize :skills, JSON
I created a module mobilephones_data.rb in directory "app/model/concerns/" which holds all the options of the checkbox as an array that can be edited easily.
In app/model/concerns/mobilephones_data.rb I wrote:
module Mobilenphones_Data
Activities = [
'Amazon Kindle', 'Blackberry', 'iPad', 'iPhone', 'Mobile Phone', 'Nokia',
'Palm', 'Samsung'
]
end
This will put all data from module's array into the checkbox drop-down as checkbox options. In My form I did:
<div class="card">
<a class="card-link card-header" data-toggle="collapse" href="#collapseOne">
Mobile Phones
</a>
<div id="collapseOne" class="collapse" data-parent="#accordion">
<div class="card-body">
<% Mobilenphones_Data::Activities.each do |activity| %>
<div id="skill_list" class="col-lg-3 col-md-4 col-sm-12 col-12">
<%= f.check_box :skills, { multiple: true }, activity, false %>
<%= activity %>
</div>
<% end %>
</div>
</div>
</div> <!--bottom-->
</div>
In my view "show.html.erb":
<% #name_of_model.skills.each do |skill| %>
<%= skill %>
<% end %>
For posterity sake:
<div class="row">
<div class="col-md-12">
<div class="form-group">
<%= f.label "Select a Product" %><br />
<%= f.check_box(:option) %>
<%= f.label(:mug, "Option") %><br />
<%= f.check_box(:option2) %>
<%= f.label(:mousepad, "Option2") %>
</div>
</div>
</div>

I can't figure out why I'm getting this error in rails app: First argument in form cannot contain nil or be empty error

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.

How can Current_user filter other users based on same category as the current_user belongs to?

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)

How to dynamically Update/Edit/Delete existing record within a list

new to rails and could use some help figuring out how to allow users to update records in a list without having to leave the page.
Specifically, I have two forms on a page where users enter their children's info.
One form is for the user to add a NEW child's info to create a list of children below.
The list of children displays the user's previously entered children info.
However, within the child list I would like to allow users to both delete and edit an individual child's record.
My DELETE function is working fine, it's the UPDATE functionality I am having trouble with...
Here's the children#update controller:
def update
raise
#user = current_user
#child = Child.find(params[:id])
if #child.update_attributes(child_params)
flash[:notice] = "Child info was updated."
else
flash[:error] = "Sorry. Something went wrong, please try again."
end
respond_with(#child) do |f|
f.html { redirect_to new_child_path }
end
end
Here's the childlist form partial view:
<form role="form">
<% i = 1 %>
<% #user.children.each do |child| %>
<div class="col-md-12 form-align list-line">
<div class="col-md-10 form-align">
<%= label_tag child, "Child #{i}:" %>
<% i += 1 %>
</div>
</div>
<%= form_for(child, method: :put) do |f| %>
<div class="col-md-12 form-align">
<div class='col-md-4 form-align'>
<%= f.label :first_name, class: 'sr-only' %>
<%= f.text_field :first_name, value: child.first_name, class: 'form-control form-control-align' %>
</div>
<div class='col-md-4 form-align'>
<%= f.label :middle_name, class: "sr-only" %>
<%= f.text_field :middle_name, value: child.middle_name, class: 'form-control form-control-align' %>
</div>
<div class='col-md-4 form-align'>
<%= f.label :last_name, class: "sr-only" %>
<%= f.text_field :last_name, value: child.last_name, class: 'form-control form-control-align' %>
</div>
</div>
<div class="col-md-12 form-align">
<div class="col-md-4 form-group form-inline form-align">
<%= f.label :birth_date, "D.O.B." %>
<%= f.date_field :birth_date, value: child.birth_date, class: 'form-control' %>
</div>
<div class="col-md-4 form-group form-inline form-align">
<%= f.label :deceased, "Deceased?" %>
<%= f.select :deceased, value: child.deceased?, class: 'form-control form-control-align' %>
</div>
<%= f.submit "Update" %>
<%= link_to '<i class="glyphicon glyphicon-remove red"></i>'.html_safe, child, method: :delete %>
</div>
<% end %>
<% end %>
</form>
...and the child model: simply belongs_to :user / user model has_many :children
...and routes: resources :children
I think I need some options passed through my form_for, but unable to find what those need to be...
I would suggest using a gem like Best in Place to allow for in-place editing on certain fields in the list.
If you don't want in-place editing then utilize a modal view that contains the edit form.

Resources