I am trying link to the 'edit' action of a nested Comment from the 'index' action of its parent Articles controller. If no comment exists, then the link will go to the 'new' action.
resources :articles do
resources :comments
end
The problem seems to be how to define #comment in the Articles controller in order to get the proper comment id with the associated article id.
The Articles controller contains:
def index
#articles = Article.all
end
I can accomplish what I want by defining #comment in the View 'index.html.erb' (see below):
<% #articles.each do |article| do %>
<% #comment = current_user.comments.where(article_id: article.id) %>
<% if #comment.empty? %>
<%= link_to "New Comment", new_article_comment_path(article) %>
<% else %>
<% #comment.each do |comment| %>
<%= link_to "Edit Comment", edit_article_comment_path(article, comment) %>
<% end %>
<% end %>
<% end %>
But I would prefer to have #comment defined in the Articles controller. I am not sure how to implement '#comment = current_user.comments.where(article_id: article.id)' in the Articles controller without the id as it's the 'index' action.
Must be something simple I'm missing.
I don't know how it would work inside a controller. But I think it's better to move the method inside a helper anyway and call it from there. methods defined inside a helper are automatically available for your views
you can do this:
def comment(article)
#comment = current_user.comments.where(article_id: article.id)
end
Then your view will look like this:
<% #articles.each do |article| do %>
<% comment(article) %>
....more code....
Like you said, if you move this in the controller, where(article_id: article.id) will trip you as you don't know which article the id is bound to.
EDIT:
if you really want to access the method inside the controller, you can do as this post suggests:
class ArticlesController < ActionController::Base
def comment(article)
#comment = current_user.comments.where(article_id: article.id)
end
helper_method :comment(article)
end
but why go through the trouble when you can easily do this inside a helper.
Related
Is it possible to generate a dynamic method using the strong parameter I get from my view?
In my view I will generate a different path according to the card the user clicks on. Then, in the controller I want to generate a dynamic method using the parameter obtained from the view, but I'm not sure how to write that. Thanks!
show.html.erb
<div class="branch-names">
<% #branches.each do |branch| %>
<div>
<%= image_tag "cat.jpeg" %>
<%= link_to "#{branch.name} Posts", send("#{branch.branch}_posts_path") %>
</div>
<% end %>
</div>
posts_controller.rb
def self.define_category(name)
define_method(name) do |params[:id]|
#posts = Post.where(category_id = params[:id])
end
end
define_category("#{params[:id]}")
You shouldn't define method based on user input. It may cause security issue, and for sure it causes performance penalty related to method cache invalidation.
Instead you can create one method that have an alternarive on params[:id] and then decide what to show to the user:
class MyController
def branches
case params[:id]
when('cat')
do_cat_stuff
when('dog')
do_dog_stuff
end
end
end
For having routes like /posts/cats you do not have to add dynamic methods. Think of branch like of an id of category:
routes:
resources :post_categories, only:[:index, :show]
view:
...
<%= link_to "#{branch.name} Posts", post_category_path(branch.branch) %>
PostCategories controller:
def show
#posts = Post.where(category_id: params[:id])
end
Also you can make posts a nested resource under categories and use a more RESTful structure with /post_categories/some_branch/posts mapping to posts#index
I'm trying to render a the index view inside my ruby-on-rails application. How do a I render the index view, from inside a view passing an array of things to display? Using the link_to.
I do not want to re-route to the controller, I just want to link_to a view passing it the variables it needs, how can I do this?
EDIT:
I am trying to create a page type functionality in the index of my article model. So I have around 400 articles for example, and when the index action in the article controller is called, it of course renders the index view which is calling a partial for each article in the '#articles array' passed on by article controller's index action.
So in the view, I'm trying to do something like:
<% count = 0 %>
<% #articles.each do |article| %>
<% if count <10 %>
<%= render partial: 'index_articles', locals: {article: article} %>
<% count = count + 1 %>
<% end %>
<% end %>
<% #articles = #articles.drop(10) %>
<% if #articles.any? %>
<%= link_to "Next", 'articles', locals: {#articles => #articles} %>
<% end %>
Thank you in advanced for all of your help.
You'll need to use the render command, probably with a partial:
<%= render "controller/index", collection: ["your", "array"], as: :object_name %>
You will have to call a controller action to generate this. You cannot simply load it on your screen, unless it was preloaded inside your javascript for something:
#View
<%= link_to "Index", controllers_path(ids: ["1","2"]), remote: true %>
#app/controllers/your_controller.rb
class YourController < ApplicationController
def index
#posts = request.xhr? Post.find(params[:ids]) : Post.all
respond_to do |format|
format.js #-> app/views/controller/index.js.erb
format.html
end
end
end
#app/views/controller/index.js.erb
$(".element").html("<%=j render 'index' %>");
There are several issues with this approach...
Flow
First of all, your flow of your app should be as structured as possible.
In short, if you're calling the index view inside another action, it's not the index view any more.
What you should look at is how to use a partial in your app:
#app/controller/views/_partial.html.erb
<%= post.title %>
This way, you can adapt your index view and your other page to use the partial in their respective action layouts:
#app/controller/views/index.html.erb
<%= render "partial", collection: #posts, as: :post %>
This will allow you to "reuse" code much in the way you want. This will be much more appropriate than trying to invoke other action/views.
-
Resources
Secondly, you'll want to look at how your app functions.
Your index view is meant to show all the items for a particular object. Whilst you're free to change this as you want, the fact remains that you have to keep some structure.
You should read up on the routes for your actions, and how they're meant to work in your application. This will give you some perspective on the resourceful nature of Rails routes, and how you'll have to call specific routes with specific actions.
Your problem is probably that the file needs to be named _index.html.erb. You can have another file named index.html.erb which just renders _index.html.erb.
If you need a full guide on using AJAX, look up the railscast. If you're not using AJAX and you just want to render it, then you don't use link_to. You just do <%= render :index %>.
I'm a beginner at rails and thus far interplating data in views has been pretty straight forward. I've been introduced to something slightly new as far as how the controllers are setup and as a result I'm not sure how one would go about getting the data to present in the view.
First controller
class PagesController < ApplicationController
def index
#guestbook_entry = GuestbookEntry.new
render "welcome"
end
end
Second controller
class GuestbookEntriesController < ApplicationController
def create
GuestbookEntry.create(guestbook_entry_params)
redirect_to root_path, notice: "Thank you for your entry."
end
private
def guestbook_entry_params
params.require(:guestbook_entry).permit(:body)
end
end
And here is the welcome.html.erb
<h1>Welcome to My Guestbook</h1>
<br>
<%= image_tag("under_construction.gif") %>
<div id="guestbook-entries">
<p>Guestbook Entries:</p>
<ul>
</ul>
</div>
<%= form_for #guestbook_entry do |f| %>
<%= f.label :body, "Guestbook Entry:" %>
<%= f.text_area :body %>
<%= f.submit "Submit" %>
<% end %>
So it wants me to iterate through all the entries and display them on a welcome page that's located in view/pages/welcome.html.erb.
Up to this point I guess I've only been doing basic simple rails applications where the view corresponded with the controller, and followed the typical CRUD setup, where index would hold the #xxx = Xxxx.all and new/create would handle #xxx = Xxxx.new/create/build. I thought I could simply move the PageController's index action to create/new and do
def index
#guestbook_entry = GuestbookEntry.all
render "welcome"
end
To satisfy the test (it looks for render welcome in the index action)
This seems weird but again I admit, I'm a beginner.
If you want to list all the guest book entries on your root page you would do something like:
class PagesController < ApplicationController
def index
#guestbook_entry = GuestbookEntry.new
#guestbook_entries = GuestbookEntry.limit(10).all
render "welcome"
end
end
And in your view you would list them like:
<% if #guestbook_entries.any? %>
<div id="guestbook-entries">
<p>Guestbook Entries:</p>
<% #guestbook_entries.each do |entry| %>
<ul>
<li class="entry"><%= h(entry.body) %></li>
</ul>
<% end %>
</div>
<% end %>
The rest of you application is correct - you should be creating entries in GuestbookEntriesController#create. In many real life applications then the functionality of the standard new and edit actions can actually be a totally different controller.
I use Devise gem for authentication.
In database I have users table and posts table in my database schema (and Post controller).
In post controller I want to find all posts assigned to specific user. I have user_id in posts table.
How to get all user's posts or how to check if specific post is assigned for SIGNED IN user.
I thought about something like this (of course is only pseudocode:
current_user.id == Post.where(params:[post_id]).user_id
So how to get current user id in Devise and how to check the current user id is the same like eg. user_id assigned to viewing post (I want to add 'edit' function when current user is post owner) and how to find all post which current user is owner.
Associations
Firstly, your user_id column in your posts table is what's known as a foreign_key
Foreign keys are used in relational database systems to give you the ability to call associative data from a single record. Simply, it means that you'll be able to use the ActiveRecord associations to call the data you require, rather than having to call it individually:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
end
#app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
This will give you the ability to use the following call:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#posts = current_user.posts
end
end
You'll be best served looking up the has_many association:
Fix
In regards to showing your posts for your users, you need to be sure that you have the correct "flow" set up. What I mean is you need some condition to know whether your user is signed in & that #posts is set:
#app/views/posts/index.html.erb
<% if #posts.present? %>
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
Maybe this is the first time you use Devise. You can access current_user inside controllers or views. I imagine you could do something like this
In controller (posts_controller.rb):
#posts = current_user.posts
In view (posts/show.html.erb, I guess):
if current_user.id = #post.current_user
#render something here
end
Get all post which current user is owner.
#posts = Post.where(:user_id => current_user.id)
and on your view
<%-# commented : checking if #posts is empty -%>
<% if #posts.empty? %>
<span>Sorry, post is empty </span>
<% else %>
<%= #posts.each do |p| %>
<% if p.user_id == current_user.id %>
<% link_to "edit", edit_path(p) %>
<% end %>
<% end %>
<% end %>
There are many ways you could get current_user posts. I'll go the long way.
we need
an action
an action view and a partial
a route
a link_to
* action *
def my_posts
#posts = current_user.posts.all.order(created_at: 'DESC')
end
* view *
my_posts.html.erb
<% if #posts.present? %>
<%= render 'posts' posts: #posts %>
<% else %>
<h1>You don't have any posts yet! create one</h1>
<% end %>
_posts.html.erb
<%posts.each do |post| %>
<%= post.title %>
<% end %>
index.html.erb
<%= render 'posts' posts: #posts %>
route
get 'post' => 'posts#my_posts', as: :my_posts
link_to
<%= link_to 'My posts', my_posts_path %>
I may be late but someone can find it useful :)
I have the following in my view (index.html.erb) code:
<% #projects.each do |project| %>
<%= link_to (#project) do %>
<div id="tombstone">
...Some HTML here...
</div>
<% end %>
<% end %>
The goal is to have each project's synopsis displayed inside the tombstone DIV and have the entire DIV act as the link to the project's details page (show.html.erb).
My Controller has the following:
def show
#project = Project.find(params[:id])
end
and the routes has the following:
resources :projects do
...
resources :updates
end
The #project in the <%= link_to %> points back to the projects (index.html.erb) page, not to the project details page (show.html.erb) that the controller defines. I can only guess that the ID parameter isn't getting passed, but I can't figure out why.
<%= link_to(project) do %> # not #project
Technically you've been sent to index because #project probably new record. #project == Project.new, so link_to(Project.new) with GET request renders path to index action.