How to add links to pages dynamically in Rails - ruby-on-rails

My pages controller has this code:
class PagesController < ApplicationController
def index
#pages = Page.all
end
def new
#page = Page.new
end
def edit
#page = Page.find(params[:id])
end
def create
#page = Page.new(page_params)
#page.save
redirect_to #page
end
def update
#page = Page.find(params[:id])
#page.update(page_params)
redirect_to #page
end
def show
#page = Page.find(params[:id])
end
def destroy
#page = Page.find(params[:id])
#page.destroy
redirect_to pages_path
end
private
def page_params
params.require(:page).permit(:title,:description)
end
end
And in my navbar I have this code:
<% #pages.each do |page| %>
<li?<%= link_to 'page.title', page_path(page)%></li>
<% end %>
The code should generate the titles of each page created, however I get the following error when I run the page:
undefined method `each' for nil:NilClass
I thought I had eliminated this issue by entering the code inside the new function in PagesController. This pages controller is just for additional pages. The navbar also contains links to static pages, so there should always be some value in the navbar.
Has anybody any advice?

Try this:
Add this in your application_controller.rb
#pages = Page.all
and in your navbar
<% #pages.each do |page| %>
<li><%= link_to "#{page.title}", page_path(page)%></li>
<% end %>

It sounds like you don't have any pages in your Page table. Ensure you have populated this table with some pages.
You can also wrap the code in an unless clause to check if #pages is nil.
For example:
<% unless #pages.nil? %>
<% #pages.each do |page| %>
<li?<%= link_to 'page.title', page_path(page)%></li>
<% end %>
<% end %>

Related

how to pass parameters in page

I have this page (called "page"). I tried calling those pages by id with <%= link_to page.title, page_path(page.id) %>which is working, but I want to call those pages using params, I don't want their link to be direct like http://localhost:3000/pages/6 but I want that id 6 to be passed through a params, so I'll have a link like http://localhost:3000/pages?category_id=1.
Here's my pages controller
class PagesController < ApplicationController
def show
#pages = Page.find(params[:id])
end
def all
#category = Category.find_by(id: params[:category_id])
#pages = #category.pages
end
def index
if params[:id].present?
show
else
#Code of index action
#pages = Page.all
end
end
end
and my show.html.erb
<%= #page.title %>
<%= #page.body %>
and then the link to this page
<% #pages.each do |page| %>
<h4>
<b>
<%= link_to page.title, page_path(page.id)%>
</b>
</h4>
<% end %>
There may be many ways to do this and my way is as follow.
Change index action of pages_controller as follow
def index
if params[:id].present?
show
else
#Code of index action
#pages = Page.all
end
end
Change show action of pages_controller as follow
def show
#page = Page.find(params[:id])
end
And pass page id in link_to function as follow
<% #pages.each do |page| %>
<h4><b><%= link_to page.title, pages_path(:id => page.id)%> </b></h4>
#<h4><b>Page Title</b></h4>
<% end %>
I hope this will solve your problem.

Rails: Edit Comment without redirecting to the Edit View

I'm building simple web app where people can share their thought / pictures / so on. It has just two controllers Post, and nested in it Comments. Generally, at the moment all works perfectly, users can add, edit and delete posts the same way as comments. The thing I'm trying to do, and have big troubles with, is possibility to Edit comments without redirecting to the Edit Comment View - so to be able to do it from the "posts#show" level, the same way as comments actually are being created. I think it just would look much more nicer... Here are my:
posts_controller.rb
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all.order(created_at: :desc)
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#comments = #post.comments
end
def edit
end
def update
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to root_path
end
private
def find_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :description)
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :find_post, only: [:create, :edit, :update, :destroy]
def create
#comment = #post.comments.create(comment_params)
if #comment.save
redirect_to #post
else
render 'new'
end
end
def edit
#comment = #post.comments.find(params[:id])
end
def update
#comment = #post.comments.find(params[:id])
#comment.update_attributes(comment_params)
if #comment.save
redirect_to #post
else
render 'edit'
end
end
def destroy
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to #post
end
private
def find_post
#post = Post.find(params[:post_id])
end
def comment_params
params.require(:comment).permit(:content)
end
end
View show.html.haml - for post
%h1 Show page
%h3= #post.title
%p= #post.description
=link_to "Edit memory", edit_post_path
=link_to "Delete memory", post_path, method: :delete
%h4 Share your thoughts about the memory
- #comments.each do |comment|
%p= comment.content
=link_to "Edit thought", edit_post_comment_path(#post, comment)
=link_to "Delete thought", post_comment_path(#post, comment), method: :delete
= simple_form_for([#post, #post.comments.build]) do |c|
= c.input :content
= c.submit "Share thought"
View edit.html.haml - for comments (the one I'd like to get rid of / nest somehow to the view shown above)
= simple_form_for([#post, #comment]) do |c|
= c.input :content
= c.submit "Update thought"
I believe there is a simple solution, however despite the fact that I've been reading a lot about possible solution, for a newbie like me it's still difficult to figure out how this should be programed.
The terminology you're looking for is in-place editing, or inline editing
You'll either need a form or JQuery plugin to make any comment written by current_user (assuming you're using Devise) editable.
I've done this a little (you can sign up for free here, click "profile" and then edit the description):
--
The way you'd want to do it is something like this:
#app/assets/javascripts/application.js
# include x-editable scripts
$(".editable).editable([..options..]);
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<%= post.body %>
<% post.comments.each do |comment| %>
<% if comment.author == current_user %>
<%= content_tag :div, comment.body, class: "editable" %>
<% end %>
<% end %>
<% end %>
I've forgotten how we implemented the provided example; x-editable seems to be the rage now.
Here's how it works:
Include X-Editable (or other plugin) in your app
X-Editable will check for the presence of a .class or #id on an element
Providing such an element will allow X-Editable to make it editable
X-Editable then sends the completed request to the server, acting as Ajax
Looks like there's an x-editable-rails gem you can use:
#Gemfile
gem `x-editable-rails`
#app/assets/javascripts/application.js
#= require editable/bootstrap-editable
#= require editable/rails
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<% post.comments.each do |comment| %>
<%= editable comment, :body if comment.author == current_user %>
<% end %>
<% end %>

No Method Error in Lists#Show

So I've done some research on Stack Overflow and tried a variety of solutions but nothing seems to be working. I'm trying to render my ListsController show page, but I keep getting the error : undefined method `name' for nil:NilClass. When I use the rails console, my params are passing the ID through, and I can call #list = List.find(params[:id] and then #list.name. However, I keep getting the same error message. My controller looks like this:
class ListsController < ApplicationController
def index
#lists = List.order("created_at DESC")
#list = List.new
end
def create
#list = List.new(list_params)
if #list.save
if request.xhr?
# somehow only send back the html for the page update
render :layout => false
else
redirect_to root_path
end
else
#lists = List.all
render :index
end
def show
#list = List.find(params[:id])
end
end
private
def list_params
params.require(:list).permit(:name)
end
end
My view currently looks like this:
<section class="todoapp">
<header class="header">
<h1><%= #list.name %></h1>
</header>
<section class="main">
<input class="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
<%= render #list.items %>
<!-- exactly the same as: -->
<%#= render :collection => #list.items, :partial => "items/item" %>
</ul>
</section>
</section>
I've tried using the line <%= #list.name if #list.name %> but that doesn't seem to be ruling out the event of nil class either (even though params currently have an ID).
class ListsController < ApplicationController
def index
#lists = List.order("created_at DESC")
#list = List.new
end
def create
#list = List.new(list_params)
if #list.save
if request.xhr?
# somehow only send back the html for the page update
render :layout => false
else
redirect_to root_path
end
else
#lists = List.all
render :index
end
end
def show
#list = List.find(params[:id])
end
private
def list_params
params.require(:list).permit(:name)
end
end

