Rails "Undefined Method for Activerecord_Associations_Collectionproxy"

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



Leave a reply



Submit