In my application, users submit reviews under brands. Here's the association:
class Brand < ActiveRecord::Base
has_many :reviews
class Review < ActiveRecord::Base
belongs_to :brand
Right now I have a partial defined to show reviews as such:
_showreview.html.erb
<% review.each do |review| %>
<div class="col-sm-4">
<div class="thumbnail">
<%= image_tag review.first_photo %>
<div class="caption">
<h4><%= link_to review.title, review %></h4>
<h6><strong><%= link_to ("WRITTEN BY " + review.user.username.upcase), review.user %></strong></h6>
<%= review.description.truncate_words(60, omission: '...') %>
<br>
<br>
<%= link_to review.brand.label, review.brand, :class => 'btn btn-sm btn-lake' %>
</div>
</div>
</div>
And I render it like this by passing an instance variable in:
<%= render "showreview", review: #top_reviews %>
It works as expected.
Now I wish to reuse the partial for brands/show.html.erb
What I want to do now is retrieve all the reviews that belong to a brand and display it.
show_controller.rb looks like this
def show
#brand = Brand.find(params[:id])
#reviews =Review.find(params[:id])
end
I tried to use this but it doesn't work. What is the correct way to do this?
<%= render "/reviews/showreview", review: '#brand.reviews' %>
<%= render "/reviews/showreview", review: #brand.reviews %>
But please, rename review to reviews. It's more convenient name of this variable.
Your method will be like this
def show
#brand = Brand.find(params[:id])
end
and in your view
<%= render "reviews/showreview", review: #brand.reviews %>
firstly, you should use a plurality for the variable review instead.
reviews.each do |review|
it makes your code readability.
then try placing review: '#branch.review' by reviews: #branch.reviews
and make sure that you did pass the variable #branch from your controller
Related
Below is my review.html.erb:
<% provide(:title, 'All reviews') %>
<h1>All reviews</h1>
<ol class="reviews">
<%= render #reviews %>
</ol>
<%= will_paginate #reviews %>
And my _review.html.erb looks like:
<li>
<p>Student: <%= Student.find(review.student_id).name%></p>
<p>Score: <%= review.score%></p>
<p>Review: <%= review.review%></p>
<p>Created at: <%= review.created_at%></p>
</li>
How can I pass #students as well to render for example?
I tried <%= render #reviews, #students %> in review.html.erb and Student: <%= student.name%> in _review.html.erb. It didn't work.
You don't actually need to pass multiple parameters. You just need to setup the assocations between reviews and students:
class Student < ApplicationRecord
has_many :reviews
end
class Review < ApplicationRecord
belongs_to :student
# optional but avoids a law of demeter violation
delegate :name, to: :student, prefix: true
end
<li>
<p>Student: <%= review.student_name %></p>
<p>Score: <%= review.score %></p>
<p>Review: <%= review.review %></p>
<p>Created at: <%= review.created_at %></p>
</li>
To avoid a N+1 query issue you should use includes or eager_load to load the student with the reviews:
#reviews = Review.includes(:student)
.all
If you do actually want to pass additional arguments when rendering a collection (which isn't needed here) you do it with local assigns:
<%= render #reviews, locals: { foo: 'bar' } %>
This will be available in the partial as foo or local_assigns(:foo).
Reivew table and students are related
In _review.html.erb , you don't need use Student.find(review.student_id)
<li>
<p>Student: <%= review.student&.name%></p> // changed
....
</li>
I have a Product (imovel) controller where the users can create his own Products (imovels). I am using devise for the authentication and the CRUD (create, Update, Delete) needs login. So for the clients be able to see the products and doesn't need a user, I created the Welcome controller where so it is the root.
In the Index of the Products I use Ransack to do the research in the table and works just fine. (very happy about it).
On the welcome controller I try to do the same thing, but when I submit the search the page gets redirect to the imovels#index.
Controller:
class WelcomeController < ApplicationController
def index
#q = Imovel.ransack(params[:q])
#imovel = #q.result(distinct: true)
end
end
View:
<div class="container text-center">
<%= search_form_for #q do |f| %>
# Search if the name field contains...
<%= f.label :descricao_cont %>
<%= f.search_field :descricao_cont %>
<%= f.submit "Pesquisar", class: "btn btn-primary" %>
<% end %>
</div>
Another thing that can be important in the index (imovels#index) there is a for in a tr and the information is filtered there:
Imovels Index
<tbody>
<% #imovels.each do |imovel| %>
<tr>
<td><%= imovel.id %></td>
<td><%= imovel.descricao %></td>
<% end %>
And in the welcome controller where I need the search, I used Divs:
Welcome Index
<% #imovels.each do |imovel| %>
<div class="card">
<div class="containerImovel">
<h4><b><%= imovel.descricao %></b></h4>
<p><%= imovel.cidade %> - <%= imovel.bairro.nome %> </p>
</div>
</div>
<% end %>
How can I do the search on the divs of welcome controller? Ransack is the better option for it? It is possible to search in the has_many :through association?
Add a path for it in your routes.rb
resources :imovel do
collection do
match 'search' => 'welcome#search', via: [:get, :post], as: :search
end
end
and then add a new controller action to WelcomeController
def search
index
render :index
end
and afterwards modify the search form like so
<%= search_form_for #q, url: search_imovel_path, html: { method: :post } do |f| %>
Be sure to recheck the naming/variables as I'm not completely familiar with your app
There are posts, comments & users. I want to post number of comments for a specific user in comments list on Post show page. I know I need to define #user, but I don't know how to define it, so that it shows specific number for every user. User is author of the comment.
Post controller
def show
#post = Post.find(params[:id])
#comment = Comment.new
#comments = Post.find(params[:id]).comments.order(created_at: :desc)
#user = ???
end
Post /show action - error is for - #user.comments.count
<div class="row">
<% #comments.each do |comment| %><br>
<div class="col-sm-4"> <%= link_to comment.user.name, user_path(comment.user) %> <br>
<%= image_tag(comment.user.smallimage) %><%= #user.comments.count %>
</div>
<div class="col-sm-8"> <b><%= comment.title %>:</b>
<div>
<% if comment.content.length > 250 %>
<%= truncate(comment.content, length: 250) %>
<%= link_to_function '...Read more', "$(this).parent().html('#{escape_javascript comment.content}')" %>
<% else %>
<%= comment.content %>
<% end %>
</div>
</div>
<% end %>
</div>
If you define an #user you will only have one user or a group of users that doesn't relate to your comments. You don't need it. You can just use the relationship between user and comment like this:
<%= comment.user.comments.count %>
Note that this will run a database query for each comment to get the total comment count for that user. For performance reasons you may want to use a counter cache for this instead.
If you defined the association in the post model belongs_to :user then you can probably do #user = #comment.user
But, if that's the case then you can call that from the view with #comment.user.name or something like that.
I'd like to see the whole codebase if you've pushed to GitHub.
I am trying to build a gallery with commenting function. Consider there are 3 classes: Album, Photo, Comment. The relation of these objects are Album has many Photos, Photo has many Comments.
Each Comment is left by registered user, thus in the comment object there are comment_text, user_id, and photo_id (Referring to the photo which the comment belongs).
I am trying to create a comment form under each photo's "show" view. Here is some of the Controller and the Show view:
controllers/photos_controller.rb
class PhotosController < ApplicationController
...
def show
#photo = Photo.find(params[:id])
#new_comment = #photo.comments.build if user_signed_in?
#comment_items = #photo.comments.paginate(page: params[:page])
end
...
end
views/photos/show.html.erb
...
<%= form_for #new_comment, html: {method: :post} do |c| %>
<div class="row">
<div class="span">
<%= image_tag current_user.avatar.url(:thumb) %>
</div>
<div class="span">
<p><%= c.label "Enter your comment here:" %></p>
<p><%= c.text_area :comment_text %></p>
<p><%= c.submit "Submit Comment", class: "btn btn-tiny" %></p>
</div>
</div>
<% end %>
So the problem is when I am writing the CommentsController, I do not know how to pass the photo's id (photo_id) from the previous "show" page to the create method. Is it only possible if a pass it thru via a hidden field in the form? Are there any more elegant way in Rails to do so? Besides, a point on security, if I retrieve the photo_id via a hidden field, will someone be able to write a specific "post" request so that it post comments to all photos in the album? (like spammer in the php's forum long time ago..)
Thank you for reading this and thanks in advance for answering!
take a look at the rails guides on nested resources http://guides.rubyonrails.org/routing.html#nested-resources
your routes would have something like this.
resources :photos do
resources :comments
end
your photo controller would stay the same, but your comments controller would need to lookup the photo from the url
class CommentsController < ApplicationController
before_action :get_photo
def create
#photo.comments.create(params.require(:comment).permit(:comment_text))
....
end
...
def get_photo
#photo = Photo.find(params[:photo_id])
end
end
and the photo view would have
<%= form_for [#photo,Comment.new], html: {method: :post} do |c| %>
<div class="row">
<div class="span">
<%= image_tag current_user.avatar.url(:thumb) %>
</div>
<div class="span">
<p><%= c.label "Enter your comment here:" %></p>
<p><%= c.text_area :comment_text %></p>
<p><%= c.submit "Submit Comment", class: "btn btn-tiny" %></p>
</div>
</div>
<% end %>
which should invoke the new_photo_comment_path
as for the user_id i would just grabbed that from the user_signed_in helper. Since you already have them logged in, no sense in passing it in from the web.
I am trying to submit info from a form in my view, that passes the submitted info :hashtag into the model and then runs the model with that info. But it seems thats my model just runs with the words "hashtag" instead of the form info. I believe it is close. I just can't figure out where to go next.
home.html.erb
<div class="row">
<div class="span6 offset2">
<%= form_for :hashtag do |f| %>
<div class="input-prepend input-append">
<span class="add-on swag">#</span>
<%= f.text_field :hashtag , class: "span3 inverse", id:"appendedPrependedInput" %>
<%= f.submit "Swag!", class: "btn btn-inverse" %>
<% end %>
</div>
</div>
<div class="span4">
<div id="hashtags">
<% #random_hashtags.each do |hashtag| %>
<blockquote><%= hashtag.content %></blockquote>
<div class="from">— #<%= hashtag.screen_name %></div>
<% end %>
</div>
</div>
</div>
hashtag.rb
class Hashtag < ActiveRecord::Base
attr_accessible :content, :profile_image, :screen_name, :tweet_date, :tweet_id
def self.pull_hashtag
Twitter.search("%#{hashtag}").results.map do |tweet|
unless exists?(tweet_id: tweet.id)
create!(
tweet_id: tweet.id,
content: tweet.text,
profile_image: tweet.profile_image_url,
screen_name: tweet.from_user,
tweet_date: tweet.created_at
)
end
end
end
end
hashtags_controller
class HashtagsController < ApplicationController
def home
#random_hashtags = Hashtag.order("RANDOM()").limit(4)
end
def create
#hashtag = Hashtag.pull_hashtag(params[:search])
end
end
Updated code that I am currently using now as I was not posting anything to the model
It is going though on submit but it seems nothing from there.
Update 2,
I am trying to post the information to the database, by taking the info from the form, running a Twitter.search on it and creating the results in my database.
Can you try to replace with this?
form_for #hashtag, :url => :action => 'home'
my guess is that the action needs to be specified.