Showing name in drop down select box - ruby-on-rails

I want to create a task and assign to a particular user who has_one profile with first name and last name.
And also user has_many tasks.
My new task form is
<%= form_for :task do |f| %>
<div>
<%= f.label :task %>
<%= f.text_area :task %>
</div>
<div>
<%= f.label :assigned_to %>
<%= f.collection_select(:assigned_to, User.profile.all, :fist_name, :fist_name, :include_blank => 'None')%>
</div>
in the collection select I should display something like " Sam Parker (sam#org.com)" like this all the users should be available in the collection select field.
Can anyone help me how to display it.

First of all read the documentation here:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-collection_select
I guess you need to create a method that returns the option's text, for example:
class User < ActiveRecordBase
# ...
def label_for_select
"#{profile.full_name} (#{profile.email})"
end
end
Then, in your view it would be something like:
<div>
<%= f.label :assigned_to_id %>
<%= f.collection_select(:assigned_to_id, User.all, :id, :label_for_select, :include_blank => 'None')%>
</div>
Notice that the form sets the assigned_to_id not the assign_to ruby object. Rails will instantiate the assign_to object based on this id.

Related

How to use nested forms in Rails if the fields have the same name?

I have two models, Dog and Owner, and I want their names to be the same, and would be redundant if I asked to fill out the fields twice (once for the dog and another time for the owner). I'm wondering if there's a simpler way to update the two databases with one input.
<h1>Create a new Dog:</h1>
<%= form_for(#dog) do |f|%>
<div>
<%= f.label :name%>
<%= f.text_field :name%>
</div><br>
<div>
<%= f.label :breed%>
<%= f.text_field :breed%>
</div><br>
<div>
<%= f.label :age%>
<%= f.text_field :age%>
</div><br>
<div>
<h3>create a new owner:</h3>
<%= f.fields_for :owner, Owner.new do |owner_attributes|%>
<%= owner_attributes.label :name, "Owner Name:" %>
<%= owner_attributes.text_field :name %>
<% end %>
</div>
<%= f.submit %>
<% end %>
First of all, not sure why you want to keep the name of the owner and the dog same.
However, there can be many ways to achieve what you want:
You can simply omit the owner name from the form.
So you no longer need: <%= owner_attributes.label :name, "Owner Name:" %>
OR you no longer need:
<div>
<%= f.label :name%>
<%= f.text_field :name%>
</div><br>
And in the Owner/Dog model, you can pass the name of the dog/owner in a callback - maybe after_initialize or before_save or before_validation depending on your validation requirements.
class Dog
belongs_to :owner
before_validation :set_name
private
def set_name
self.name = owner&.name
end
end
You can make the owner name as a hidden field instead and can write some javascript to update the hidden field with the dog name before submitting the form or onblur event. I would prefer the first approach since it's simpler and more secure than only JS solution to maintain database consistency
If dogs belongs_to and owner, you don't really need to store the owner's name separately. You can just call dog.owner.name anywhere you have a Dog instance. Having said that, it is relatively straightforward to append attributes on top of the POSTed form values in your controller using .merge():
def create
#dog = Dog.new(dog_params.merge(owner: params[:dog][:owner])[:name])
if #dog.save
...
end
end
def dog_params
params.require(:dog).permit(:name, :breed, :age, owner: %i[name])
end

Ruby on Rails - user forms reference param other than ID

I created the user table and I created a scaffold from there. the user table only has 1 attribute name. I created 1 user called "John"
I then created another scaffold called order generation which references the user (i.e the user must exist before i can order)
<div class="field">
<%= form.label :user_id %>
<%= form.text_field :user_id %>
</div>
However what I want is to reference the username john and then map back to the user_id. Is there a way to do this using a drop down list and display the username and in the backend, it will pass the user ID ?
update: I tried to do this but it doesnt seem to work also
<div class="field">
<%= form.label :user_id %>
<%= form.select :user_id, options_for_select(#users.each { |c| [c.name, c.id] })%>
</div>
You need
<%= form.select :user_id, options_for_select(User.all.map{|u|[u.name, u.id]}) %>
Also as pointed out in the comments by #eyeslandic this will also work
options_for_select(User.pluck(:name, :id))
Which I think is actually nicer syntax

Rails - Show objects related to user in form dropdown

In my rails application the following relationships exist:
user belongs_to :team ,
element belongs_to :team ,
task belongs_to :element
A user can then create a task which belongs to an element.
When a user is creating a task, they can select the element they would like the task to belong to. How do I show only the elements that belong to the current_user's team? I am using Devise to get the current_user.
The samples below do not work.
<div class="field">
<%= form.label :element_id %>
<%= form.select :element_id, options_for_select(Element.current_user.team_id.map{|s|[s.title, s.id]}),{ :multiple => true} %>
</div>
I also tried to call the method below from the tasks_controller.rb file but it didnt work either
def new
#task = Task.new
#tasks_element_dropdown = Element.current_user.team_id.map{|s|[s.title, s.id]}
end
In the tasks/_form.html.erb file, I called the method with the code below
<%= form.select :element_id, options_for_select(#tasks_element_dropdown),{ :multiple => true} %>
When I tried the example below it does work but it displays all elements, and I only want the elements that belong to the user's team to display
<div class="field">
<%= form.label :element_id %>
<%= form.select :element_id, options_for_select(Element.all.map{|s|[s.title, s.id]}),{ :multiple => true} %>
</div>
The problem is in the following code, which should return the elements:
Element.current_user.team_id.map{|s|[s.title, s.id]}
Since you have a user, you can get the team: current_user.team
And then get the elements of the team (as long as has_many :elements is defined in the Team class): current_user.team.elements
Thus, the final code should be something like:
<div class="field">
<%= form.label :element_id %>
<%= form.select :element_id, options_for_select(current_user.team.elements.map{ |s| [s.title, s.id] }),{ :multiple => true} %>
</div>

simple_form with two models?

This is my creation form for Customer model.
While populating customers table I am inserting some data in managers table as well. But I want to add a date picker in this simple_form but that date is only stored in Manger model and Customer model doesn't have date field. How do I do it? What alternative options I have?
new.html.erb
<%= stylesheet_link_tag "customers" %>
<div class="row">
<div class="panel panel-default center" id="new-width">
<div class="panel-body">
<%= simple_form_for #customer do |f| %>
<%= f.input :name,:autocomplete => :off %>
<%= f.input :principalAmount,:autocomplete => :off %>
<%= f.input :interestRate %>
<%= f.input :accountType %>
<%= f.input :duration,:autocomplete => :off %>
<%= f.button :submit %>
<% end %>
</div>
</div>
</div>
Edit: Manager model has many field which is independent of Customer model. But When a customer is created it has to add a date in Manager model which is absent in the Customer model.
I suggest you to use accepts_nested_attributes_for in customers model.
Something like this:
In customer model,
accepts_nested_attributes_for :managers
In view page,inside the existing form
<%= f.fields_for :managers do |m| %>
<%= m.date_field :date %>
<% end %>
You can always add a getter and setter to the customer model and manually set the manager fields. Again it depends on the relationship with manager, if it exists already, etc. but the main point is you can create methods that can then be accessed in the form as customer methods.
# in customer.rb
def manager_date=(date)
manager.date = date
end
def manager_date
manager.date
end
then in the form
<%= f.input :manager_date %>
Note - this is a brief example, you'll need to save the manager somewhere and doing this before or after the customer is updated will depend on your needs.
Another way to do this is to create an attr_accessor for manager_date in customer and if it's there, update the manager after the customer is saved
after_save :update_manager
def update_manager
manager.date = manager_date
manager.save
end

Nested fields not being added on form submit

I am using the cocoon gem to try and achieve adding an object which belongs to another with nested fields. I have a 'user_resolution' which has many 'milestones'. I have set up the associations accordingly in both of these models. For some reason, milestones are failing to be created, however if I add one manually in the database I can successfully update it. I am able to dynamically add the fields and remove them using the cocoon gem but that is all. When I click 'add milestone' it redirects me to the show view of the user resolution and throws the success message saying user resolution has been updated, no errors are thrown but the milestone(s) is/are not created.
user_resolution.rb
has_many :milestones
accepts_nested_attributes_for :milestones, reject_if: :all_blank, allow_destroy: true
milestone.rb
belongs_to :user_resolution
I have set up the nested form within the edit view as for now I only want users to add a milestone to a resolution in the edit view.
user_resolutions/edit.html.erb
<%= form_for(#user_resolution) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<%= f.fields_for :milestones do |milestone| %>
<%= render 'milestone_fields', f: milestone %>
<% end %>
<%= link_to_add_association 'Add Milestone', f, :milestones %>
<%= f.submit "Add Milestone" %>
<% end %>
_milestone_fields.html.erb
<div class="nested-fields">
<div class="field-row">
<%= f.label :name, 'Name' %>
<%= f.text_field :name %>
</div>
<div class="field-row">
<%= f.label :description, 'Name' %>
<%= f.text_area :description %>
</div>
<div class="field-row">
<%= f.label :severity, 'severity' %>
<%= f.check_box :severity %>
</div>
<div class="field-row">
<%= f.label :target_date, 'target_date' %>
<%= f.date_select :target_date %>
</div>
<%= link_to_remove_association 'Remove', f %>
</div>
The permitted parameters within the user resolutions controller also contain the following
milestones_attributes: [:id, :user_resolution_id, :name, :description, :target_date, :severity, :complete, :_destroy]
The milestones themselves have no views, they only have a model and a controller. The controller create action (which i'm unsure is required for nested forms) contains the standard following code
def create
#milestone = Milestone.new(milestone_params)
if #milestone.save
redirect_to user_resolutions_path,
:flash => { :success => "You successfully created a milestone" }
else
redirect_to new_milestone_path,
:flash => { :error => "Oops something went wrong. Try again." }
end
end
I've been as informative as I can but if you need anything else let me know. Thanks guys.
which i'm unsure is required for nested forms
You don't need a create action for milestones - they'll be populated from the user_resolutions#create controller action.
There are several things to look at with this. I'll detail some here. This won't be a specific answer, but may help point you in the right direction.
Firstly, you need to make sure you're receiving the correct params.
Cocoon does a great job building the nested form - you need to make sure it's obliging Rails' nested attribute structure.
To do this, you should right-click > view source.
In the f.fields_for section (it won't be called that in the HTML), you'll be looking for the equivalent to the following:
<input type="text" name="milestones_attributes[0][name]" value="">
The important thing to note is the name...
Each time you use a form, or any Rails view helper for that matter, you're really just building standard HTML. form_for just creates an HTML form, and thus any params contained within it need to adhere to a certain structure for Rails to recognize the params.
The f.fields_for elements will typically be called x_attributes[:id][:param] - this is passed to Rails, which cycles through each [:id] to determine the number of nested params to add.
You need to check the source for the above naming structure. If you see it, that's good. If not, it means you haven't built your form properly.
Secondly, you need to make sure your objects are being built in the controller.
I'm not sure how Cocoon does this, but essentially, each time you use f.fields_for, you have to build the associated object before:
def new
#user_reservation = UserReservation.new
#user_reservation.milestones.build #-> this is what makes f.fields_for work
end
If the first step shows incorrect element naming, it means your associative objects are not being built (which is why they're not being recognized).
To test it, you should build the associative objects in the new method, before sending.
Finally, you'll want to post your params.
These tell you in explicit detail what Rails is doing with the nested attributes, allowing you to determine what's happening with them.
Sorry for the long-winded answer. You'll not have received any answers anyway, so I felt it prudent to give you something.

Resources