Can't save data from collection_select helper to model - ruby-on-rails

I'm trying to save an organization to a contact model via a form using a collection_select helper but it's not saving the data to a model. I can't seem to understand why.
I am using Rails 5.1.4
Here are my contact.rb model:
class Contact < ApplicationRecord
belongs_to :organization
has_many :deals
end
Here is my organization.rb model:
class Organization < ApplicationRecord
has_many :deals, through: :contacts
has_many :contacts, dependent: :destroy
end
Here is my schema.rb:
create_table "contacts", force: :cascade do |t|
t.string "contact_name"
t.integer "organization_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["organization_id"], name:
"index_contacts_on_organization_id"
end
create_table "organizations", force: :cascade do |t|
t.string "org_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Here is my contacts_controller.rb:
def new
#contact = Contact.new
end
def edit
#contact = Contact.find(params[:id])
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to #contact
else
render 'new'
end
end
private
def contact_params
params.require(:contact).permit(:contact_name, :organization_id,
organizations_attributes: [:org_name,
:id])
end
Here is my new.html.erb file:
<h1>New Contact</h1>
<%= form_with scope: :contact, url: contacts_path, local: true do |form| %>
<p>
<%= form.label :contact_name %><br>
<%= form.text_field :contact_name %>
</p>
<p>
<%= form.label :organization %><br>
<%= form.collection_select(:organization_id, Organization.all, :id, :org_name) %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
<hr>
Edit: I added params for my controller and schema.

In organization.rb model:
class Organization < ApplicationRecord
has_many :deals, through: :contacts
has_many :contacts, dependent: :destroy
def org_name
"#{name}"
end
end
in your new.html.erb file:
<%= form.fields_for :organizations do |o| %>
<%= o.collection_select(:organization_id, Organization.all,
:id, :org_name,
{:prompt => 'Please select the organization'}) %>

Related

collection_select content is not showing

