I have a Rails 3.2.21 app where I'm adding a simple form/collection_select field in my form. When selecting an object from the dropdown (or leaving it blank) I get the following error:
ActiveRecord::AssociationTypeMismatch at /calls/5
BillFacility(#70179530126460) expected, got String(#70179505820040)
Here's what my models look like:
call.rb
belongs_to :bill_facility
attr_accessible :bill_facility_id
bill_facility.rb
has_many :calls
Here's what my form looks like:
_form.html.erb
<%= f.collection_select(:bill_facility_id, BillFacility.order("facility_name ASC"), :id, :facility_name, {:include_blank => true}, {:class => 'select'}) %>
Here's the migrations I did to add the BillFacility model and add the bill_facility_id to the Call model:
class CreateBillFacilities < ActiveRecord::Migration
def change
create_table :bill_facilities do |t|
t.string :facility_name
t.string :facility_address
t.timestamps
end
end
end
class AddBillFaciltyIdToCalls < ActiveRecord::Migration
def change
add_column :calls, :bill_facility_id, :integer
end
end
If I manually assign the call an id in bill_facility_id I get an unknown to_i method error. If I manually make it nil then select a BillFacilty from the drop down (or leave it blank) I get the mismatch error:
ActiveRecord::AssociationTypeMismatch at /calls/5
BillFacility(#70179530126460) expected, got String(#70179505820040)
I'm sure this is something simple that I'm missing. Anyone have any ideas on what I'm doing wrong here? It's a bit early so my mind is kind of fuzzy so I should probably wait until I'm fully awake but figured I'd ask for some help.
If you have any questions, please let me know.
I think I have this figured out. Definitely not awake enough to be writing code.
I had this in my form before the BillFacility collection_select
<%= f.label :Bill_Facility, "Bill Facility", class: "control-label" %><%= f.check_box :bill_facility, :id => 'bill_facility_checkbox' %>
So I was calling a field named bill_facility that was in my database, but since bill_facility is an associated model, it gave me the mismatch error. So I simple altered the migration to change the check_box to bill_fac and it worked.
Related
I am creating a small app to manage my own online portfolio but I can't solve an issue with update.
The main table of my database is works, then there's the tables authors and clients where I set the fields authorName and clientName as unique. Authors and clients can have multiple works, but a work can only have one of each.
In the form where I create works I have a field for the authorName and another one for clientName: if the author doesn't exist in the authors table it gets created, otherwise the existing one gets linked to the work. Same thing with the client. To achieve this I am using first_or_initialize and it works perfectly. Problems start when I try to use the same method inside the update action. These are my models:
Work Model
class Work < ApplicationRecord
has_one :description
belongs_to :author
belongs_to :client
accepts_nested_attributes_for :client
accepts_nested_attributes_for :author
scope :active, lambda {where(:isActive => true)}
scope :descOrder, lambda {order(:date => :desc)}
scope :cover, lambda {where(:isCover => true)}
end
Author Model
class Author < ApplicationRecord
has_many :works
end
Client Model
class Client < ApplicationRecord
has_many :works
end
Quick edit: the models as you see them are exactly as they are in my app. No code has been removed.
This is the form in my view:
<%= form_for(#work, :url => { :controller => "projects", :action => "update"} ) do |f| %>
<%= f.label("title") %>
<%= f.text_field(:title) %>
<%= f.fields_for(:author) do |author| %>
<%= author.label("author") %>
<%= author.text_field(:authorName) %>
<% end %>
<%= f.fields_for(:client) do |client| %>
<%= client.label("client") %>
<%= client.text_field(:clientName) %>
<% end %>
<%= f.label("date") %>
<%= f.date_field(:date) %>
<%= f.submit("update") %>
<% end %>
And this is how I am handling it in the controller:
def edit
#work = Work.find(params[:id])
if #work.client.nil?
#work.build_client
end
if #work.author.nil?
#work.build_author
end
end
def update
#work = Work.find(params[:id])
#work.client = Client.where(clientName: work_params["client_attributes"]["clientName"]).first_or_initialize
#work.author = Author.where(authorName: work_params["author_attributes"]["authorName"]).first_or_initialize
if #work.update(work_params)
flash[:notice] = "work: #{#work.title} updated successfully."
redirect_to(project_path(#work))
else
redirect_to new_project_path
end
end
private
def work_params
params.require(:work).permit(:title, :date, client_attributes: [:id, :clientName], author_attributes: [:id, :authorName])
end
This is the error that I get:
Started PATCH "/projects/21" for ::1 at 2019-10-14 20:00:27 -0700
Processing by ProjectsController#update as HTML
Parameters: {"authenticity_token"=>"rw3X7VJg8CDnOibniv1jKHTVTGp7pjE4ep6xHpHy0Zp8Xv/0uQd6y5xqq629M2FOOQNoYyOAXH//w5/VoeNEOA==", "work"=>{"title"=>"Progetto1", "author_attributes"=>{"authorName"=>"Autore1", "id"=>"34"}, "client_attributes"=>{"clientName"=>"Cliente4", "id"=>"30"}, "date"=>""}, "commit"=>"update", "id"=>"21"}
Work Load (0.7ms) SELECT `works`.* FROM `works` WHERE `works`.`id` = 21 LIMIT 1
↳ app/controllers/projects_controller.rb:42:in `update'
Client Load (0.6ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`clientName` = 'Cliente4' ORDER BY `clients`.`id` ASC LIMIT 1
↳ app/controllers/projects_controller.rb:44:in `update'
Author Load (0.6ms) SELECT `authors`.* FROM `authors` WHERE `authors`.`authorName` = 'Autore1' ORDER BY `authors`.`id` ASC LIMIT 1
↳ app/controllers/projects_controller.rb:45:in `update'
Completed 404 Not Found in 15ms (ActiveRecord: 1.9ms | Allocations: 3805)
ActiveRecord::RecordNotFound (Couldn't find Client with ID=30 for Work with ID=21):
app/controllers/projects_controller.rb:47:in `update'
Even though those record do exist in the database (with those IDs that you see in the error) and their foreign keys are correctly stored in the works table (I checked in mysql).
What I am expecting to achieve is the same behaviour of the new action (that I described in the beginning of my post).
How can I solve this? Thank you!
Small update: if I change first_or_initialize with first_or_create it does create the author (or client), if not existing, but in the same time it still gives me the same error.
After dozens of tests I eventually came up with a sort of solution - it's not "elegant" and probably it's not the best, but at least it works without interruptions:
def edit
#work = Work.find(params[:id])
if #work.client.nil?
#work.build_client
end
if #work.author.nil?
#work.build_author
end
end
def update
#work = Work.find(params[:id])
#work.client = Client.where(clientName: work_params["client_attributes"]["clientName"]).first_or_create
#work.author = Author.where(authorName: work_params["author_attributes"]["authorName"]).first_or_create
if #work.update(update_params)
flash[:notice] = "work: #{#work.title} updated successfully."
redirect_to(project_path(#work))
else
redirect_to new_project_path
end
end
private
def work_params
params.require(:work).permit(:title, :date, client_attributes: [:id, :clientName], author_attributes: [:id, :authorName])
end
def update_params
params.require(:work).permit(:title, :date)
end
Being that first_or_initialize works smoothly with save method, but it gets stuck - at least in my code - with update, I replaced it with first_or_create.
This time, however, I am using another private method update_params which simply ignores :client_attributes and :authors_attributes.
This results in an Unpermitted parameters: :author_attributes, :client_attributes error, as expected, but at least everything goes through and gets updated.
Honestly I am not quite sure that I totally understood why it's working. But it does.
Anyway, if anyone have a better solution to this problem I am totally open to improve it.
I'm following this guide for multi-checkbox in rails. I am using Rails 3 conventions, so I still have attr_accessible instead of strong parameters. Everything seems to work fine except I get this error:
undefined method `match' for []:Array
userprofile.rb model:
class Userprofile < ActiveRecord::Base
before_save do
self.expertise.gsub!(/[\[\]\"]/, "") if attribute_present?("interest")
end
attr_accessible :interest, :user_id, :country, :state_prov, :city
serialize :interest, Array
userprofiles_helper.rb:
module UserprofilesHelper
def checked(area)
#userprofile.interest.nil? ? false : #userprofile.interest.match(area)
end
end
_form.html.erb:
<h3>Area of Interest</h3>
<%= label_tag 'interest_physics', 'Physics' %>
<%= check_box_tag 'userprofile[interest][]', 'Physics', checked("Physics"), id: 'interest_physics' %>
<%= label_tag 'expertise_maths', 'Maths' %>
<%= check_box_tag 'userprofile[interest][]', 'Maths', checked("Maths"), id: 'interest_maths' %>
If I remove the checked helper method, then the checkbox value does not persist. I've been trying to fix the undefined method 'match' error. Or find an alternate way to keep the correct checkbox value checked when I edit the form.
Any suggestions would help, thank you!
Since Userprofile#interest is an array, it looks like you actually want to use include? in your helper instead of match. So in userprofiles_helper.rb:
def checked?(area)
#userprofile.interest.present? && #userprofile.interest.include?(area)
end
so I have a tricky issue here I'm not sure how to solve.
I have a Provider model that has_many :educational_affiliations
EducationalAffiliation belongs_to :institution & belongs_to
:provider
I have about 9000 universities in my database, so I'm using the handy-dandy rails3-jquery-autocomplete gem to give me type-ahead support. That's all working great - on TOP of that I'm using cocoon to support the nesting of the :educational_affiliations form inside of the provider's edit form.
So here's where the issue comes — This works great for submitting new affiliation records, (I'm using some jquery to set the :institution_id on the :educational_affiliations_attributes object, works great)
BUT when I return to edit this later, of course the :institution_name isn't populated, because it's not part of the :educational_affiliations model, it's in the :institution model.
Here's what I just tried in my :educational_affiliations, which I assume is the right solution:
class EducationalAffiliation < ActiveRecord::Base
attr_accessible :degree, :graduation_year, :honors, :institution_name, :institution_id, :provider_id
belongs_to :institution
belongs_to :provider
# attr_accessor :institution_name
validates :institution_id, :graduation_year, :provider_id, :degree, presence: true
def institution_name
Institution.find(institution_id).name
end
end
(i had it working for saving using the attr_accessor, but I've commented it out for now)
So when I render the edit view with the above, I get a ActiveRecord::RecordNotFound: Couldn't find Institution without an ID error — but when I open a debugger on that statement, the model DOES seem to know the institution_id...so confused why it doesn't pick it up.
Am I just doing this in the worst way possible? I assume there's a dumb solution.. :)
Here's the partial that needs the name populated:
.nested-fields
= f.input :institution_name, url: autocomplete_institution_name_data_path, as: :autocomplete, :input_html => {:id_element => '#provider_educational_affiliations_institution_id'}
= f.input :institution_id, as: :hidden
= f.input :provider_id, as: :hidden, input_html: { value: current_provider.id }
= link_to_remove_association "Remove Degree", f
Instead of the virtual attribute method, try the following to define the attribute:
delegate :name, :name=, :to => :institute, :prefix => true
I have found a lot of posts about this Railscast but all the suggestions haven't helped me.
I have been able to render in the view a nested form field, but only one, not the 3 that I have called out in my controller. When I submit, I get the error: Can't mass-assign protected attributes: clue
Chapter.rb
class Chapter < ActiveRecord::Base
belongs_to :trail
has_many :clues, :dependent => :destroy
accepts_nested_attributes_for :clues
attr_accessible :asset, :assetkind, :description, :gate, :name, :trail, :trail_id, :cover
.
.
.
end
Clue.rb
class Clue < ActiveRecord::Base
attr_accessible :chapter_id, :theclue, :typeof, :chapter
.
.
.
belongs_to :chapter
end
In the railcast it says to use the equivalent of :clues, and this renders 3 fields. But in mine, it didn't render the fields. Instead, I use #chapter.clues and it renders only one.
My form when making a new chapter.
<h1>Add a New Chapter</h1>
<h3>Add To Trail : <%= #trail.title %></h3><br>
<%= form_for [#trail, #trail.chapters.build] do |f| %>
<h6>About the Chapter</h6>
<%= f.label :name, 'Chapter Name' %>
.
.
.
<h6>Progressing the Story</h6>
<%= f.fields_for #chapter.clues do |builder| %>
<p>
<%= builder.label :theclue, "Enter Clue" %>
<%= builder.text_area :theclue, :rows => 2 %>
</p>
<% end %>
.
.
.
<% end %>
My chapters_controller.rb new
class ChaptersController < ApplicationController
def new
#trail = Trail.find(params[:trail_id])
#chapter = Chapter.new
#title = "Chapter"
3.times { #chapter.clues.build }
logger.debug "CHAPTER!!!!!!!!!!!!new: am i in a trail? #{#trail.to_yaml}"
logger.debug "CHAPTER!!!!!!!!!!!!new: am i in a clue? #{#chapter.clues.to_yaml}"
end
My log shows me 3 clues, but the attributes are empty (no :id). Is this a sign of something wrong? So even though my log shows 3 clue objects, my view only shows one.
Thoughts? I have already, thanks to suggestions on stackoverflow, added to chapter.rb
attr_accessible :clues_attributes
and had no luck, same behavior and errors with and without that.
Thanks in advance for your time
I figured it out for myself. Not sure why exactly, I will speculate, someone is welcome to explain it better if I'm off.
The issue was here:
<%= form_for [#trail, #trail.chapters.build] do |f| %>
which I changed to:
<%= form_for #chapter do |f| %>
and then I had to change some things around in my chapters_controller to make the trails objects and capture the ids. But, after I made this change, my 3 clue fields started showing up in the view and my error about mass-assign went away.
I think the chapter I created before was empty and not really generated, only holding information, so trying to hold nested information with the clues form_for was another step of temporary data...Where as creating the object in my controller and then filling it with the form was more substantial....I know really technical...Like I said, I got it working, don't ask me how...but I'm beginning to understand how Rails thinks.
When I submit, I get the error: Can't mass-assign protected attributes: clue
This is telling you that the attribute is protected from mass assignment. Basically, the only way you would be able to set it is through a method in your code, not from user input. (Which get assigned, usually, through update_attributes on the model.)
What you need to do is add :clue to attr_accessible in models/chapter.rb.
You may want to add :clues as well - I think it should actually be giving you the error that :clues is protected. You may run into an issue with :clue_ids. Whatever it says is protected, just put in the attr_accessible method in that model and you should be able to update it from user input.
Hey all,
I'm having a pretty weird problem and am having trouble isolating the cause. I get the feeling its a simple solution, but I was hoping for a nudge in the right direction. I have the following models:
class User < ActiveRecord::Base
has_many :pnotes
class Pnote < ActiveRecord::Base
belongs_to :preport
belongs_to :user
class Preport < ActiveRecord::Base
has_many :pnotes, :dependent=>:destroy
The Pnote portion of my schema looks as so:
create_table "pnotes", :force => true do |t|
t.integer "preport_id"
t.integer "user_id"
t.text "content"
t.datetime "created_at"
t.datetime "updated_at"
end
I'm trying to display all of the Pnotes associate with a given Preport on the show page of the Preport
My Preport Controller has the following code for the show action:
def show
#board = Board.find(params[:board_id])
#preport = #board.preport
#pnotes = #preport.pnotes
#pnote=#preport.pnotes.build
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #preport }
end
end
So now in my show.html.erb in the Preports folder, I am trying to display a list of the Pnotes as such:
<ul>
<% #pnotes.each do |pnote| %>
<li><%= pnote.user.login %><span>-<%=pnote.content %></span></li>
<% end %>
</ul>
"login" is the standard field that came along with the Devise Authentication Gem.
However, this gives me the following error:
undefined method `login' for nil:NilClass
If I change the view to this:
<%= pnote.user%>-<%=pnote.content %>
I get :
#<User:0x106c25888>-Testing
, so it appears that it is identifying the associated user, but unable to grab its attributes.
Any advice would be greatly appreciated! I feel like there is a fairly small oversight going on here, but I am unable to distinguish from exactly where
Thanks!
Unless you're using a very old version of Devise that I'm not aware of, the User model wouldn't have a login attribute.
Try email instead.