I am trying to add a relational field drop down select to the existing table. My current Schema
create_table "hardwares", force: :cascade do |t|
t.string "serialnumber"
t.string "modelnumber"
t.string "modeltype"
t.string "location"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "poc_id"
t.index ["poc_id"], name: "index_hardwares_on_poc_id"
end
create_table "pocs", force: :cascade do |t|
t.string "name"
t.string "address"
t.string "facility"
t.string "phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The index field in the hardwares table was created when I ran the migration.
rails g migration addPocReferencesToHardwares poc:references
which generated the migration file below as well as the index in the schema
class AddPocReferencesToHardwares < ActiveRecord::Migration[5.1]
def change
add_reference :hardwares, :poc, foreign_key: true
end
end
After setting up the relationship, I would like to be able to select a POC for the hardware by name as a drop down of all available POC's.
I added this to the Hardware form:
<div class="field">
<%= form.label "POC" %>
<%= form.collection_select(:poc_id, Poc.all, :id, :name, { :prompt => 'Select a POC', :selected => #poc.poc_id }, { class: 'form-control' }) %>
</div>
The error I get is " undefined method `poc_id' for nil:NilClass". How do I allow a drop down selection for adding a POC to the hardware?
Issue was the fact that I had set the relationship as POC belongs to Hardware, thus in the Form field it needed to be:
<div class="field">
<%= form.label "POC" %>
<%= form.collection_select(:poc_id, Poc.all, :id, :name, { :prompt => 'Select a POC', :selected => #hardware.poc_id }, { class: 'form-control' }) %>
</div>
Related
Would be super grateful if anyone had any insights into what I should be doing that I'm not already doing.
db/schema.rb
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "password_digest"
t.bigint "cell_number"
t.boolean "sms_daily"
t.string "initials"
t.string "remember_token"
t.boolean "admin", default: false
t.boolean "vacation_mode", default: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "remember_digest"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["remember_token"], name: "index_users_on_remember_token"
end
create_table "schedules", force: :cascade do |t|
t.text "comments"
t.integer "author_id", null: false
t.boolean "draft", default: true
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["author_id"], name: "index_schedules_on_author_id"
end
create_table "rooms", force: :cascade do |t|
t.integer "schedule_id", null: false
t.integer "order"
t.string "site"
t.string "note"
t.string "name"
t.integer "start_hour"
t.integer "start_minute"
t.string "user_initials"
t.boolean "block"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["schedule_id"], name: "index_rooms_on_schedule_id"
end
app/model/schedule.rb
class Schedule < ApplicationRecord
belongs_to :author, class_name: "User"
has_many :rooms
accepts_nested_attributes_for :rooms
...
end
app/model/room.rb
class Room < ApplicationRecord
belongs_to :schedule
...
end
app/views/schedule/new.hthl.erb
<% provide(:title, 'Create Schedule') %>
<h1>Create Schedule</h1>
<div class="row">
<aside class="span4">
<section>
<%= form_with(model: #schedule, local: true) do |f| %>
<div class="field">
<%= f.fields_for :rooms, html: {class: 'form-inline' } do |r| %>
<div class="room-title" id="<%="#{r.object[:site]}-#{r.object[:name].delete(' ')}" unless r.object[:name] == nil %>">
<%= "#{r.object[:site]} #{r.object[:name]}"%>
<%= r.hidden_field :site, value: r.object[:site] %>
<%= r.hidden_field :name, value: r.object[:name] %>
<% unless (r.object[:name] == "CHARGE" || r.object[:name] == "CO-CHARGE" || r.object[:site] == "ON_CALL" || r.object[:site] == "On-Call TODAY (Sunday or Holiday)") %>
<br/>
<%= r.label :start_hour %>
<%= r.number_field :start_hour, in: 0..24, step: 1 %>
<br/>
<%= r.label :start_minute %>
<%= r.number_field :start_minute, in: 0..60, step: 1 %>
<% end %>
<%= r.collection_select(:user_initials,User.all.map(&:initials).sort.unshift("-- late start").collect,:initials,:initials, include_blank: true) %>
</div>
<% end %>
<%= f.submit "Save Schedule and Review", class: "btn btn-large btn-primary", input_html: { :tabindex => autotab } %>
</div>
<% end %>
</section>
</aside>
</div>
I'd like for the form to present a choice of all the User's initials to be assigned to the room's user_initials, also offer the choice of not designating anyone's initials with "-- late start" as well as leaving the initials blank for an empty room.
When I deploy my code to heroku the schedule/new page generates a "We're sorry, something went wrong" error and the logs say:
ActionView::Template::Error (undefined method `initials' for "-- late start":String):
I got this all working in Rails 4 using simple_form but heroku will no longer support the stack that I deployed the site to starting in November, 2020, and heroku's new stack's won't use the old ruby version from the original site. I'm rewriting the code in Rails 6 which simple_form doesn't work for.
Thanks in advance for your consideration!
collection_select works on a collection of objects and will look for the initials method on each object.
when you do this...
<%= r.collection_select(:user_initials,User.all.map(&:initials).sort.unshift("-- late start").collect,:initials,:initials, include_blank: true) %>
You're just creating an array of strings, and you're prepending another string to the array, and the strings don't have an initials method.
Better might be just to use select
<%= r.select(:user_initials, options_for_select(User.all.pluck(:initials).sort.unshift("-- late start"), r.object.user_initials), include_blank: true) %>
You can use collection_select, it must be ALL user objects, so you could temporarily create a user with initials '--late start', something like...
<%= r.collection_select(:user_initials, User.order(:initials).to_a.prepend(User.new(initials: "-- late start")), :initials, :initials, include_blank: true) %>
I have a joined table but looking for a way to input the information from a form into both tables, or have it work in general:
My schema:
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories_listings", id: false, force: :cascade do |t|
t.integer "category_id", null: false
t.integer "listing_id", null: false
end
create_table "listings", force: :cascade do |t|
t.string "name"
t.text "description"
t.decimal "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image"
t.integer "user_id"
end
Models:
class Category < ApplicationRecord
has_and_belongs_to_many :listings
end
Listing < ApplicationRecord
belongs_to :category, required: false
belongs_to :categories_listings, required: false
end
Views
<%= form_with(model: listing, local: true) do |form| %>
...
<div class="space">
<%= form.select :category_ids, options_from_collection_for_select(Category.all, :id, :name), :prompt => "Select a Category", :multiple => true %>
</div>
...
Before i joined the tables, I had it working with a categories element (i believe thats the right term) within the listing tables that was attached to a categories table... You can see my previous post on SO where I was suggested to do this: Allowing multiple records in category to submit to listing
When i click submit, nothing enters into the categories_listings tables. Suggestions on how I make this happen?
The associations in your Listing model are wrong. It should be just
Listing < ApplicationRecord
has_and_belongs_to_many :categories
end
I suggest you to read has_and_belongs_to_many
I have a drop down of options that links to the names in a profiles table. They are linked by a key named "profile_id". When I select on of these options and display it in the show page. It shows me the profile_id, but I want to show the name. Can anyone tell me how to do this.
The Form View Selection looks like this:
<div class="field">
<%= f.label :profile %><br>
<%= f.collection_select :profile_id, Profile.all, :id, :name, {:prompt => 'Please select an Aritst or Band'} %>
</div>
The Show View looks like this:
<p>
<strong>Artist:</strong>
<%= #album.profile_id %>
</p>
The schema is like this:
create_table "albums", force: :cascade do |t|
t.string "title"
t.date "released"
t.string "genre"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "profile_id"
t.string "image"
end
create_table "profiles", force: :cascade do |t|
t.string "name"
t.date "born"
t.string "bio"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image"
end
The form does give me the correct name options so the tables are linking up correctly. But when I view the results, it gives me the profile id and not the name I selected. Now I am aware that is because I have specified for it to do this. But how do I get it to show the name. Can it be done in the show view code or does it have to be converted in the controller or model somewhere.
I intend on that selected option also being a link back to the profile. If you know this also, that would help me out big time.
As always, all help is greatly appreciated.
Change your show action to
<p>
<strong>Artist:</strong>
<%= #album.profile.name %>
</p>
I have Item and List models and they are both associated. List has_many items and an item belongs_to a list
Schema:
create_table "items", force: :cascade do |t|
t.string "name"
t.integer "list_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "completed", default: false
end
create_table "lists", force: :cascade do |t|
t.string "name"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "permission", default: "private"
end
I want to create a view (most likely items/new.html.erb) so when a user creates a new item, there will be a drop-down option for the user to select which list it belongs to. There will be a pre-defined list in the beginning (i.e.: List name: "Home", "Work", "Personal"). Any item that user makes will be associated to either one of those three.
Right now I have an Item new.html.erb view that takes in simple item name and list_id.
<%= form_for #item do |f| %>
<%= f.label :name %><br>
<%= f.text_area :name, size: "24x12" %><br>
<%= f.label :list_id %><br>
<%= f.text_field :list_id %><br>
<%= f.submit %>
<% end %>
Entering list_id manually is very inconvenient; after researching, it seems like select_tag is the best form helper to do the job.
How can I build a select_tag that displays 3 drop-down List that a user can choose from to associate an Item to List?
you can also use select since you use form to achieve this. since you mentioned List name are pre-defined you can do it like this:
<%= f.select :list_id, options_for_select([['Home', 1], ['Work', 2], ['Personal', 3]]), {:include_blank => true} %>
Note: ['Home', 1] home has an id of 1 here {:include_blank => true} to include blank.
I've renamed the SessionsController and Session Model to Periods/Period because it conflicted with Devise and so you'll see this in the update
I have a sessions and events model/controller. When a new session is created, it needs to be associated with a particular event.
In my sessions model, I have an event_id, but I want to have a dropdown on the form that is populated with name of non-past events. Once that is selected, the form should be able to assign the correct event_id to the created session.
What is the correct way to go about doing this?
Here is my schema.rb to help you get a clearer picture of what the Models look like:
ActiveRecord::Schema.define(:version => 20120807154707) do
create_table "events", :force => true do |t|
t.string "name"
t.date "date"
t.string "street"
t.string "city"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "sessions", :force => true do |t|
t.string "name"
t.integer "event_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "admin", :default => false
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
end
Here is my form:
<%= form_for(#period) do |f| %>
<%= f.label :Name %>
<%= f.text_field :name%>
<%= f.label :Event %>
<%= f.collection_select(:period, :event_id, Event.all, :id, :name)%>
<%= f.label :time %>
<%= f.text_field :time, id: "timepicker" %>
<%= f.submit "Create Event" %>
<% end %>
and I keep getting the following error: undefined methodmerge' for :name:Symbol`
Breaking out the various arguments of collection select: f.collection_select(:period, :event_id, Event.all, :id, :name)
:period -> The object
:event_id -> the method I want to set on the object.
Event.All -> The collection (for now I'll take all of them)
:id -> the value of the html element option
:name -> the value displayed to the user
Am I doing that correct?
To display a select menu with options from another model (not another controller), try collection_select.
In your new Session form, this might look like:
collection_select(:event, :id, Event.where("date > :date", date: Time.now.strftime("%m/%d/%Y"))
In the Sessions controller, in the create action, build the association like this:
#session.event = Event.find(params[:event][:id])
I have found that this structure works for me:
<%= f.label :event %>
<%= f.collection_select :event_id, Event.all, :id, :name, {:prompt=> "Pick an Event"}, {:class => "form-control"} %>
The last bit was the html part which I used to set the Bootstrap class.
:name here could be :date or :street etc...