I have a rails app which displays images of various album covers using an Album model. I want to render a partial view alongside these album covers with the details of a selected album when it is clicked on.
I've looked for examples of this but don't seem to be able to find one that helps me. Having said that I'm new to rails so don't know for sure if I'm looking up the correct terms.
I know this must be a simple question but if anyone can point me in the right direction it would be much appreciated.
UPDATE
This seems similar to what I'm looking to do I think:
How to get Rails 3 link_to :partial to work
I've setup my code as follows:
routes.rb
Rails.application.routes.draw do
root 'albums#index'
resources :albums do
get :details, :on => :member
end
albums_controller.rb
class AlbumsController < ApplicationController
def index
#albums = Album.all
end
def show
#album = Album.find(params[:id])
#tracks = #album.tracks
end
def details
respond_to do |format|
format.js { render :layout => false }
end
end
end
views/albums/index.html.erb
<div class="row">
<% #albums.each do |album| %>
<div class="col-md-3">
<%= link_to 'Details', details_album_path(:id => album.id), :remote => true %>
<div class="thumbnail">
<img src="<%= album.cover %>">
</div>
<% end %>
</div>
<% end %>
</div>
<div id="details">
</div>
views/albums/details.js.erb
$( "#details" ).html( "<%= escape_javascript( render( :partial => "details", :locals => { :album => #album} ) ) %>" );
views/albums/_details.html.erb
<div>
<%= album.title %>
</div>
If I run this and click on the details link for an album I get this error in dev tools:
GET http://localhost:3000/albums/1/details 500 (Internal Server Error)
Rails error message at url shown in dev tools error above
And no partial is shown anywhere.
Very new to rails so any pointers appreciated. If this isn't the best way to go about this then any suggestions welcome.
So I fixed this using Muhammad's suggestion in the comments by updating def details in the albums_controller.rb to include #album = Album.find(params[:id]) :
def details
#album = Album.find(params[:id])
respond_to do |format|
format.js { render :layout => false }
end
end
Related
I am working on my first Rails project and I am running into a persistent issue. I suspect it has something to do with the routing, however, I can't seem to find anything about it online.
I assume it a rather simple fix, so please take a look and let me know if you can help.
TL;DR
What I was trying to achieve
Account detail Cards display Name, Phone number, and a note.
A delete and edit button would allow users to delete or edit.
What is happening:
Edit and Delete buttons return a weird param.
see image
Image of error, Showing Rails getting a different ID
Controller
class AccountdetailsController < ApplicationController
def index
#accountdetail = Accountdetail.all
end
#I can't find the ID to show the relevent card.
def show
#accountdetail = Accountdetail.find(params[:id])
if #accountdetail.nil?
redirect_to accountdetail_path
end
end
def new
#accountdetail = Accountdetail.new
end
def edit
#accountdetail = Accountdetail.find(params[:id])
end
def create
#accountdetail = Accountdetail.new(accountdetail_params)
if #accountdetail.save
redirect_to #accountdetail
else
render 'new'
end
end
#it affects this
def update
#accountdetail = Accountdetail.find(params[:id])
if #accountdetail.update(accountdetail_params)
redirect_to accountdetail
else
render 'edit'
end
end
#and this
def destroy
#accountdetail = Accountdetail.find(params[:id])
#accountdetail.destroy
redirect_to accountdetail_path
end
private def accountdetail_params
params.require(:accountdetail).permit(:first_name, :last_name, :phone, :notes, :id)
end
end
Index.HTML.ERB
<div class="ui card">
<div class="content">
<a class="header"><%= account.first_name %> <%= account.last_name %> </a>
<div class="meta">
<span class="date"><%= account.phone %></span>
<strong><p><%= account.notes %></p></strong> <br>
<%= link_to "edit", edit_accountdetail_path(#accountdetail) %>
<%= link_to 'Inspect', accountdetail_path(#accountdetail) %>
</div>
</div>
</div>
<% end %>
Routes
Rails.application.routes.draw do
get 'welcome/index'
resources :articles do
resources :comments
end
resources :accountdetails
root 'welcome#index'
end
In you index.html.erb replace following
<%= link_to "edit", edit_accountdetail_path(#accountdetail) %>
<%= link_to 'Inspect', accountdetail_path(#accountdetail) %>
with
<%= link_to "edit", edit_accountdetail_path(account) %>
<%= link_to 'Inspect', accountdetail_path(account) %>
#accountdetail was providing you all the records of account, as it was firing select query in controller. But here we need only one instance, so account.
Hope this helps.
Can't seem to find an answer for my specific problem.
I have a rails 4 application which displays both a blog (model is post) and a portfolio (model is pletool). My post model is working fine, as is my pletool model except that I am unable to replicate my index controller from posts to pletools.
I'm using act as taggable to tag and have two separate tag types - "tags" for the post and "pletags" for the pletools.
For both index views I want to be able to display a tag cloud of the most popular tags, which if the user then clicks on will filter to only posts or pletools of that particular tag.
I get an 'undefined method nil class' error when I try to alter the index definition in my pletools_controller.rb from "tags" to "pletags".
pletools_controller.rb
class PletoolsController < ApplicationController
layout 'application'
before_action :find_pletool, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :tag_cloud
def index
if params[:pletag].present?
#pletool = Pletool.tagged_with(params[:pletag]).paginate(:page => params[:page], :per_page => 20)
else
#pletools = Pletool.all.order('created_at DESC').paginate(page: params[:page], per_page: 20)
end
end
def tag_cloud
#pletags = Pletool.tag_counts_on(:pletags, :limit => 10, :order => "count desc")
end
def new
#pletool = Pletool.new
end
def show
end
def edit
end
def create
#pletool = Pletool.new(pletool_params)
if #pletool.save
redirect_to #pletool, notice: "Tool succesfully saved!"
else
render 'new', notice: "Try Again. I was unable to save your PLE Tool."
end
end
def update
if #pletool.update(params[:pletool].permit(:title, :description, :link, :image, :pletag_list))
redirect_to #pletool, notice: "PLE Tool succesfully edited!"
else
render 'edit'
end
end
def destroy
#pletool.destroy
respond_to do |format|
format.html { redirect_to pletools_url, notice: 'Ple Tool was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def pletool_params
params.require(:pletool).permit(:title, :link, :description,:image, :image_url, :slug, :pletag, :pletag_list)
end
def find_pletool
#pletool = Pletool.friendly.find(params[:id])
end
end
index.html.erb
<% #pletools.each do |pletool| %>
<li class="post msnry-blog-entry #">
<% if pletool.image.exists? %>
<div class="click-slide click-top">
<%= link_to image_tag pletool.image.url(:large) %>
<div class = "text-center">
<%= link_to '<span class = "ti ti-eye"></span>'.html_safe, pletool %>
</div>
</div>
<% end %>
<div class="msnry-blog-entry-text">
<h4 class"h5"><%= link_to pletool.title, pletool %></h4>
<p><%= markdown truncate(pletool.description, :length => 150) %></p>
<ul class="msnry-blog-entry-meta list-inline">
<li>
<span class="ti ti-pencil-alt">
</span>
by Anthony Llewellyn
</li>
<li>
<span class="ti ti-calendar">
</span>
<%= pletool.created_at.strftime('%A, %B %d') %>
</li>
<li class="entry-tags hidden-xs">
<% pletool.pletags.any? %>
<% pletool.pletags.each do |tag| %>
<li><a href="#">
<%= link_to tag.name, pletag_path(tag.name) %>
</a></li>
<% end %>
</li>
</ul>
</div>
</li>
<% end %>
</li>
</ul>
ok after much searching (with no real answers that I could find online) and playing around with various parameters, it turns out i had some very minor issues in a couple of my scripts.
firstly for pletools_controller.rb
i needed to change #pletool to plural in a couple of lines e.g.
#pletools = Pletool.tagged_with(params[:pletag]).paginate(:page => params[:page], :per_page => 20)
also in my routes.rg i have configured two separate index routes and again i needed to make a minor change from get 'pletag:tag' to get 'pletag:pletag'
here is the relevant section of my final routes.rb
get 'pletags/:pletag', to: 'pletools#index', as: :pletag, layout: 'application'
get 'tags/:tag', to: 'posts#index', as: :tag, layout: 'application'
Hope that this helps someone else out one day / some day!
i'm building this app where the user should be able to perform all rest actions in the same page. So below a table like the following:
<div class="row">
<div class="col-lg-3">Name</div>
<div class="col-lg-4">Lastname</div>
<div class="col-lg-3">Schedule</div>
<div class="col-lg-1"> </div>
<div class="col-lg-1"> </div>
</div>
<div id="table-body-clients">
<% #clients.each do |client| %>
<%= render :partial => 'client', :locals => { :client => client } %>
<% end %>
</div>
I should include a form to add a new client (same form will then load and edit selected clients. All on remote).
The easiest way i can think is to render 'new' page as a partial. But i don't seem to find the way to call the correct action and/or load the locals correctly.
This did not work:
<%= render 'new', :controller => "clients", :action => "new", :locals => { :client => #client } %>
'new' is actually a partial named '_new'
Anyway, I would appreciate a fix on this code as much as an insight for the right way to approach the issue.
Thanks
should be able to perform all rest actions in the same page
Don't worry about performing actions on the same page - make sure you keep your views structured in the resourceful style of Rails, but call them in the view you want (much the same as you would with partials)
As you have demonstrated, you can do this:
<%= render "clients/new", locals: { client: #client } %>
To give you a caveat here, you need to appreciate that since you're creating a new client, you'll want to build the resource in your controller:
#app/controllers/clients_controller.rb
class ClientsController < ApplicationController
def index
#clients = Client.all
#client = Client.new
end
end
--
As you mention you've got a nested route (IE client belongs to company), you want to make sure you have the following set up:
#config/routes.rb
resources :companies do
resources :clients #-> domain.com/companies/:company_id/clients
end
#app/controllers/clients_controller.rb
class ClientsController < ApplicationController
def index
#clients = Client.all
#company = Company.find params[:company_id]
#client = Client.new
end
end
#app/views/clients/index.html.erb
<%= render "new", locals: {company: #company, client: #client} %>
#app/views/clients/new.html.erb
<%= form_for [company, client] do |f| %>
...
<% end %>
Create a partial _form.html.erb as the following
<%= form_for client do |f| %>
your form fields here
<% end %>
Then, from new.html.erb and edit.html.erb, or whatever page where you need the form:
<%= render "form", client: #client %>
Replace #client with the actual client object you need the form for.
I am implementing ancestry on a nested resource.
resources :loads do
resources :messages
end
Here is my index action
def index
load = Load.find(params[:load_id])
#messages = load.messages.scoped
#message = load.messages.new
end
My index.html.erb is throwing the following error.
Missing partial messages/message with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "C:/Sites/final/cloud/app/views"
My index.html.erb is as follow
<% title "Messages" %>
<%= nested_messages #messages.arrange(:order => :created_at) %>
<%= render "form" %>
Here is my nested_message definition
module MessagesHelper
def nested_messages(messages)
messages.map do |message, sub_messages|
render(message) + content_tag(:div, nested_messages(sub_messages), :class => "nested_messages")
end.join.html_safe
end
end
Here is my _message.html.erb
<div class="message">
<div class="created_at"><%= message.created_at.strftime("%B %d, %Y") %></div>
<div class="content">
<%= link_to message.content, message %>
</div>
<div class="actions">
<%= link_to "Reply", new_load_message_url(:parent_id => message) %> |
<%= link_to "Destroy", [message.load, message], :confirm => "Are you sure?", :method => :delete %>
</div>
</div>
Any help appreciated.
This error states that your application has tried to search for a partial _messages.html.erb, as a result of this the partial must not be in your /app/views/messages which results in the message you are being shown. Check your messages directory and check if you have this partial. Going by your nested resources I am guessing your association between Load and Message is:
class Load < ActiveRecord::Base
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :load
end
Further more I noticed that you have the following line in your index action: #message = load.messages.new surely this does not seem right. Because what your telling your application to do is when the controller recieves a response to render the index action it should also create message by doing #message = load.messages.new which is why it is trying to render the partial.
To clarify things a bit more for you. If in your application you had a link_to to create a new user. Upon clicking the new user it will do something like:
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
And will render `app/views/users/new.html.erb which inside this will most probably have a
<%= form_for #user do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %>
<% end %>
This will call your partial which in normal cases would be _form.html.erb. The create action of a particular controller will come into play when you attempt to save the partial. Usually a create block for a controller will look like this:
def create
#title = "Create a user"
#user = User.new(params[:user])
if #user.save
redirect_to usermanagement_path
flash[:success] = "Created successfully."
else
#title = "Create a user"
render 'new'
end
end
Here inside the create action when your _form.html.erb or _message.html.erb is submitted it will try to create a new user by passing in the user through the params. I do thoroughly believe that your issue may potentially well be:
1) Your missing your _message.html.erb
2) Also you are calling a .new inside your index action.
Hope this clears this up for you.
I currently have a comment section that posts only after the whole page refreshes. Although after the post the page refreshes by itself it feels inefficient for the whole page to refresh. I was wondering if anyone can help me with a js file that would refresh just that partial, I am still shakey with my js. Any help is much appreciated! Thank you!
This is my current js for the create.js:
$("#comments").html("<%= escape_javascript(render(:partial => #micropost.comments)) %>");
comment controller
class CommentsController < ApplicationController
def create
#micropost = Micropost.find(params[:micropost_id])
#comment = #micropost.comments.build(params[:comment])
#comment.user_id = current_user.id
#comment.save
respond_to do |format|
format.html
format.js
end
end
end
Comment Section
<div id='CommentContainer-<%= micropost.id%>' class='CommentContainer Condensed2'>
<div class='Comment'>
<%= render :partial => "comments/form", :locals => { :micropost => micropost } %>
</div>
<div id='comments'>
<%=render micropost.comments %>
</div>
</div>
You should use something like this in your controller. This will trigger both the js and html templates as needed.
class CommentsController < ApplicationController
respond_to :html
respond_to :js, only: [ :create ]
def create
# ...
respond_with #comment if #comment.save
end
def index
#comments = Microcomment.find(params[:id]).comments
respond_with #comments
end
end
This will then require views/comments/create.js to respond with something like:
// create.js.erb
$("#comments").get("/api/micropost/<%= #micropost.id %>/comments");
And the view for the comments will be index.html.erb
# index.html.erb
<% #comments.each do |comment| %>
<!-- Display your comment here -->
<% end %>
Now all you have to do is set up a match for /api/micropost/:id/comments in your routes, and this can then serve the list of comments in the desired html format.
Note that this is not completely restful, but I like to keep the /api there to distinguish calls coming from xhr on a url level.