ActiveRecord::AssociationTypeMismatch in Controller#create on dropdown select for a Rails self join
Lee -
Your Quote
and Artist
models look OK. Your schema, however, is wrong. It should look like:
create_table "artists", force: :cascade do |t|
t.integer "user_id"
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "quotes", force: :cascade do |t|
t.integer "user_id"
t.integer "speaker_id"
t.integer "topic_id"
t.text "content"
t.string "source"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Note speaker_id
and topic_id
instead of artist_id
.
I'd need to see your stack trace to see what might be wrong with how you have other things set up.
BTW, have you fixed your params whitelist? This is wrong:
def quote_params
params.require(:quote).permit(:content, :source, :topic, :artist_id)
end
Since your params look like:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"7xXgP3T1ZyxVhnr9TtBxeuYSRLBiuX01JSkQ4m4rN9pBS1W0iW6TJtsS7KyvunpCIZFiFltmdEwZGIYqsnxbyw==", "quote"=>{"topic_id"=>"2", "speaker_id"=>"1", "content"=>"asdfadsf", "source"=>"http://fuzz.com"}, "commit"=>"Post"}
It should be:
def quote_params
params.require(:quote).permit(:content, :source, :topic_id, :speaker_id)
end
As a shot in the dark, try changing:
validates :speaker, uniqueness: {scope: :topic}
validates :topic, uniqueness: {scope: :speaker}
To:
validates :speaker_id, uniqueness: {scope: :topic_id}
validates :topic_id, uniqueness: {scope: :speaker_id}
I'll update with explanation if that's the problem.
RAILS || ActiveRecord::AssociationTypeMismatch: Error on new model object
where
always returns an ActiveRecord relation, find
returns a single instance. You can use where
like this for similar effect
@user.pay = Pay.where(years: @user.years).first
however a better way would be
@user.pay = Pay.find_by(years: @user.years)
ActiveRecord::AssociationTypeMismatch error when I run my create method?
Change your form like this (I renamed @category
to @categories
as well):
= simple_form_for @post do |f|
= f.input :title
= f.input :content
= f.input :category_id, collection: @categories, label_method: :name, value_method: :id
= f.submit
Also in controller:
def post_params
params.require(:post).permit(:title, :content, :category_id)
end
Error in you code was associated with the fact, that by default SimpleForm considers collection as an array of strings. So :category
parameter was given a String
value, while it should be Category
.
How do you use a single select dropdown with Rails has_many through association?
Yes! exactly, I had the same problem but I have solved by using own tricks, see the below code
<div class="form-group">
<label>Artist</label>
<select name="quote[artist_ids][]" id="quote_artist_ids" class="form-control">
<% Artist.all.each do |artist| %>
<option value="<%= artist.id %>">
<%= artist.name %>
</option>
<% end %>
</select>
</div>
It's working, without this everything are same like: quote_params
I mean all are the same which before worked for multiple.
Hope to help
Combining elements in select dropdown while maintaining correct id in association
I figured it out. All I had to do is add a array inside the collection block with the first item displayed and the second item as the id. So it should look like this:
collection: Student.all.map{|s| ["#{s.firstname} #{s.lastname}",s.id] }
How do you structure a rails model where two attributes need to share the same association with another model?
I believe you want Quote to look something like:
class Quote < ActiveRecord::Base
belongs_to :speaker, class_name: "Artist"
belongs_to :subject, class_name: "Artist"
belongs_to :user
validates :speaker, uniqueness: {scope: :subject}
validates :subject, uniqueness: {scope: :speaker}
...
end
This assumes:
- A User (probably current_user or something like that) is creating the quote and that the quote belongs to that user.
- An Artist is a distinct notion from User. That is, an Artist is not necessarily a User (a Quote may have David Bowie as a subject, but David Bowie may not be a User of your system (especially given that he has passed away as has Lou Reed)).
This way, both speaker
and subject
are specified as being of the class Artist
.
The uniqueness validations ensure that a speaker
is never a subject
and visa-versa. (You may need to twiddle with the validates
statement as I did not test.)
In your Artist
model, you probably want to do something like:
class Artist < ActiveRecord::Base
has_many :spoken_quotes, class_name: "Quote", foreign_key: :speaker_id
has_many :referencing_quotes, class_name: "Quote", foreign_key: :subject_id
...
end
That way, you could do something like:
Artist.find_by(name: 'David Bowie').spoken_quotes
And get all the Quotes
for which David Bowie is the speaker
.
And, in your User
model, you probably want something like:
class User < ActiveRecord::Base
has_many: :quotes
...
end
So that you can do something like:
current_user.quotes
And get all the quotes the current_user
has created.
Rails: How to pass index object into controller for further sorting?
I think your code will be much clearer and reusable if you don't directly call index() from list_open_process, but instead move the part that populates @quotes to another method or object. For instance:
def index
# do other stuff first?
@quotes = get_quotes
end
def list_open_process
@quotes = return_open_process(get_quotes)
end
def get_quotes
# extracted from the index() method
end
private :get_quotes
Now, the intention is clearer, and you aren't doing any extra steps that index might execute that aren't needed by list_open_process.
As for making it more flexible, depending on size you might consider a case statement that matches a param string like 'quotes' to the method that gets quotes, and so on. Or use a hash of keywords to method references. The point is, you want to make sure that you ONLY execute code when an allowed keyword type is passed, and any other ones get ignored or trigger an error message back to the client.
How to validate the uniqueness on a form instance and not the entire database in Rails?
Multiple occurences of an Artist both as a speaker and a topic, are at the core of your model logic; I don't think there is any uniqueness
to validate at all - neither scoped or conditional. Validation that you want considers only context of single instance of a Quote; I believe it should be a custom one.
validate :topic_cant_be_a_speaker
def topic_cant_be_a_speaker
errors.add(:speaker, "Topic can't be a speaker") if speaker == topic
end
Related Topics
What Does This Mean in Ruby Language
Rails Error Message Displays Key and I Only Want Value
Can't Install Ruby via Rvm, Error Running '_Rvm_Make -J4' on Ubuntu 22.04
Ruby Error After Installing Heroku Toolbelt
How to Mock Super in Ruby Using Rspec
Are There More Elegant Ways to Prevent Negative Numbers in Ruby
Ruby Equivalent for Python's For/Else
Interface Builder Not Seeing Outlets with MACruby
How to Start Ruby 1.9 Without Rubygems
Get Instance Variable Name from Itself in Ruby
Typeerror: Object Doesn't Support This Property or Method
How to Capture a Part of a Screen Using Ruby on Windows
Rails 7 Signup Form Doesn't Show Error Messages
Rails Cancan and State MAChine - Authorizing States
Differencebetween Unicorn and Unicorn_Rails
How to Use Headless Chrome with Capybara and Selenium