Rails object method returning full array - ruby-on-rails-4

I'm having an issue with an association. I've got an Employee model that belongs_to a Role model. When I try to display the association, I get the full array displayed back.
Here's the show action from my Employee controller. As you can see, I've tried a few different methods to make the proper association in the first place:
def show
#employee = Employee.find(params[:id])
# #role = Role.where(:id => #employee)
# #role = Role.find_by_sql("select roles.role_title from roles where roles.id in (select role_id from employees where role_id='1')")
#role = Role.where(id: #employee)
end
And here's the view:
<p>
<strong>Role:</strong>
<%= #role.each do |r|
r.role_title
end %>
</p>
My output comes back as:
Role: [#<Role id: 3, role_title: "Support Engineer", created_at: "2014-08-20 16:09:22", updated_at: "2014-08-20 16:09:22">]
What am I missing here?

You need to actually iterate and display something for each role.
<%= %> means "display the result of the expression", which in your case, is an each.
each returns the collection you were iterating over. You want something closer to:
<% #role.each do |r| %>
<%= r.role_title %><br/>
<% end %>
Although it obviously depends on what you actually want to display, for example:
<%= #role.collect(&:role_title).join(', ') %>
Unrelated: I might argue that Role#role_title is redundant and Role#title would be sufficient.

If the employee belongs_to a role there is only one role for each employee.
You can retrieve it as easily as specifying...
#employee.role
but if you insist on constructing a separate retrieval then
#role = Role.where(id: #employee.role_id).first
EDIT
So talking about the views... if there's only one #role you don't need to iterate through an array...
<p>
<strong>Role:</strong> <%= #role.role_title %>
</p>
You're seeing an array because the where returns an array, you could bypass that with...
#role = Role.where(id: #employee).first
As Dave Newton pointed out, if it really was an array you'd need to do...
<p>
<strong>Role:</strong>
<% #role.each do |r| %>
<%= r.role_title %>
<% end %>
</p>

Related

Ruby on Rails, Datepicker search between two dates

I am a new ROR user trying to implement a DateTime picker to select dates for a search function.
My problem is that when I enter two dates (date from, and date to) in the DatePicker, I get inconsistent results from the search. Sometimes I get no results, and sometimes I get all the results. I am also using the bootstrap-datepicker-rails gem as well as the ransack gem.
This is what my view looks like
<div class="field">
<%= f.label :departure_date_gteq, "Departure Date Between" %>
<%= f.search_field :departure_date_gteq, "data-provide" => "datepicker" %>
<%= f.label :return_date_lteq, "and" %>
<%= f.search_field :return_date_lteq, "data-provide" => "datepicker" %>
</div>
The two database columns I am referencing are departure_date, and return_date. The date stored is datetime and looks like this,
departure_date
2016-08-07 00:00:00.000000
return_date
2016-08-14 00:00:00.000000
I enter 2016-08-06 and 2016-08-15 in the DatePickers and I am returned all the results.
Could my search form DatePicker be sending data that cannot be correctly compared to the DateTime in the database?
Am I using the 'gteq' and 'lteq' calls correctly?
EDIT #1
#Michael Gaskill, you are correct that the problem is the date formatting. When I enter a date manually, I get the correct search results. I just need to figure out how to correct the formatting before its passed to the controller.
Here is what my controller looks like.
class HomeController < ApplicationController
def index
#search = Sailing.search(params[:q])
#sailings = #search.result
... Other calls ...
end
end
Here is the full piece of code in my view that generates sailings content. Note that I'm using search_for_for which is part of the ransack gem.
<%= search_form_for #search, url: root_path, method: :post do |f| %>
<div class="field">
<%= f.label :cruise_ship_name_or_cruise_ship_company_or_destination_identifier_cont, "Cruise Ship Name" %>
<%= f.text_field :cruise_ship_name_or_cruise_ship_company_or_destination_identifier_cont %>
</div>
<div class="field">
<%= f.label :departure_date_gteq, "Departure Date Between" %>
<%= f.search_field :departure_date_gteq, "data-provide" => "datepicker" %>
<%= f.label :return_date_lteq, "and" %>
<%= f.search_field :return_date_lteq, "data-provide" => "datepicker" %>
</div>
<div class="actions"><%= f.submit "Search" %></div>
<% end %>
Thanks.
You need to convert the string-formatted dates entered in the form (either via the DatePicker or manually-entered) to Date or DateTime values. When you query the database, use this DateTime#strptime to convert:
MyTable.where(date_field_to_search: DateTime.strptime(date_value_from_ui, "%F %T")
You can check out the formats available as the second argument to strptime, using the instructions at DateTime:strftime. Note that strftime and strptime are used to convert back and forth between DateTime and formatted String values.
In your Sailing#search(params[:q]) example, you can either implement the solution in Sailing#search (if you have access to change that code) or prior to calling Sailing.search.
Here is how you might implement this in Sailing#search:
class Sailing
def search(args)
datetime = args[:date_field_to_search]
if datetime.kind_of?(String)
datetime = DateTime.strptime(datetime, "%F %T")
end
# other search functionality
end
end
or, prior to calling Sailing#search:
datetime = params[:q][:date_field_to_search]
if datetime.kind_of?(String)
datetime = DateTime.strptime(datetime, "%F %T")
end
Sailing.search(params[:q].merge({ date_field_to_search: datetime })

rails4-autocomplete with belongs to association

I want to implement autocomplete via rails4-autocomplete
Rails 4.2.4
Here is the controller
app/controllers/samples_controller.rb
class SamplesController < ApplicationController
autocomplete :patient, :code
Here is the route file,
config/routes.rb
resources :samples do
get :autocomplete_patient_code, on: :collection
end
And that's the view
app/views/samples/_form.html.erb
<div class="field">
<%= f.label :patient_code %><br>
<%= f.autocomplete_field :patient_id, autocomplete_patient_code_samples_path %>
</div>
With this code I mange to get the autocomplete
However I get invalid foregin key error when try to save the sample that's because the patient's code is passed to the foregin key instead of ID. How do I fix this?
Here is the request Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"blabla",
"sample"=>{"patient_id"=>"A123",
"commit"=>"Create Sample"}
Get "/samples/autocomplete_patient_code?term=A12" returns
{"id":"15","label":"A123","value":"A123"}]
After reading the GitHub documentation of rails4-autocomplete, I devised the following solution:
Add attr_accessor :patient_name to your Sample model and modify the form as follows:
...
<%= f.autocomplete_field :patient_name, autocomplete_patient_code_samples_path, id_element: '#patient_id' %>
<%= f.hidden_field :patient_id, id: 'patient_id' %>
...
With this change whenever you select any patient name, that patient's ID will be updated on the hidden field and it will be submitted as patient_id.
Hope this solves your problem.
Source: Github

RoR: How to set the value in a collection_select from the database in the edit view (1:many relation)

I am at the moment creating a complicated rails form for 1:n relationship with nested form and collection select with values from yet another data table.
So far, it overwrites the database value with the first entry in the values list of the collection_select whenever the user does not select the correct value before update. I still need to set the initial value in the collection_select correctly.
I have read a lot of questions on SO already, most relevant was:
f-collection-select-not-displaying-the-selected-value
The only thing still missing (I hope!), is the setting of the value of the form field from the database, so it does not get overwritten with a default value from the selects selectable values, even though the user has not touched the select.
This snippet is derived from my code and the solution to the abovementioned question and is wrong.
Let a person have many things and validthings contains the possible values for things:
In the things table there will only be Thing strings, that are also in the validthings table. It is possible to give the collection_select selected param a string from the things table that can be identified in the list of values from the validthings table.
<div class="col-md-12">
<%= form_for(#person) do |f| %>
<%= f.fields_for :things do |d| %>
<%= d.hidden_field :id %><%= d.hidden_field :person_id %>
<%= d.collection_select(:Thing, Validthings.all, :Thing, :Thing, {:selected => #person.things.map(&:id).Thing.to_s} ) %>
<% end %>
<% end %>
</div>
This is what is wrong:
#person.things.map(&:id).Thing.to_s
And yes, in tables persons and things and validthings the column is named "Thing". It is a unique string in table validthings - the database structure was not my idea, I only work with it.
Found a helpful answer here: rails-accessing-current-value-of-a-symbol
to another subject, but my problem was that I did not know how to access the information that I knew must already be loaded.
This is how I can specify the default value of a collection_select to be the data from the database:
<div class="col-md-12">
<%= form_for(#person) do |f| %>
<%= f.fields_for :things do |d| %>
<%= d.hidden_field :id %><%= d.hidden_field :person_id %>
<%= d.collection_select(:Thing, Validthings.all, :Thing, :Thing, {:selected => d.object.Thing} ) %>
<% end %>
<% end %>
</div>
where d.object.Thing is the value of the respective object of the form element for the attribute "Thing", which is already present in the form.
I'd be very grateful for constructive ideas, in case my approach is un-ruby-like or some such. I am rather new to ruby, rails etc.

(Rails 4) Acts_as_taggable_on: using a model other than "Tag"

I am trying to implement the acts_as_taggable_on gem. In my set up I have a Model called Discipline which is pre-populated with about 40 names.
I also have a Model Micropost which I want to tag - using a select box containing all the names in the disciplines database. I thought that I could call the acts_as_taggable_on the Model I wanted - in this case Disciplines but its not working with my current set up.
class Micropost < ActiveRecord::Base
acts_as_taggable
acts_as_taggable_on :disciplines
end
Here is the form......
<%= simple_form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.input :tag_list, :as => :select,
:multiple => :true,
:collection => ActsAsTaggableOn::Tag.pluck(:name) %>
<%= f.text_area :content, placeholder: "What is your question?", :style => "height:75px;" %>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
I can tell from the documentation that there is a way to do this....but I guess I am just not getting it. Any suggestions?
I don't think you can use acts_as_taggable_on using a model other than the default Tag and Taggings models.
Alternative Approach #1
Seed your database with the pre-populated 40 Tags containing your discipline names.
Alternative Approach #2
Use bitmask_attributes for your 40 disciplines.
For example, in my application I have:
bitmask :instruments, as: [:others, :guitar, :piano, :bass, :mandolin, :banjo,
:ukulele, :violin, :flute, :harmonica, :trombone,
:trumpet, :clarinet, :saxophone, :viola, :oboe,
:cello, :bassoon, :organ, :harp, :accordion, :lute,
:tuba, :ocarina], null: false

Rails Update Model from Multiple Select Form: No implicit conversion of String into Integer

If Project has_many Genre through: GenresProject
and params are:
def project_params
params.fetch(:project, {}).permit(genres_projects_attributes: [:id, {genre_id: []})
end
and my submit form is:
<%= form_for #project do |f| %>
<%= f.fields_for :genres_projects_attributes do |ff| %>
<%= ff.select :genre_id, Genre.order(:id).collect{|g| [g.name, g.id]}, {}, { multiple: true } %>
<% end %>
<%= f.submit 'Update'%>
<% end %>
and my params look like this:
"project"=>{ ... "genres_projects_attributes"=>{"genre_id"=>["3", "5"]}} ... }
Should
project.update(project_params)
Automatically iterate through the genre_id array and create the appropriate GenresProject records?
If you don't have GenreProject record, then you will not get an id from the params.
Secondly, it will not automatically create the new Genre record or update one for you, I think. You should handle creating new record in the update action yourself. For example:
params[:project][:genre_id].each do |id|
unless GenreProject.find(id)
# create new record here
GenreProject.create
end
# other updating operations
end
Hope it works for you