I'm currently trying to display the organization which a content identifies themselves with via a collection_select form.
The issue is that after creating a new contact and choosing an organization. The organization doesn't display.
I have tried searching the web for an answer so far but nothing has helped. I have also tried everything that I can think of is the issue with my code.
Here are my models:
class Contact < ApplicationRecord
has_many :contact_orgs
has_many :organizations, through: :contact_orgs
accepts_nested_attributes_for :organizations
end
class Organization < ApplicationRecord
has_many :contact_orgs
has_many :contacts, through: :contact_orgs
end
class ContactOrg < ApplicationRecord
belongs_to :contact
belongs_to :organization
accepts_nested_attributes_for :organization
end
Here is my schema.rb:
create_table "contact_orgs", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "contact_id"
t.integer "organization_id"
t.index ["contact_id"], name: "index_contact_orgs_on_contact_id"
t.index ["organization_id"], name: "index_contact_orgs_on_organization_id"
end
create_table "contacts", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "organizations", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "industry"
end
Here is my contact_controller.rb:
private
def contact_params
params.require(:contact).permit(:first_name, :last_name,
organizations_attributes: [:name, :industry])
end
def new
#contact = Contact.new
end
def show
#contact = Contact.find(params[:id])
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to #contact
else
render 'new'
end
end
Here is my contact/new.html.erb:
<%= form_with scope: :contact, url: contact_path, local: true do |form| %>
<p>
<%= form.label :first_name %><br>
<%= form.text_field :first_name %>
</p>
<p>
<%= form.label :last_name %><br>
<%= form.text_field :last_name %>
</p>
<p>
<%= form.label :organization_id, "Organization:" %><br>
<%= form.collection_select :organization_id, Organization.order(:name), :id, :name, {}, {multiple: true} %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Here is my contact/show.html.erb:
<p>
<strong>First name:</strong>
<%= #contact.first_name %>
</p>
<p>
<strong>Last Name:</strong>
<%= #contact.last_name %>
</p>
<hr>
<p>
<strong>Organizations:</strong>
<ul>
<% #contact.organizations.each do |organization| %>
<li><%= organization.name %></li>
<% end %>
</ul>
</p>
Here is what my Rails Server is saying when I refresh my localhost:3000/contact/2 page.
Here is what is in my Rails Console:
2.4.1 :001 > Contact.find(2).organizations
Contact Load (0.2ms) SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Organization Load (0.2ms) SELECT "organizations".* FROM "organizations" INNER JOIN "contact_orgs" ON "organizations"."id" = "contact_orgs"."organization_id" WHERE "contact_orgs"."contact_id" = ? LIMIT ? [["contact_id", 2], ["LIMIT", 11]]=> #<ActiveRecord::Associations::CollectionProxy []>
Here is my routes.rb file:
Rails.application.routes.draw do
get 'welcome/index'
resources :contacts, :organizations
root 'welcome#index'
end
Thank you ahead of time :)
Edit:
Added Contacts#Show method and Contact.find(2).organization via Rails c command.
Added routes.rb
Since you’re using a joins table (ContactOrg) you really are trying to create a new ContactOrg record when you create a Contact, not assign it to Organization, which is how your code reads.
EDIT
While my first statement above still has a (little) bit of merit (you are in fact creating a joins record), you can definitely let rails help you out and you were pretty close in your original answer. Here's code only where there are updates, I tried to highlight changes.
app/models/contact.rb
class Contact < ApplicationRecord
has_many :contact_orgs
has_many :organizations, through: :contact_orgs
accepts_nested_attributes_for :organizations # you were correct here
end
app/views/contact/new.html.erb
<%= form_with model: :contact, local: true do |form| %>
# use :model here so you can ultimately use this form for both new and edit.
# The model method will infer the correct path
... contact fields here as you have them ...
<p>
<%= form.collection_select :organization_ids, Organization.order(:name), :id, :name, {}, {multiple: true} %>
# the attribute for organization_id should be plural because you're accepting multiple
<p>
<p>
<%= form.submit %>
</p>
<% end %>
app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
... new, show, and create as you have them ...
private # private methods should go after all public methods
def contact_params
params.require(:contact).permit(:first_name, :last_name, organization_ids: [])
# again, the attribute you're passing in is called organization_ids, and you give it an empty array
end
end
Your contract_controller do not initialize #contact used in show.html.erb because there isn't any show method does it that.
Try to add in contact_controller
def show
#contact = Contact.find(param[:id])
end
PS: when you call show method be sure to pass to it a contact.id
I hope this help you.
There are two problems:
You are not able to save the organizations to your contract.
You can check in your rails c by Contact.find(2).organizations.
We never use to write new and create in the private method.
Your private method should not contain any of the curd.
In your app/controllers/contacts_controller.rb
private
def contact_params
params.require(:contact).permit(
:first_name,
:last_name,
organizations_attributes: [
:name,
:industry
]
)
end
In your app/views/contact/new.html.erb
<%= form_with scope: :contact, url: contact_index_path, local: true do |form| %>
<p>
<%= form.label :first_name %><br>
<%= form.text_field :first_name %>
</p>
<p>
<%= form.label :last_name %><br>
<%= form.text_field :last_name %>
</p>
<p>
<%= form.fields_for :organizations do |o| %>
<%= o.label :organization %><br>
<%= o.collection_select(:organization_id, Organization.all,
:id, :org_name,
{:prompt => 'Please select the organization'}) %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>

Issue Adding Category to Article in Rails

