In my RoR application I have a form whereby users can search for their contacts by first name and select the ones that they want to send an email to. My problem is that after searching for say "Tom", and selecting the checkbox for "Tom", if they then reset the search to display all check boxes "Tom" is no longer selected.
Can someone please tell me how this can be sorted?
The code in the view is:
<div class="panel-body">
<%= form_tag '/emails/contact_search', :method => 'get' do %>
<p>
<%= text_field_tag :search_string, params[:search_string], :placeholder => "Search by firstname" %>
<%= submit_tag "Search" %>
</p>
<% end %>
<%= form_for(#email) do |f| %>
<fieldset>
<div class="form-group">
<label>From Email Address</label></br>
<% #useraccounts.each do |useraccount| %>
<%= f.radio_button :account_id, useraccount.account_id, :checked => false %>
<%= f.label :account_id, useraccount.account.email, :value => "true" %><br>
<% end %>
</div>
<div class="form-group">
<label>Contacts</label></br>
<%= f.collection_check_boxes :contact_ids, #contacts, :id, :fullname, checked: #selected_contact_ids %>
</div>
<div class="form-group">
<label>Groups</label></br>
<%= f.collection_check_boxes :group_ids, Group.where(user_id: session[:user_id]), :id, :name ,{ prompt: "name" } %>
</div>
<div class="form-group">
<label>Attachment</label>
<%= f.file_field :attachment, :size => 42 %><br>
</div>
<div class="actions">
<%= f.submit "Continue", {:class => 'btn btn-primary '} %>
<%= render "/error_messages", :message_header => "Cannot save: ", :target => #email %>
</div></br>
</fieldset>
<% end %>
</div>
The controller code for the search is:
def contact_search
#email = Email.new(session[:email_params])
#email.current_step == session[:email_step]
#useraccounts = Useraccount.where(user_id: session[:user_id])
#contacts = Contact.contact_search(params[:search_string])
if #contacts.empty?
flash[:notice] = "There are no emails with that subject"
#contacts = Contact.all
end
render :action => "new"
end
private
def email_params
params.require(:email).permit(:subject, :message, :account_id, { contact_ids: [] }, { group_ids: [] }, :attachment)
end
And in the model:
def self.contact_search(search_string)
self.where("firstname LIKE ?", search_string)
end
I cannot work out how to keep a checkbox selected after a user then searches for something else or resets the search, can someone please shed some light on how this can be achieved?
This seems to be one of those obscure and badly documented features of Rails. What has to be done is pass an array if ids to be checked into the checked parameter
= f.collection_check_boxes :contact_ids, #contacts, :id, :fullname, checked: #selected_contact_ids
and then check boxes with items of id 1, 2 and 3 will be checked. You will need to pass this array obviously from the controller somehow. E.g.
#selected_contact_ids = email_params.fetch(:contact_ids, [])
Related
Firstly, I would like to describe what I am going to do. So, my application is set of tasks (eg. exercises depend on writing computer program) which user it available to send solutions through form and server will have compiled it and return results of process.
My problem is that I have model Solution which is presented below:
Solution(id: integer, exercise_id: integer, code: string, user_id: integer,
created_at: datetime, updated_at: datetime, language_id: integer)
and exercise_id, user_id, language_id are foreign keys and postgresql return error that it couldn't be null values...
The form which I use to send this information looks like below:
<fieldset style="add">
<legend>Send solution</legend>
<%= form_for [#user, #exercise, #solution], url: exercise_solutions_path, :html => { role: "form" } do |f| %>
<div class="form-group">
<%= f.label "Source code" %>
<br>
<%= f.text_area :code %>
</div>
<div class="form-group">
<%= f.label "Programming language" %>
<br>
<%= f.select(:language_id, available_lang) %>
</div>
<div class="form-group">
<%= f.submit "Send", :class => "btn btn-default" %>
</div>
<% end %>
</fieldset>
Frankly speaking I don't how to include more information such as user.id or exercise.id. Params look like:
#_params
{"utf8"=>"✓", "authenticity_token"=>"abwhTn3KrVneli0pCVccoWHyzlI7cRTFK5Wo7DdYRK+lL4GwZ8jUPqdzn8ZznCHsWTkfDAFS2RP6gTkWuk33iw==", "solution"=>{"code"=>"ds", "language_id"=>"C++"}, "commit"=>"Wyślij", "controller"=>"solutions", "action"=>"create", "exercise_id"=>"1"}
SolutionController
class SolutionsController < ApplicationController
def index
#solutions = Solution.last(20)
end
def new
#solution = Solution.new
end
def create
#solution = Solution.new(solution_params)
if #solution.save
redirect_to #solution
else
render :new
end
end
def edit
#solution = Solution.find(params[:id])
if #solution.update(solution_params)
redirect_to #solution
else
render :edit
end
end
def destroy
end
private
def solution_params
params.require(:solution).permit(:language_id, :code)
end
end
Edit:
<fieldset style="add">
<legend>Send solution</legend>
<%= form_for [#user, #exercise, #solution], url: exercise_solutions_path, :html => { role: "form" } do |f| %>
<div class="form-group">
<%= f.label "Source code" %>
<br>
<%= f.text_area :code %>
</div>
<div class="form-group">
<%= f.label "Programming language" %>
<br>
<%= f.select(:language_id, available_lang) %>
</div>
<div class="form-group">
<%= f.hidden_field :exercise_id, value: #exercise.id %>
<%= f.hidden_field :user_id, value: #user.id %>
<%= f.submit "Send", :class => "btn btn-default" %>
</div>
<% end %>
</fieldset>
You could 1) add hidden_fields in your form to set the missing attributes:
<div class="form-group">
<%= f.hidden_field :exercise_id, value: #exercise.id %>
<%= f.hidden_field :user_id, value: #user.id %>
<%= f.submit "Send", :class => "btn btn-default" %>
</div>
Make sure to add these attributes to the solution_params permitted parameters:
def solution_params
params.require(:solution).permit(:language_id, :code, :exercise_id, :user_id)
end
A better idea would be to manually set the exercise and user in the controller and leave your solution_params as is. That way you're not allowing the exercise and user to be set by mass assignment, which could be spoofed.
So instead do 2) in your controller:
def create
#solution = Solution.new(solution_params)
#solution.exercise_id = params[:exercise_id]
#solution.user_id = params[:user_id]
if #solution.save
redirect_to #solution
else
render :new
end
end
I'm assuming that :exercise_id and :user_id are in the URL. If not add them as hidden_fields as needed (but this time not on the form object):
<%= hidden_field_tag :user_id, #user.id %>
Also remember to actually select a language_id from the dropdown before you submit the form.
I got a backend(Namespace admin) and want to create 4 new database entries with 1 form submit(4 new countries). What I got so far:
In my countries_controller.rb
class Admin::CountriesController < Admin::AdminController
def new
#countries = Array.new(4) { Country.new }
end
end
In my new.html.erb:
<%= form_for [:admin, #countries] do |f| %>
<% #countries.each do |country| %>
<div class="row">
<div class="col-md-6">
<div class="form-group col-md-6">
<%=f.text_field :country, :name, :class => "form-control", :placeholder => "Country 1" %><br>
<%=f.text_field :country, :iso, :class => "form-control", :placeholder => "us" %>
</div></div></div>
<% end %>
<% end %>
But that doesn't work and I get a undefined method model_name for Array:Class error. What is the right way to do this?
form_for is for a single ActiveRecord object, but you're using it with an Array of object :
<%= form_for [:admin, #countries] do |f| %>
Either create a form per object (with each form a save button):
<% #countries.each do |country| %>
<%= form_for [:admin, country] do |f| %>
...
<% end %>
<% end %>
Or see this question for a solution using only one form: Multiple objects in a Rails form
I have these forms:
<%= form_for(#user) do |f| %>
<div>
<%= f.number_field :money, :value => #user.money %>
</div>
<% end %>
and
<%= form_for #product, :url => product_path, :html => { :multipart => true } do |f| %>
<div>
<%= f.label :count, 'How Many product?' %><br />
<%= f.number_field :count, :value => "1" %>
</div>
<div>
<%= f.submit('submit') %>
</div>
<% end %>
is there any way to submit this two at once when clicking submit button ? Thanks!
A service object might be a good way to approach this.
class Order
include ActiveModel::Model
attr_accessor :money, :count
def initialize(user=nil, product=nil)
#user = user
#product = product
#money = user.money
#count = 1
end
def persisted?
false
end
def save
// this code needs to save to db
end
end
Hello i have a form like
<%= form_for #user,
:url => url_for(:controller => 'frontend',
:action => 'registration_completion') do |f| %>
<div class="control-group">
<%= f.label :name, "Jméno", :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'text_field' %>
</div>
</div>
And user is displaying the form where he can see already registered values, but some of that value i want to hide if some condition (specifically i need hide value of username if it contains #) It is possible? thank you
solution: it seems that
<% if #user.name.include?('#') %>
<%= f.text_field :name %>
<% else %>
<%= f.text_field :name, :value => "" %>
<% end %>
works
I strongly suggest to put your logic inside a helper method:
module UserHelper
def name_input(instance, f, options = {})
options[:html_options] ||= {}
f.text_field :name, options[:html_options] if instance.name.include?('#')
end
end
Then in your view:
<%= name_input(#user, f, html_options: { class: 'text_field' }) %>
If you want to simply hide the value you can do:
<%= f.text_field :name, value: #user.name.include?('#') ? #user.name : '' %>
Feel free to move this to a helper method also.
To create a hidden field when the username contains an # symbol you could use the following helper method
module UserHelper
def hidden_name_field(user, f, options = {})
options[:html_options] ||= {}
if user.name.include?('#')
f.hidden_field(:name, options[:html_options])
else
f.text_field(:name, options[:html_options])
end
end
end
and use it in you form:
<%= hidden_name_field(#user, f, html_options: { class: 'text_field' }) %>
I am working on a script that allows for an admin to assign multiple languages to a user.
I have my multi select working like so:
<%= fields_for :users_languages do |u| %>
<div class="field">
<%= #lang_list.inspect %>
<%= u.label :Assign_Languages %><br />
<%= select_tag :language_id, options_for_select(Language.all.collect {|lang| [lang.english, lang.id]}),:multiple => true, :prompt => 'Select Language' %>
</div>
<% end %>
But when I go in to edit the user their languages are not showing up as auto selected. How would I go about doing this?
Figured it out by doing the following:
Controller:
def edit
#user = User.find(params[:id])
#users_langs = UsersLanguage.where("user_id = ?", params[:id])
#lang_list = []
#users_langs.each do |langs|
#lang_list << langs.language_id
end
end
I created an array variable called #lang_list, which I then used in my view to tell my multi-select which fields to auto highlight.
View:
<%= fields_for :users_languages do |u| %>
<div class="field">
<%= u.label :Assign_Languages %><br />
<%= select_tag :language_id, options_for_select(Language.all.collect {|lang| [lang.english, lang.id]}, #lang_list),:multiple => true, :prompt => 'Select Language' %>
</div>
<% end %>
Hope this helps someone!