undefined method `commentable' for # ActiveRecord::Associations::CollectionProxy [] (accesing commentable id and type via polymorphic association)
As the error message says, you can't call commentable
on @question.comments
- an association. Pass an array to the form_for
method with the commentable (Question
) object and the comment object. You don't need to set any hidden fields.
<%= form_for [@question, @comment] do |f| %>
<div><%= f.label :content %></div>
<div><%= f.text_area :content %></div>
<div><%= f.submit 'Post' %></div>
<% end %>
Replace content
with the field where you're storing the comment's content.
This should generate a form
tag with an action
attribute of /questions/1/comments
which upon submission is processed by CommentsController#create
.
class CommentsController < ApplicationController
before_action :set_commentable
def create
@comment = @commentable.comments.new(comment_params)
if @comment.save
redirect_to @commentable, notice: 'Comment created'
else
render :new
end
end
private
def set_commentable
# e.g. request.path => '/questions/1/comments'
resource, id = request.path.split('/')[1, 2] # ['questions', '1']
@commentable = resource.singularize.classify.constantize.find(id)
end
def comment_params
params.require(:comment).permit(:content)
end
end
In the set_commentable
method, the commentable type and its id are detected from the request path. Since resource
is 'questions'
, resource.singularize.classify.constantize
returns the Question
model. The commentable object is then found using the find
method. The CommentsController#create
method creates the comment and redirects to the commentable object which is the question show page (/questions/:id
). If there's an error, it renders the new
view (you have to create views/comments/new.html.erb
to render the form with errors).
undefined method `keys' for # ActiveRecord::Associations::CollectionProxy []
Rename attributes
as that's what is causing you issues
if you have a has_many called attributes, you can’t access to your
object attributes anymore; only the associated objects Original Rails
Wiki - additional words
Relevant link:
http://reservedwords.herokuapp.com/words/attributes
Rails 3 HABTM yields ActiveRecord::Associations::CollectionProxy objects
Having a hard time trying to find the error here.. But maybe some of these will help you:
I think you are missing the multiple field index:
add_index : volunteer_circles_users, [:volunteer_circles_id, :user_id]
add_index : volunteer_circles_users, [:user_id, :volunteer_circles_id]
And the create_join_table creates it in alphabetical order, so it would be user_volunteer_circles instead. So, maybe you could need to do something like:
class VolunteerCircle < ActiveRecord::Base
has_and_belongs_to_many :users, :join_table => : volunteer_circles_users
end
Hope it helps..
Sort order for ActiveRecord::Associations::CollectionProxy in table rails
I would add a class method on the Room
model in order to return for a given collection the number of free rooms and reserved rooms:
class Room < ApplicationRecord
belongs_to :hotel, optional: true
accepts_nested_attributes_for :hotel
def self.reserved_count
where(reserved: true).count
end
def self.free_count
where(reserved: false).count
end
end
Once you have implemented, you can call it from the relationship declared in Hotel
model:
class Hotel < ApplicationRecord
has_many :rooms, dependent: :destroy
accepts_nested_attributes_for :rooms
def reserved_rooms
rooms.reserved_count
end
def free_rooms
rooms.free_count
end
end
Your view will look finally like this:
<table>
<tr>
<th>Name</th>
<th>Rooms count</th>
<th>Rooms status: in reserved || free</th>
</tr>
<% @hotels.each do |hotel| %>
<tr>
<td><%= hotel.name %></td>
<td><%= hotel.rooms_count %></td>
<td><%= "#{hotel.reserved_rooms} || #{hotel.free_rooms}" %></td>
<td ><%= link_to 'Show', hotel_path(hotel) %></td>
<td><%= link_to 'Destroy', hotel, method: :delete, data: { confirm: 'Are you sure?' } %>
</tr>
<% end %>
</table>
Sorting the Hotels in your controller
In your controller make sure that you eager load Rooms
for Hotel
:
@hotels = Hotel.includes(:rooms).sort_by { |h| h.free_rooms.to_i }.reverse
You could eventually implement it as Hotel.includes(:rooms).sort_by(&:free_rooms).reverse
.
In this way you won't need any join or helper.
Regarding your comment, free_rooms
is implemented as an instance method (e.g. Hotel.first.free_rooms
), so it will not be available for an ActiveRecord_Relation
(e.g. Hotel.all.free_rooms
)
Rails loop through ActiveRecord::Associations:CollectionProxy
You can do this completely in SQL/ActiveRecord. The query you want to run ultimately is
SELECT article_id, min(date), sum(views)
FROM daily_value_metrics -- Or whatever your table is called
GROUP BY article_id
You can run this with ActiveRecord with the following:
table = DailyValueMetric.arel_table
results = DailyValueMetric.select(table[:article_id],
table[:date].minimum.as('date'),
table[:views].sum.as('views')).group(:article_id).to_a
# Calling to_a so I can call first for the example
results.first.date #=> date
results.first.views #=> views
results.first.article_id #=> Id
The records will look like
[#<DailyViewMetric id: nil, article_id: 1089536>, ...]
Because the SQL query does not return an id column in the result set. This is because of the way that ActiveRecord::Base#inspect
shows the columns defined on the table, and not the returned values outside of the table columns. Views and Date will not necessarily be shown, unless there is a column with the same name, but if you call those attributes on the model instance, you will be able to get the value
Access attributes in ActiveRecord::Associations::CollectionProxy
I am trying to write a custom function that will throw an error if the amount of associated objects are >=4
You are overcomplicating things. If you just want to count the number of records in a collection then you can simply do animal.animal_images.size. So your model will look like this:
class Animal < ActiveRecord::Base
has_many :animal_images
validate :max_num_of_images
def max_num_of_images
errors.add(:base, "Max of 3 images allowed") if self.animal_images.size >= 4
end
end
Related Topics
How to Install Nokogiri Ruby Gem with Mkmf.Log Saying Libiconv Not Found
How to Get a Date from a Week Number
How to Get the Latest Record from Each Group in Activerecord
How to Avoid Putting the Magic Encoding Comment on Top of Every Utf-8 File in Ruby 1.9
In Ruby What Does "=>" Mean and How Does It Work
Iconv Deprecation Warning with Ruby 1.9.3
How to Switch to an Older Version of Rails
Logging All Method Calls in a Rails App
Writing Over Previously Output Lines in the Command Prompt with Ruby
Ruby - Determine If a Number Is a Prime
Why Doesn't Rails' "Errors.Full_Messages" Replace Attribute and Message Variables
How to Determine the Md5 Digest of a Given Asset in the Rails Asset Pipeline