I have an issue adding Categories to article in my simple form.
The categories are showing up in the simple_form_for but the category_id is not attributed to the article when creating it ! (params ?)
Tx for your help !
I have created two models
class Category < ApplicationRecord
has_many :articles
end
class Article < ApplicationRecord
belongs_to :category
has_attachments :photos, maximum: 2
end
and a foreign key between them
create_table "articles", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "card_summary"
t.text "summary"
t.integer "category_id"
t.index ["category_id"], name: "index_articles_on_category_id", using: :btree
end
The Articles controller to create an article
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to article_path(#article)
else
render :new
end
end
private
def article_params
params.require(:article).permit(:title, :card_summary, :summary, :body, photos: [])
end
and the simple_form_for where I used f.association (which shows correctly the different categories)
<%= simple_form_for #article do |f| %>
<%= f.input :title %>
<%= f.input :card_summary %>
<%= f.input :summary %>
<%= f.input :photos, as: :attachinary %>
<%= f.input :body %>
<%= f.association :category %>
<%= f.submit "Soumettre un article", class: "btn btn-primary" %>
<% end %>
I think my db is ok because I can attribute a category to an article with the console but I m stuck in this form. Any help would be much appreciated. Thx Edouard
EDIT
Here is my migration. Anything wrong?
class AddCategoryReferenceToArticles < ActiveRecord::Migration[5.0]
def change
add_reference :articles, :category, foreign_key: true, index: true
end
end
Adding category_id in article_params should solve the issue
def article_params
params.require(:article).permit(:title, :card_summary, :summary, :category_id, photos: [])
end

Can't save my data into sqlite database

I am trying to implement a Parking Permit application page using ROR. I couldn't get my data saved into the database. The permit database is associated with the user also. The program won't save the data and execute the else statement. There is no error generated, i think i have missed something but i don't know the exact problem. Any help is appreciated!
Permit_controller.rb
class PermitsController < ApplicationController
before_action :set_permit, only: [:show, :destroy]
def index
#permits = Permit.all
end
def new
#permits = Permit.new
end
def create
#permits = Permit.new(permit_params)
if #permits.save
redirect_to root_path
else
redirect_to contact_path
end
end
def destroy
end
def show
#permits = Permit.find(params[:id])
end
private
# Use callbacks to share common setup or constraints between actions.
def set_permit
#permits = Permit.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def permit_params
params.require(:permit).permit(:vehicle_type, :name, :studentid, :department, :carplate,:permitstart, :permitend)
end
end
Permit.rb
class Permit < ApplicationRecord
belongs_to :user
end
Create_permit.rb
class CreatePermits < ActiveRecord::Migration[5.0]
def change
create_table :permits do |t|
t.string :vehicle_type
t.string :name
t.string :studentid
t.string :department
t.string :carplate
t.date :permitstart
t.date :permitend
t.references :user, foreign_key: true
t.timestamps
end
add_foreign_key :permits, :user
add_index :permits, [:user_id, :created_at]
end
end
User.rb
class User < ApplicationRecord
has_secure_password
has_many :permits
end
#book pg 264 Validation
permit/new.html.erb
<% provide(:title, 'New Permit') %>
<h1>Permit Application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits) do |f| %>
<%= f.label :"Vehicle" %>
<%= f.text_field :vehicle_type, class: 'form-control' %>
<%= f.label :"License Plate" %>
<%= f.text_field :carplate, class: 'form-control' %>
<%= f.label :"Student ID" %>
<%= f.text_field :studentid, class: 'form-control' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :"Department of applicant" %>
<%= f.text_field :department, class: 'form-control' %>
<%= f.label :permit_start %>
<%= f.date_select :permitstart, class: 'form-control' %>
<%= f.label :permit_end %>
<%= f.date_select :permitend, class: 'form-control' %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
schema.rb
ActiveRecord::Schema.define(version: 20160921071908) do
create_table "permits", force: :cascade do |t|
t.string "vehicle_type"
t.string "name"
t.string "studentid"
t.string "department"
t.string "carplate"
t.date "permitstart"
t.date "permitend"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_permits_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.integer "user_type"
end
end
check with this #permits.save!.
it shows the exact error.
module ApplicationHelper
#for current user to use through out the app
def current_user
#current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id]) # Use find_by_id to get nil instead of an error if user doesn't exist
end
end
and
def create
#permits = Permit.new(permit_params)
#permits.user = current_user
if #permits.save
redirect_to root_path
else
redirect_to contact_path
end
end
test it
Or you can just say that a permit has a single user and avoid the confusion.
#models/permit.rb
class Permit < ApplicationRecord
has_one :user
end
#controllers/permit_controller.rb
def create
#user = User.find(session[:user_id]) #use your session variable
#permits = Permit.new(permit_params)
if #permits.save
#user.permits << #permits
redirect_to root_path
else
redirect_to contact_path
end
end
It will save permits for the logged in user.

Nested form fields not showing in polymorphic association

Hi I have a polymorphic association with for a Document model for storing document uploads. I'm trying to submit the document attributes as a nested attribute via the associated model.
However, when I load the form, the nested field does not show. What am I missing?
Schema:
create_table "documents", force: :cascade do |t|
t.json "links"
t.integer "linkable_id"
t.string "linkable_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "documents", ["linkable_type", "linkable_id"], name: "index_documents_on_linkable_type_and_linkable_id", using: :btree
Models:
class Document < ActiveRecord::Base
belongs_to :linkable, polymorphic: true
belongs_to :user
belongs_to :company
mount_uploaders :links, DocUploader
end
class CustomerPlan < ActiveRecord::Base
has_many :documents, as: :linkable
accepts_nested_attributes_for :documents
end
Controller:
class CustomerPlanController < ApplicationController
def new
#customer_plan = current_company.customer_plans.build
end
def create
#customer_plan = current_company.customer_plans.build(customer_plan_params)
if #customer_plan.save
redirect_to #customer_plan, notice: 'Customer plan was successfully created.'
else
render :new
end
end
private
def cusomter_plan_params
params.require(:cusomter_plan_params).permit(:date, :name, :plan_type,
documents_attributes: [:id, links: []])
end
end
Form:
<%= simple_nested_form_for #stock_plan, :html => { :multipart => true } do |f| %>
<%= f.error_notification %>
<%= f.input :date %>
<%= f.input :name %>
<%= f.input :plan_type %>
<%= f.simple_fields_for :documents do |d| %>
<p><b>Upload here:</b></p>
<%= d.file_field :links, multiple: true %>
<br>
<% end %>
<%= f.button :submit%>
<% end %>

