I'm trying to paginate my posts under it's forum_thread_id.
When I paginate #forum_posts I'm getting all the posts and not the ones specific to the thread id that I'm in.
I'm using will_paginate for pagination.
It's probably any easy fix that I'm not seeing.
You have to filter the query with the ForumThread id, try something like this (modify the code accordingly)
def show
#forum_post = ForumPost.new
#forum_posts = ForumPost.where(forum_thread_id: #forum_thread.id).paginate(:page => params[:page], :per_page => 3)
end
Your problem is here:
def show
#forum_post = ForumPost.new
#forum_posts = ForumThread.find(params[:id])
#forum_posts = ForumPost.paginate(:page => params[:page], :per_page => 3)
end
You're paginating the equivalent of ForumPost.all, which means you're going to get back all the posts, regardless of which thread they're a part of.
You need:
def show
#forum_post = ForumPost.new
#forum_thread = ForumThread.find params[:id]
#forum_posts = #forum_thread.paginate(page: params[:page], per_page: 3)
end
This is assuming you have the following setup:
#app/models/forum_thread.rb
class ForumThread < ActiveRecord::Base
has_many :forum_posts
end
#app/models/forum_post.rb
class ForumPost < ActiveRecord::Base
belongs_to :forum_thread
end
As an aside (this is advanced), you'd be much better putting your thread and post models into a Forum module:
#app/models/forum.rb
class Forum < ActiveRecord::Base
has_many :threads, class_name: "Forum::Thread"
end
#app/models/forum/thread.rb
class Forum::Thread < ActiveRecord::Base
belongs_to :forum
has_many :posts, class_name: "Forum::Post"
end
#app/models/forum/post.rb
class Forum::Post < ActiveRecord::Base
belongs_to :thread, class_name: "Forum::Thread"
end
This would allow you to use the following:
#config/routes.rb
scope path: ":forum_id", as: "forum" do
resources :threads do
resources :posts
end
end
#app/controllers/forum/threads_controller.rb
class Forum::ThreadsController < ApplicationController
def show
#forum = Forum.find params[:id]
#threads = #forum.threads
end
end
This is how I got it working.
#forum_posts = #forum_thread.forum_posts.paginate(:page => params[:page], :per_page => 2)
Related
I am new in Rails and I want to create shopping History. I think my association doesn't work correctly or my function current order
My model
User
Order
Order_line_item
Order_item
Cart
So my Db Looks like this
When I click "Buy" button in cart Oder_items create in Order_line_items. For example you can order 1 item or several items. The quantity of you order save in Order Line Items. So the order_line_items save in Order. It's order history. This is how My logic work. I think so. I can see any order by id. Like this
Association
class User < ApplicationRecord
has_many :cart_items
has_many :order_items
has_many :order_line_items, through: :order_items
has_one :cart, dependent: :destroy
has_one :order, dependent: :destroy
end
class Order < ApplicationRecord
has_many :order_line_items
has_many :order_items
belongs_to :user
end
class OrderLineItem < ApplicationRecord
has_many :order_items
belongs_to :order
has_one :user, through: :order
end
class OrderItem < ApplicationRecord
belongs_to :order_line_items
belongs_to :order
belongs_to :product
# has_one :user, through: :order_line_items, :source => :order
end
Application Helper
module ApplicationHelper
def current_order_line(order_line)
if OrderItem.find_by(order_line_id: order_line[:id]).present?
OrderItem.find_by(order_line_id: order_line[:id])
else
current_order.order_line_items || current_order.build_order_line_items
end
end
#I think this code doesn't work property
def current_order
if session[:order_id].present?
Order.find(session[:order_id])
else
current_user.order || current_user.build_order
end
end
def current_cart
if session[:cart_id].present?
Cart.find(session[:cart_id])
else
current_user.cart || current_user.build_cart
end
end
end
My Controllers
class OrdersController < ApplicationController
def show
#order_line_items = current_order.order_line_items
end
end
class OrderItemsController < ApplicationController
def create
#order_line_items = current_order_line_items
#order_item = #order_line_items.order_items.new(order_params)
#order_line_items.save
redirect_to my_orders_path
OrderMailer.order_confirmation(current_user, #order_item).deliver_now
flash[:success] = "Order has been confirmed"
session[:order_id] = #order.id
session[:user_id] = current_user.id
def order_params
params.require(:order_item).permit(:product_id)
end
end
#There I need also call order_line_item to create order. I don't know how
class OrderLineItemsController < ApplicationController
def show
#order_items = current_order.order_items
end
class CartsController < ApplicationController
def show
#cart_items = current_cart.cart_items
#order_line_item = current_order.order_line_items.new
#order_item = current_order_line(#order_line_item.id).order_items #I got error here
end
Error message:
NoMethodError in CartsController#show
undefined method `[]' for nil:NilClass
I think I made a mistake with my association and my function current_order_line doesn't work property. I will be pressure If you can help me!
Maybe I think It can be work
module ApplicationHelper
def current_order_line
if session[:order_line_id].present?
OrderLineItem.find(session[:order_line_id])
else
current_order.order_line_items || current_order.build_order_line_items
end
end
class CartsController < ApplicationController
def show
#cart_items = current_cart.cart_items
#order_line_item = current_order.order_line_items.new
#order_item = current_order_line.order_items.new
end
So then I got this error message
NoMethodError in CartsController#show
undefined method `order_items' for #<ActiveRecord::Associations::CollectionProxy []>
I believe that your issue might be here.
def current_order_line
if session[:order_line_id].present?
OrderLineItem.find(session[:order_line_id])
else
current_order.order_line_items || current_order.build_order_line_items
end
end
If I look at the if block OrderLineItem.find(session[:order_line_id]), you are returning a OrderLineItem record.
However, the else block current_order.order_line_items || current_order.build_order_line_items does not return a OrderLineItem record. Instead, you are returning a relationship and not a single record.
When you do current_order.order_line_items, you are returning an ActiveRecord collection (not a single record). And ActiveRecord does not have a order_items method; that method is defined on OrderItem
If you want to keep the current design, what you need to do is return an OrderLineItem from current_order_line. I think the following should work (syntactically, but not sure if that makes sense in terms of the business logic):
def current_order_line
if session[:order_line_id].present?
OrderLineItem.find(session[:order_line_id])
else
if !current_order.order_line_items
current_order.build_order_line_items
end
current_order.order_line_items.first
end
end
I have two controllers- a ProfilesController and a UsersController. I have a page full of blog posts, and I want each to have a link to the profile of the user who created them. I've been having a wee problem with this lately, and I want to start fresh, but don't know where to begin. How can I go about this?
Post controller:
def index
#shit = Static.all.order('id DESC')
if params[:search]
#posts = Post.search(params[:search]).order("created_at DESC").paginate(page: params[:page], per_page: 5)
else
#posts = Post.all.order('created_at DESC').paginate(page: params[:page], per_page: 5)
end
end
Profiles model:
class Profile < ApplicationRecord
belongs_to :user
end
Users model:
class User < ApplicationRecord
has_secure_password
validates :username, uniqueness: true
has_many :posts, foreign_key: :author
has_many :comments, foreign_key: :author
has_one :profile, foreign_key: :user
after_create :build_profile
def build_profile
Profile.create(user: self) # Associations must be defined correctly for this syntax, avoids using ID's directly.
end
end
BTW not using Devise
Use joins
def index
#shit = Static.all.order('id DESC')
scope =
if params[:search]
Post.search(params[:search])
else
Post.all
end
#posts =
scope.
joins(:users).
joins(:profiles).
order("created_at DESC").
paginate(page: params[:page], per_page: 5)
end
In single #post object you should have relation to owner (user). In your view for each post use route for user_path but provide it with #post.user
Example in view
<% #posts.each do |post| %>
<%= link_to user_path(post.user) %>
//Rest of post content
<% end %>
I need to filter the posts that appear on my index page. I filtered them initially by using this condition in the view:
if current_user.courses.any? {|h| h[:name] == post.course.name}
But since I added will_paginate, I get blank pages because it paginates even the posts I don't want to show. How can I use a scope to filter out the posts in the controller?
These are my models:
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :course
has_many :comments
end
and
class Course < ActiveRecord::Base
belongs_to :user
has_many :posts
belongs_to :major
end
and my controller codes
def index
#posts = Post.all.order("created_at DESC").paginate(:page =>
params[:page], :per_page => 1)
end
If your filter contains more than one courses names :
def index
#posts = Post.joins(:course).where('courses.name in (?)',current_user.courses.map(&:name)).paginate(:page => params[:page], :per_page => 1)
end
I am totally new to Ruby, and Rails. Currently, I am using helper methods. How can I write the same code as this in my Model 'User' so as to access all these variables from controller and view?
Writting code this way in helper is 100% functional:
module HomeHelper
def init(user_id)
#friends = Array.new
#followers = Array.new
#user = User.find_by_id(user_id) #Get User
#friends = #user.users #Get all his friends
#
#statuses = Array.new #
#friends.each do |friend| #
#statuses += friend.statuses #Get all statuses for 'a' friend, then loop
end #
#statuses += #user.statuses #
#statuses = #statuses.sort_by {|status| status.created_at}.reverse!
#friendsof = Array.new
#filtered_friendsof = Array.new
#friends.each do |friend|
#friendsof += friend.users
end
#friendsof.each do |friendof|
unless (#friends.include?(friendof))
if #user != friendof
#filtered_friendsof << friendof
end
end
end
end
#filtered_friendsof = #filtered_friendsof.uniq
end
Controller
class HomeController < ApplicationController
def index
#user_id=3
end
end
Model:
class User < ActiveRecord::Base
has_many :statuses
has_and_belongs_to_many(:users,
:join_table => "user_connections",
:foreign_key => "user1_id",
:association_foreign_key => "user2_id")
#has_many :user_connections
end
Home controller:
class HomeController < ApplicationController
def index
#user = User.find(3)
end
end
User model:
class User < ActiveRecord::Base
has_many :statuses
has_and_belongs_to_many :friends,
:class_name => 'User'
:join_table => "user_connections",
:foreign_key => "user1_id",
:association_foreign_key => "user2_id"
def combined_statuses
(friends.map(&:statuses) + statuses).flatten.
sort_by {|status| status.created_at}.reverse!
end
end
Now, you don't need your helper method and in your view you can use:
#user.friends # instead of #friends
#user.combined_statuses # instead of #statuses
I'll let you figure out the rest, but I hope you get the general idea of pushing the logic into the model.
Most of that logic belongs in the User model. Nothing else needs to be actually doing those computations, and the User model has access to all the relevant pieces. There are additionally several other improvements that can be made. I'll try to add comments below to indicate these improvements.
Model
class User < ActiveRecord::Base
has_many :statuses
has_and_belongs_to_many :friends, # now you can just say user.friends
:class_name => 'User', # makes more sense semantically
:join_table => "user_connections",
:foreign_key => "user1_id",
:association_foreign_key => "user2_id"
def friends_statuses
(friends.map(&:statuses).flatten + statuses).sort_by!(&:created_at).reverse
# Ruby has many great methods for Arrays you should use.
# You can often avoid instantiating variables like the empty Arrays you have.
end
def second_order_friends
(friends.map(&:friends).flatten.uniq - friends) - [self]
end
end
Controller
class HomeController < ApplicationController
def index
user = User.find(7) # how do you decide which user you're displaying things for?
# this might be better off in 'show' rather than 'index'
# here you can call all the methods you have for 'User', such as:
# user.friends, user.statuses, user.friends_statuses, user.second_order_friends
# to make things accessible in the view, you just need an #variable, e.g.:
#friends = user.friends
#latest_statuses = user.friends_statuses.first(10)
end
I am having an issue trying to save into an intermediate table. I am new on Rails and I have spent a couple of hours on this but can't make it work, maybe I am doing wrong the whole thing. Any help will be appreciated. =)
The app is a simple book store, where a logged-in user picks books and then create an order.
This error is displayed:
NameError in OrderController#create
uninitialized constant Order::Orderlist
These are my models:
class Book < ActiveRecord::Base
has_many :orderlists
has_many :orders, :through => :orderlists
end
class Order < ActiveRecord::Base
belongs_to :user
has_many :orderlists
has_many :books, :through => :orderlists
end
class OrderList < ActiveRecord::Base
belongs_to :book
belongs_to :order
end
This is my Order controller:
class OrderController < ApplicationController
def add
if session[:user]
book = Book.find(:first, :conditions => ["id = #{params[:id]}"])
if book
session[:list].push(book)
end
redirect_to :controller => "book"
else
redirect_to :controller => "user"
end
end
def create
if session[:user]
#order = Order.new
if #order.save
session[:list].each do |b|
#order.orderlists.create(:book => b) # <-- here is my prob I cant make it work
end
end
end
redirect_to :controller => "book"
end
end
Thnx in advance!
Manuel
Only got time to look at this briefly, I'm afraid, but the first thing I spot is that your has_many relations are called :orderlists. I think that needs to be :order_lists, with an underscore.
This is not directly associated with your question but this query:
book = Book.find(:first, :conditions => ["id = #{params[:id]}"])
...is vulnerable to sql injection. In this case content of params[:id] gets passed to sql without proper escaping. I would suggest changing this line to something like this:
book = Book.find(:first, :conditions => ["id = ?, params[:id]])
Here's explanation: http://wiki.rubyonrails.org/howtos/security/sql_injection
Yes that was one of the problems. Then I could make it work with this line in the 'create' method:
def create
if session[:user]
#order = Order.new
if #order.save
session[:list].each do |b|
OrderList.create(:book => b, :order => #order)
end
end
end
redirect_to :controller => "book"
end
Thanks Chris