Link_To In Ruby on Rails Is Giving Me Trouble - ruby-on-rails

I'm having trouble with using link_to in Ruby on Rails. I'm making a blog like application which displays a feed of all user posts and allows users to click posts to view/edit them.
This is my _feed partial, which is used to render all the posts of a user.
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3, false).each do |feeds| %>
<div class="row">
<% feeds.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= link_to render feed , edit_post_path(feed) %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>
The line <%= link_to render feed , edit_post_path(feed) %> is what is throwing errors. I'm just not 100% certain how to write a link_to which also renders the feed. I've tried a lot of variations and nothing works. The error I get as it is currently written is: undefined method `keys' for "/posts/160/edit":String
This is my Posts controller, which I wrote after this error occurred in an attempt to fix it. I'm not sure if any of this is even necessary:
class PostsController < ApplicationController
before_action :find_note, only: [:show, :edit]
def edit
end
def show
end
private
def find_note
#post = Post.find(params[:id])
end
I'm sure my problem is super basic but I'm having trouble figuring out how to solve it. Any help is appreciated!

Use block to render a partial inside of a link:
<%= link_to edit_post_path(feed) do %>
<%= render feed %>
<% end %>

Related

Rails doesn't send object as a param error

I've got a controller that handles articles, and recently implemented the edit and create action that way:
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render :edit, status: :unprocessable_entity
end
end
The error occours when I try to edit an article showing the message: screenshot
I'm using a form partial to load the layout this way:
<%= render "form", article: #article %>
After trying to save an new article the edit action works properly and the body error message doesn't shows if trying to save without the requirements. What should I do so solve this problem?
Thanks in advance.
There is a better way altogether to handle rendering errors - just access the object wrapped by the form builder:
<%= form_with(model: article) do |form| %>
<% if form.object.errors.any? %>
<ul>
<% form.object.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
<% end %>
# ...
<% end %>
This lets you DRY out the rendering of errors messages without having to know the name of variable which corresponds to the model instance wrapped by the form.
However you also have a classic nil error - #article is most likely nil. And this isn't an issue we can actually help you with since it cannot be reproduced if we take the code in the question at face value. Like often with stackoverflow the actual problem it lurking somewhere outside of picture.
The debug this code you need to ensure that the code you think is running is actually running and set a series of breakpoints to verify that it is indeed being set and is being passed correctly all the way to the view.
I see that you change article to #article in edit.html.erb. Because article does not exist. article exists when you render "form", article: #article use in _form.html.erb
<% #article.erors.full_messages_for(:title).each do |message|
<div><%= message %></div>
<% end %>
But i think you don't show errors in edit.html.erb
In edit.html.erb file
<%= render "form", article: #article %>
In _form.html.erb
<%= form_with(model: article) do |form| %>
<% if article.errors.any? %>
<ul>
<% article.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
<% end %>
<div>
<%= form.label :title, class: "form-control" %>
<%= form.text_field :title %>
</div>
<div>
<%= form.submit, class: "btn btn-primary" %>
</div>
<% end %>
P/S: That's my opinion, if anyone has any ideas, please leave a comment. I thank you very much

Acts_As_Votable Gem Automatically Liking Everything

I'm using the acts_as_votable gem to like and unlike "Deals" in my Ruby on Rails project. My user is set to act_as_voter and my deal is set to acts_as_votable, but for some reason everything is set to like as soon as a new user is created, and they can't unlike the deal. For some reason my list of deals all have an unlike button and it doesn't actually do anything but refresh the page. Here's some of my code.
app/views/catalog/index.html.erb
<ul class="deals_list">
<% #deals.each do |deal| %>
<li>
<div>
...
<div class="favorite">
<% if account_signed_in? and current_account.accountable_type == "Personnel" %>
<%= image_tag("dark-favorite.png") %>
<% if deal.liked_by current_account %>
<%= link_to unlike_deal_path(deal), method: :put do %>
Unlike
<% end %>
<% else %>
<%= link_to like_deal_path(deal), method: :put do %>
Like
<% end %>
<% end %>
<% end %>
</div>
</li>
<% end %>
</ul>
app/controllers/deals_controller.rb
def like
#deal = Deal.find(params[:id])
#deal.liked_by current_account
redirect_back(fallback_location: catalog_index_url)
end
def unlike
#deal = Deal.find(params[:id])
#deal.unliked_by current_account
redirect_back(fallback_location: catalog_index_url)
end
config/routes.rb
resources :deals do
member do
put 'like', to: "deals#like"
put 'unlike', to: "deals#unlike"
end
end
Be sure and read the entire Readme because you're using the library wrong.
To check if a voter has voted on a model, you can use voted_for?. You can check how the voter voted by using voted_as_when_voted_for.
I zeroed in on your problem because I was expecting to see a "?" after the deal.liked_by call, which would indicate a boolean result (by convention, not always the case).
So use this instead:
<% if current_account.voted_for? deal %>

Rails 4 retrieve nested attributes for display in an index.html.erb

Just looking to find out how to retrieve nested images for display on my front page. I have no problems with a standard model but have been unable to find how to bring has_many nested attribute through. All my nested Forms work fine just have neglected the front end.
eg. product has nested product_images. This doesn't look like a clever way of doing it as the last five images uploaded wont necessarily be related to the last five products added.
Could someone please share an example.
cheers
app/controller/home_controller.rb
class HomeController < ApplicationController
def index
#products = Product.last(5)
#product_images = ProductImage.last(5)
end
end
app/views/home/index.html.erb
<% #products.each do |pd| %>
<div><%= pd.product_name %>
<% end %>
<% #product_images.each do |pd| %>
<%= image_tag (pd.product_image(:medium)) %>
<% end %>
</div>
You can try this:
app/controller/home_controller.rb
class HomeController < ApplicationController
def index
#products = Product.last(5)
#product_ids = #products.collect(:id)
#product_images = ProductImage.where(:id => #product_ids).last(5)
end
end
app/views/home/index.html.erb
<% #products.each do |pd| %>
<div><%= pd.product_name %>
<% end %>
<% #product_images.each do |pd| %>
<%= image_tag (pd.product_image(:medium)) %>
<% end %>

Using partial with paper trail

I'm trying to put some code in a partial from my show page in /events. The code works fine when I use it in my show page, but when i extract it to a partial I'm getting a No Method Error
undefined method `event' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_PaperTrail_Version:0x007f4368823a68>
versions/_version.html.erb
<% cache version do %>
<div class="feed-item">
<h4>
<%= link_to version.item.name, version.item %>
<small>
<%= version.event + "d" %> by <%= link_to User.find(version.whodunnit).username, User.find(version.whodunnit) %>
</small>
</h4>
<ul class="list-unstyled">
<% version.changeset.each do |data| %>
<li>
<strong><%= data[0].capitalize %>:</strong>
<% if data[1][0].present? %><p class="red">- <%= data[1][0] %></p><% end %>
<p class="green">+ <%= data[1][1] %></p>
</li>
<% end %>
</ul>
</div>
<% end %>
show.html.erb
<%= render :partial => '/versions/version', :object => #versions %>
events controller
def show
#versions = #event.versions
end
events model
has_paper_trail
Any idea how i could put my code in a partial instead of having it inside my show view? Thanks.
EDIT:
I still get a No Method Error
undefined method `item' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_PaperTrail_Version:0x007f43688ee1a0>
events_controller.rb
before_action :set_event, only: [:show, :update, :destroy]
def set_event
#event = Event.find(params[:id])
end
Do you have defined the #eventvariable in the eventscontroller?
The #event.versions method has to be called on an actual event object.
For example
def show
#event = Event.find(1)
#versions = #event.versions
end

Rendering a partial in rails. Specifying the partial for a resource gives an error, but not specifying a partial works fine. What gives?

I've got this working now quite accidentally, but I don't understand what causes it to break when I explicitly specify what partials are to be used for rendering the resource/s. Can anyone explain it?
The index template for my Posts controller contained the following line, which was giving me an error:
<%= render partial: 'posts', collection: #posts %>
The error (in my browser) said:
NoMethodError in Posts#index
Showing /Users/applebum/Sites/rails_projects/eventful2/app/views/posts/_posts.html.erb where line #1 raised:
undefined method `any?' for #<Post:0x000001064b21f0>
Extracted source (around line #1):
1: <% if posts.any? %>
2: <div id="posts">
3: <% posts.each do |post| %>
4: <%= render partial: "posts/post", locals: { post: post } %>
Changing the problem line to
<%= render #posts %>
made the error disappear and the posts appear (displayed nicely in markup from the appropriate partials) as I had wanted and expected them to.
Here's my _posts.html.erb partial:
<% if posts.any? %>
<div id="posts">
<% posts.each do |post| %>
<%= render partial: "posts/post", locals: { post: post } %>
<% # render :partial => "comments/comments", :collection => post.comments %>
<% end %>
</div>
<% end %>
And the _post.html.erb partial it's referring to, if that matters:
<div class="post" id="post_<%= "#{post.id}" %>">
<div class="post_inner">
<%= link_to avatar_for(post.user, size: "small"), post.user.profile %>
<div class="post_body">
<div class="user-tools">
<% if can? :destroy, post %>
<%= link_to '<i class="fi-x"></i>'.html_safe, post, :method => :delete, remote: true, :class => "delete", :confirm => "Are you sure you want to delete this post?", :title => post.content %>
<% end %>
</div>
<h5 class="username">
<%= link_to post.user.name, post.user.profile %>
<span class="timestamp">• <%= time_ago_in_words(post.created_at) %> ago</span>
</h5>
<div class="content">
<%= post.content %>
</div>
<ul class="foot">
<li>Like<li>
<li>Share</li>
</ul>
</div>
</div>
</div>
And the relevant bits from the controller:
class PostsController < ApplicationController
respond_to :html, :js # Allow for AJAX requests as well as HTML ones.
before_filter :load_postable
load_and_authorize_resource
def index
#post = Post.new
#posts = #postable.posts
end
private #################
def load_postable
klass = [User, Event].detect { |c| params["#{c.name.underscore}_id"] } # Look for which one of these there's a ***_id parameter name for
#postable = klass.find(params["#{klass.name.underscore}_id"]) # Call find on that, passing in that parameter. eg Event.find(1)
end
Can anyone explain to me what's going on here? I couldn't find anything in the Layouts and Rendering guide at rubyonrails.org.
Thanks!
Your error comes from assuming :collection and #posts mean the same thing when rendering. From Rails Docs (point 3.4.5):
Partials are very useful in rendering collections. When you pass a collection to a partial via the :collection option, the partial will be inserted once for each member in the collection
So, if you use that, for each post, you will be doing post.any? which fails as any? isn't defined for a single post.
From the same docs, you should check if render returns Nil to see if the collection is empty:
<h1>Posts</h1>
<%= render(#posts) || "There are no posts." %>
PD: Use the partial to render only one post, not all of them.
GL & HF.

Resources