Can't get 'has_and_belongs_to_many' to work

Made a previous post about this but after a lot of testing and changing it's outdated.
I'm trying to tie users and activities together.(One user can have several activities. An activity can have several users). I'ts pretty much a multi-user agenda thing.
Whenever i create a new activity i can select users by checkbox which will be doing the activity.
I can't get it to work though; The users won't show up in my activity show. Printing #activity.users in my show results in #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_User:0x43d2158> but looping it, or checking my activities.js shows nothing(The activities.js shows "users":[] in the activity. So I'm pretty certain they're not associated properly.
Here's some code:
The activities.js index method
def index
#activities = Activity.all
respond_to do |format|
format.html
format.js {render_json #activities.to_json(:include => [:pictogram ,:users]) }
end
end
The activities' form(Loops all users)
<%= form_for(#activity) do |f| %>
<% if #activity.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#activity.errors.count, "error") %> prohibited this activity from being saved:</h2>
<ul>
<% #activity.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :start_date %><br>
<%= f.date_select :start_date %>
</div>
<div class="field">
<%= f.label :end_date %><br>
<%= f.date_select :end_date %>
</div>
<div class="users">
<% for user in User.all %>
<label class="activity">
<%= check_box_tag "activity[user_ids][]", user.id %>
<%= user.name %>
</label>
<% end %>
</div>
<div class="pictograms">
<% for p in Pictogram.all %>
<% #f.fields_for :pictograms do |x| %>
<%= p %>
<% #end %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The schema.rb
ActiveRecord::Schema.define(version: 20130911095113) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "activities", force: true do |t|
t.string "title"
t.date "start_date"
t.date "end_date"
t.integer "pictogram_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "activities", ["pictogram_id"], name: "index_activities_on_pictogram_id", using: :btree
create_table "activities_users", id: false, force: true do |t|
t.integer "activity_id"
t.integer "user_id"
end
add_index "activities_users", ["activity_id"], name: "index_activities_users_on_activity_id", using: :btree
add_index "activities_users", ["user_id"], name: "index_activities_users_on_user_id", using: :btree
create_table "pictograms", force: true do |t|
t.string "title"
t.string "url"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.string "name"
t.text "avatar"
t.date "birthdate"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Activity.rb
class Activity < ActiveRecord::Base
belongs_to :pictogram
has_and_belongs_to_many :users
accepts_nested_attributes_for :pictogram, allow_destroy: false
accepts_nested_attributes_for :users, allow_destroy: false
end
User.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :activities
validates_presence_of :name, :on => :create
validates_presence_of :birthdate, :on => :create
accepts_nested_attributes_for :activities, allow_destroy: false
end
And the activity params from my activities controller
def activity_params
params.require(:activity).permit(:title,
:start_date,
:end_date,
:users,
:pictogram)
end
Try sth like this:
class Activity < ActiveRecord::Base
belongs_to :pictogram
has_and_belongs_to_many :users
accepts_nested_attributes_for :pictogram, allow_destroy: false
def user_ids=(values)
self.users << User.find(values)
end
end
#controller
def activity_params
params.require(:activity).permit(:title,
:start_date,
:end_date,
{:user_ids =>[]},
:pictogram)
end
I suggest you try some minimalist debugging first,
User.create!(...) # create a valid user record
Activity.create!(...) # same as above
User.all.first.activities << Activity.all.first
User.all.first.activities.any?
See if this works, also keep an eye on your join_table and check that actual records are being persisted. Your schema looks good as well.
I think, none of them read about the strong_parameters with nested attributes :
You can easily define :users_attributes in permit parameters for nested_attributes.
activities controller :
def activity_params
params.require(:activity).permit(:title,
:start_date,
:end_date,
users_attributes: [:id])
end
This is the ideal way to do this. Thanks

Resources