What is causing NoMethodError in my CRUD?

I am student working on my first project on my own. The user is supposed to be able to create a to-do list. I have my form partial displayed and am trying to now render the list items through a partial. After altering my routes.rb and items_controller.rb I still receive NoMethodError.
Here is the stack trace.
Completed 500 Internal Server Error in 23ms (ActiveRecord: 0.2ms)
ActionView::Template::Error (undefined local variable or method `items' for #<#<Class:0x007fa1c3b4e238>:0x007fa1bd6f2258>):
1: <% items.each do |i| %>
2: <%= i.name %>
3: <% end %>
app/views/items/_item.html.erb:1:in `_app_views_items__item_html_erb___4201771908086516106_70166314068980'
app/views/users/show.html.erb:5:in `_app_views_users_show_html_erb__1693372631105662933_70166313045680'
items_controller.rb
class ItemsController < ApplicationController
def index
#items = Item.all
end
def show
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
def edit
#item = Item.find(params[:id])
end
def create
#item = Item.new(params.require(:item).permit(:name))
if #item.save
flash[:notice] = "The item was added to your list."
redirect_to :show
else
flash[:error] = "There was a problem creating your item."
redirect_to :new
end
end
end
routes.rb
Rails.application.routes.draw do
get 'welcome/index'
get 'welcome/about'
# resources :welcome, only: [] do
# collection do
# get 'about'
# get 'index'
# end
# end
devise_for :users
resources :users, only: [:show]
resources :items
root to: 'welcome#index'
end
users/show.html.erb
<h1>Welcome <%= current_user.name %></h1>
<p>Add an item</p>
<%= render partial: 'items/form', locals: { item: #new_item } %>
<%= render partial: 'items/item', locals: { item: #items } %>
items/_item.html.erb
<% items.each do |i| %>
<%= i.name %>
<% end %>
EDIT: Here is my users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
def show
#user = User.find(params[:id])
#new_item = Item.new
end
end
You need to use local variable item, which you passed to the partial _item.html.erb. :
<% item.each do |i| %>
<%= i.name %>
<% end %>
and ...
class UsersController < ApplicationController
before_action :authenticate_user!
def show
#user = User.find(params[:id])
#new_item = Item.new
#items = Item.all
end
end

Rails many to many association

I have implemented a save buttons for jobs and it work fine now i want to list some of the saved jobs in the jobs index page for this i have this code
<h3>Saved Jobs</h3>
<ul>
<% #user.saved_jobs.limit(5).order(:created_at).reverse_order.each do |saved_job| %>
<li><%= link_to saved_job.job.title, saved_job.job.url %>
<span class="delete_button">
<%= link_to "X", saved_job, :method => :delete, :remote => true %></span></li>
<% end %>
</ul>
<%= link_to "see all", saved_jobs_path %>
but when i want access to the jobs index page i get this error undefined method saved_jobs' for nil:NilClass
this my saved_jobs controller
class SavedJobsController < ApplicationController
before_filter :authenticate_user!
def index
#saved_jobs = SavedJob.find_all_by_user_id(current_user.id)
end
def create
#job = Job.find(params[:saved_job][:job_id])
current_user.save_job!(#job)
respond_to do |format|
format.html { redirect_to #job }
format.js
end
end
def destroy
#job = SavedJob.find(params[:id]).job
current_user.saved_jobs.find(params[:id]).destroy
respond_to do |format|
format.html { redirect_to #job }
format.js
end
end
end
and this is my user controller
class ProfilesController < ApplicationController
before_filter :authenticate_user!
def show
#user = User.find_by_slug(params[:id])
if #user
#posts = Post.all
render action: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
def index
#users = user_scope.paginate(page: params[:page], per_page: 2)
end
private
def user_scope
current_user ? User.where.not(id: current_user.id) : User.all
end
end
The error suggests that you didn't set #user in your controller action. Can you post the code from your controller?
Update based on controller code:
Your index action in SavedJobsController does not set #user. When you then call #user.saved_jobs.limit(5)..etc... in the view #user is nil, rather than current_user or whatever.
Additionally, you have set #saved_jobs - why not just use that instead of #user.saved_jobs?
for instance:
#in SavedJobsController
def index
#saved_jobs = current_user.saved_jobs.limit(5).order('created_at DESC')
end
and then, in your view:
<% #saved_jobs.each do |saved_job| %>

Resources