Values of helper collection_select is being called twice - ruby-on-rails

I have model Category:
class Category < ActiveRecord::Base
has_many :projects
end
Model project:
class Project < ActiveRecord::Base
belongs_to :category
validates :title, :description, :category, :skill, :payment, presence: true
validates :price, numericality: { only_integer: true }
PRICE_CATEGORIES = ['cat_price1', 'cat_price2', 'cat_price3', 'cat_price4']
end
projects/new
<%= form_for #project, url: {action: 'create'} do |f| %>
<p>
<%= f.label 'Titel' %>
<%= f.text_field :title %>
</p>
<P>
<%= f.label 'Budget' %>
<%= f.text_field :price %>
für
<%= f.select :price_category, Project::PRICE_CATEGORIES %>
</P>
<p>
<%= f.label 'Beschreibung' %>
<%= f.text_area :description %>
</p>
<p>
<%= f.label 'Kategorie' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
</p>
<P>
<%= f.submit 'erstellen' %>
</P>
<% end %>
schema.rb:
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 "projects", force: :cascade do |t|
t.string "title"
t.text "description"
t.integer "price"
t.string "skill"
t.string "location"
t.string "payment"
t.boolean "anonymity"
t.string "file"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "price_category"
end
When calling <%= f.collection_select :category_id, Category.all, :id, :name %>
all items in dropdown list displaying twice. Cant undestand, why.
For example:
cat1
cat2
cat3
cat1
cat2
cat3
Thank for you help.

Related

Rails 5 - Nested Model Form Not Saving Child Model Attributes

I've been at this problem for a couple weeks now on and off.
Currently I have a User model, Employee model and an Employee_Contact model. The User model was generated using Devise. After the User is logged in they can go to their User Dashboard and create an Employee using a nested form. I am having an issue where the child model Employee_Contact is not saving into the database.
Schema:
create_table "employee_contacts", force: :cascade do |t|
t.string "street"
t.string "city"
t.string "state"
t.string "zip"
t.string "phone_num"
t.string "alt_phone_num"
t.string "email"
t.string "emergency_contact_first_name"
t.string "emergency_contact_last_name"
t.string "emergency_contact_num"
t.integer "user_id"
t.integer "employee_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["employee_id"], name: "index_employee_contacts_on_employee_id"
t.index ["user_id"], name: "index_employee_contacts_on_user_id"
end
create_table "employees", force: :cascade do |t|
t.string "first_name"
t.string "middle"
t.string "last_name"
t.string "sex"
t.string "race"
t.date "birthdate"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "employee_contact_id"
t.index ["user_id"], name: "index_employees_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name:
"index_users_on_reset_password_token", unique: true
end
end
These are my models:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :employees, :dependent => :destroy
end
class Employee < ApplicationRecord
belongs_to :user
has_one :employee_contact, inverse_of: :employee, autosave: true
accepts_nested_attributes_for :employee_contact, allow_destroy: true
end
class EmployeeContact < Employee
belongs_to :employee, inverse_of: :employee_contact
end
My Employee Controller:
class EmployeesController < ApplicationController
before_action :authenticate_user!
def index
#employees = Employee.all
end
def new
#employee = Employee.new
end
def create
#employee = current_user.employees.create(employee_params)
if #employee.save!
redirect_to root_path
else
render :new, status: :unprocessable_entity
end
end
private
def employee_params
params.require(:employee).permit(:first_name, :middle, :last_name,
:sex, :race, :birthdate, employee_contact: [:id, :street, :city,
:state, :zip, :phone_num, :email, :alt_phone_num,
:emergency_contact_first_name, :emergency_contact_last_name,
:emergency_contact_num])
end
end
My View Form:
<%= form_with(model: #employee, local: true) do |form| %>
<h3>Employee Profile Information</h3>
<%= form.label :first_name %><br />
<%= form.text_field :first_name %><br />
<%= form.label :middle %><br />
<%= form.text_field :middle %><br />
<%= form.label :last_name %><br />
<%= form.text_field :last_name %><br />
<%= form.label :sex %><br />
<%= form.text_field :sex %><br />
<%= form.label :race %><br />
<%= form.text_field :race %><br />
<%= form.label :birthdate %><br />
<%= form.date_field :birthdate %><br />
<h3>Employee Contact Information</h3><br />
<%= form.fields_for :employee_contacts do |builder| %>
<%= builder.label :street %><br />
<%= builder.text_area :street %><br />
<%= builder.label :city %><br />
<%= builder.text_area :city %><br />
<%= builder.label :street %><br />
<%= builder.text_area :street %><br />
<%= builder.label :state %><br />
<%= builder.text_area :state %><br />
<%= builder.label :zip %><br />
<%= builder.text_area :zip %><br />
<%= builder.label :phone_num %><br />
<%= builder.text_area :phone_num %><br />
<%= builder.label :alt_phone_num %><br />
<%= builder.text_area :alt_phone_num %><br />
<%= builder.label :email %><br />
<%= builder.text_area :email %><br />
<%= builder.label :emergency_contact_first_name %><br />
<%= builder.text_area :emergency_contact_first_name %><br />
<%= builder.label :emergency_contact_last_name %><br />
<%= builder.text_area :emergency_contact_last_name %><br />
<%= builder.label :emergency_contact_num %><br />
<%= builder.text_area :emergency_contact_num %><br />
<% end %>
<%= form.submit "Add", class: 'btn btn-primary' %><br />
<% end %>
When I get submit the form to create a new employee this is what I get in my console parameters:
Processing by EmployeesController#create as HTML
Parameters:{"utf8"=>"✓","authenticity_token"=>"IgYzybxM8+M8jZ8NJgYKZ+Zhqr07kcV1e0QyWf> uY8hQLyBY844jfOlLNl65F/2RRr4TTW0F1MeSmDzVzBsXOjg==", "employee"=>
{"first_name"=>"Firt Nam", "middle"=>"kk", "last_name"=>"jak", "sex"=>"dfkj", "race"=>"jkadflj", "birthdate"=>"2011-01-01", "employee_contacts"=>{"street"=>"afdjkljadfkl", "city"=>"jadklfjakldfj", "state"=>"fadjlkdf", "zip"=>"32787", "phone_num"=>"567567567", "alt_phone_num"=>"57875875875", "email"=>"dajkjdlkfj#jkj.com", "emergency_contact_first_name"=>"adfjkladjf", "emergency_contact_last_name"=>"adfjkaldf", "emergency_contact_num"=>"784339793"}}, "commit"=>"Add"}
Unpermitted parameter: :employee_contacts
And so it saves the Employee but not anything associated with their contact information. If I run Employee.last in the Rails console I get a nil value for employee_contact_id. If I try and use the Rails Console to look up Employee_Contact.last or Employee_Contact.all I get an 'unable to autoload constant Employee_Contact, expected employee_contact.rb to define it'.
UPDATE
I changed a few things thanks to Anton.
My Employee Contact model now inherits from ApplicationRecord:
class EmployeeContact < ApplicationRecord
belongs_to :employee, inverse_of: :employee_contact
end
I changed the view form in the employee_contact loop from plural to singular:
<%= form.fields_for :employee_contact do |builder| %>
I added a build method in Employee#New
def new
#employee = Employee.new
#employee.build_employee_contact
end
And edited Employee#Create
def create
#employee = current_user.employees.create(employee_params)
if #employee.valid?
redirect_to root_path
else
render :new, status: :unprocessable_entity
end
end
This is now saving an Employee Contact. Here are the results from the console:
#<EmployeeContact id: 1, street: "dafjkafdjl", city: "adjfklajdk", state: "dfjkljalkdfjioad", zip: "dafjadlkfjkajdkl", phone_num: "adf", alt_phone_num: "871274892174", email: "dafnajdklj#jkklda.com", emergency_contact_first_name: "ajdfjalkj", emergency_contact_last_name: "fjadkljdfkl", emergency_contact_num: "11287244", user_id: nil, employee_id: 1, created_at: "2017-10-03 19:01:55", updated_at: "2017-10-03 19:01:55">
Employee id: 1, first_name: "dafad", middle: "dfad", last_name: "dafd", sex: "adfd", race: "dfad", birthdate: "1210-01-01", user_id: 1, created_at: "2017-10-03 19:01:55", updated_at: "2017-10-03 19:01:55", employee_contact_id: nil>
The Employee model is still getting an Employee_Contact_Id: nil value. However, the Employee Contact model is getting the correct Employee_Id attribute.
SOLVED
So I'm going to leave it at with what I have posted in the Update. There is no need for my Employee model to have an Employee_Contact_Id attribute. When I create a new Employee the Contact correctly maps to that Employee currently.
Please set the EmployeeContact to inherit from ApplicationRecord, not Employee.
In the new action build the employee contact for the nested form from the employee.
I would suggest to remove the foreign key from the has_one association.
The employee_id on the employee_contact is enough.

Rails many to many model with select in the view

The logic in the exercise is create a Bill where a Bill have a list of Products with an amount of them.
I have the next 3 models:
Bill
Product
BillItem (This is the intermediate model between Bill and Product for the many to many relationship)
Schema for more clarity:
create_table "bill_items", force: :cascade do |t|
t.integer "amount"
t.integer "product_id"
t.integer "bill_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["bill_id"], name: "index_bill_items_on_bill_id"
t.index ["product_id"], name: "index_bill_items_on_product_id"
end
create_table "bills", force: :cascade do |t|
t.string "user_name"
t.string "dni"
t.date "expiration"
t.float "sub_total"
t.float "grand_total"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "products", force: :cascade do |t|
t.string "name"
t.string "description"
t.float "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
First i have a list of created products in my database.
For my BillController i have a _form.html.erb where i want be capable to create dynamic selects for choose a product and set a amount.
My view is the next:
<%= form_for bill do |f| %>
<div>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
</div>
<div>
<%= f.label :dni %>
<%= f.text_field :dni %>
</div>
<div>
<%= f.label :product %>
<%= f.collection_select :product_ids, Product.all, :id, :name %>
</div>
# Here i should add more selects if the user want to add more products.
<div><%= f.submit %></div>
<% end %>
My problem or my question is: how to "groupe" the ids of the products and the amount of them. And the another question is, i can create the other selects dynamically with JS?
You need to be adding multiple BillItem to your form to account for the amount and the product. This is done through accepts_nested_attributes_for on the model. For example:
class Bill < ActiveRecord::Base
has_many :bill_items
accepts_nested_attributes_for :bill_items
end
Initialize a BillItem on the Bill in your controller:
class BillsController < ActionController::Base
def new
#bill = Bill.new
#bill.bill_items.build
end
end
Then in your form, use the fields_for helper to create sub-forms:
<%= form_for #bill do |f| %>
<div>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
</div>
<div>
<%= f.label :dni %>
<%= f.text_field :dni %>
</div>
<%= f.fields_for :bill_items do |f| %>
<div>
<%= f.label :product %>
<%= f.collection_select :product_id, Product.all, :id, :name %>
</div>
<div>
<%= f.label :amount %>
<%= f.number_field :amount %>
</div>
<% end %>
<%= f.submit %></div>
<% end %>
And yes, you can use javascript to create new nested forms.

Image upload using carrierwave in show page

Using Rails 4 and Ruby 2.2,
I have book as model which should have image upload functionality in the show page of book. So User can create the book first and from show page upload the multiple images for book. I have used carrierwave as gem and have separate model created for Image.
image.rb
class Image < ActiveRecord::Base
belongs_to :book
mount_uploader :avatar, AvatarUploader
end
book.rb
class Book < ActiveRecord::Base
belongs_to :subject, dependent: :destroy
belongs_to :user, dependent: :destroy
has_many :images, dependent: :destroy
end
books/show.html.erb
<%= form_for(Image.new, :html => { :multipart => true }) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
<%= hidden_field_tag "image[book_id]", #book.id %>
</div>
<%= f.fields_for :images do |p| %>
<div class="field">
<%= p.label :avatar %><br>
<%= p.file_field :avatar, :multiple => true, name: "images[avatar]" %>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
schema.rb
create_table "images", force: :cascade do |t|
t.datetime "avatar_updated_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "book_id", limit: 4
t.string "avatar", limit: 255
t.string "name", limit: 255
end
create_table "books", force: :cascade do |t|
t.string "title", limit: 255
t.integer "page_number", limit: 4
t.text "description", limit: 65535
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id", limit: 4
t.integer "subject_id", limit: 4
t.boolean "active", default: false
end
Now I am kind of unable to proceed with this, can someone guide me on this because I am having form in books/show page and I need to show the image on the same page after successful updation of images.(Multiple images can be uploaded)
Thanks in advance
let me know if I need to provide any more information.
You can use the association itself and list all the images which have been uploaded.
<%= form_for(Image.new, :html => { :multipart => true }) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
<%= hidden_field_tag "image[book_id]", #book.id %>
</div>
<%= f.fields_for :images do |p| %>
<div class="field">
<%= p.label :avatar %><br>
<%= p.file_field :avatar, :multiple => true, name: "images[avatar]" %>
</div>
<% end %>
<!-- Listing all the images for a book -->
<% if #book.images.any? %>
<% #book.images.each do |img| %>
<%= image_tag(img.avatar.url) %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

Rails 4 Create record with record.id of join table

Ruby on Rails 4
I am trying to have a form create a record in my Test table. The record needs to have the id(s) from its join table called questions_tests. Do I need to create the records in questions_tests from the form and then create the tests record? How would you do that?
The Models (not sure if I named the join table correct):
class Test < ActiveRecord::Base
has_many :questions_tests
has_many :questions, :through => :questions_tests
end
class Question < ActiveRecord::Base
has_many :questions_tests
has_many :tests, :through => :questions_tests
end
class QuestionTest < ActiveRecord::Base
belongs_to :question
belongs_to :test
end
My schema:
create_table "questions", force: true do |t|
t.string "content"
t.string "question_type"
t.string "category"
t.integer "product_id"
t.boolean "active"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
add_index "questions", ["product_id", "created_at"], name: "index_questions_on_product_id_and_created_at", using: :btree
create_table "questions_tests", id: false, force: true do |t|
t.integer "test_id", null: false
t.integer "question_id", null: false
end
create_table "tests", force: true do |t|
t.string "name"
t.integer "user_id"
t.string "type"
t.string "category"
t.string "description"
end
The form should fill in the Test attributes and somehow have the id(s) from questions_tests. Right now I do not know how to send or create the questions_tests records.
My form, not sure how to have option to select questions and store them to the tests record. Here, :question_id is undefined but I need to store 2 to 200 of them in the test.
<h1>New Test</h1>
<%= form_for #test do |f| %>
<%= f.label :name, "Test Name" %><br>
<%= f.text_field :name, class: "input-lg" %>
<%= f.label :description, "Description" %><br>
<%= f.text_field :description, class: "input-lg" %>
<%= f.label :question_id %><br>
<%= f.select :question_id, Question.all.collect { |p| [ p.content, p.id ] }, class: "input-lg" %>
<%= f.label :category %><br>
<%= f.select :category, [ ["IP Voice Telephony", "ip_voice"], ["IP Video Surveillance", "ip_video_surveillance"], ["IP Video Telephony", "ip_video_telephony"], ["Enterprise Gateways", "enterprise_gateways"], ["Consumer ATAs", "consumer_atas"], ["IP PBX", "ip_pbx"] ], {prompt: "Select Category"}, class: "input-lg" %>
<%= f.label :type %><br>
<%= f.select :type, [ ["Beginner", "beginner"], ["Intermediate", "intermediate"], ["Advanced", "advanced"] ], {prompt: "Select Type"}, class: "input-lg" %>
<br/><br/><br/>
<%= f.submit "Create Test", class: "btn btn-lg btn-primary" %>
<% end %>
You need to look into fields_for.
You'll have a fields_for block in your form
f.fields_for :questions do |question|
question.select(...)
end`
Within this block, you'll have a way to select the questions to add to the test.
There's a gem called cocoon that will help you add a "Add question" link to add more questions.
You'll have to add accepts_nested_attributes_for :questions in your test model. Then Rails will create the QuestionTest itself, you don't need to worry about that.

Associations with simple_form an input field (not checkboxes, selects. or radios)

I was hoping someone could please help me with a simple_form association that I'm trying to do.
What I want to do is to create a simple_form for a music video that that has an association in the form of a has many through. My schema looks like this:
create_table "music_videos", force: true do |t|
t.string "song_title", null: false
t.string "venue", null: false
t.string "location", null: false
t.string "description", null: false
t.string "url_id", null: false
t.integer "user_id", null: false
end
create_table "music_videos_tags", id: false, force: true do |t|
t.integer "music_video_id", null: false
t.integer "tag_id", null: false
end
add_index "music_videos_tags", ["music_video_id"], name:
index_music_videos_tags_on_music_video_id", using: :btree
add_index "music_videos_tags", ["tag_id"], name: "index_music_videos_tags_on_tag_id",
using: :btree
create_table "tags", force: true do |t|
t.string "name", null: false
end
Music Videos has many tags through music_video_taggings vice versa. But I'm confused on how to do accomplish the association with simple_form. I have a new.html.erb with a form like so:
<h1>Submit Your Video</h1>
<%= simple_form_for #music_video url: music_videos_path, method: :post do |f| %>
<%= f.input :song_title %>
<%= f.input :venue %>
<%= f.input :location, label: "City", collection: MusicVideo::CITY %>
<%= f.input :description %>
<%= f.input :url_id, label: "Paste url id ex. 82237472" %>
<%= f.input :name, label: "Tag" %>
<%= f.submit %>
Now I know, I'm supposed to put an association for f.input :name, but I don't want checkboxes, selects, or radios. How can I do this? I thought about creating a form for both #music_videos, and #tags right at the top of the form, but I don't think that will work though.The errors that I keep receiving are that there is an undefined method name. Any ideas? I've been stuck on this for awhile. Some help would greatly be appreciated. Thanks.
Replace
<%= f.input :name, label: "Tag" %>
With
<%= f.simple_fields_for :tags do |p| %>
<%= p.input :name, label: "Tag" %>
<% end %>
Refer to Nested Models in Simple Form for more details.

Resources