Hi guys im creating blog with friendly id, but its not working..
The problem is when i tried to edit the title, friendly id came up, but when i reopen, it just show the blog id. not the slug anymore
this is the code
in my model :
class Blog < ApplicationRecord
extend FriendlyId
friendly_id :title, use: :slugged
def should_generate_new_friendly_id?
slug.blank? || title_changed?
end
end
my blog controller
class BlogsController < ApplicationController
before_action :set_blog, only: [:show, :edit, :update, :destroy]
def index
#blogs = Blog.all
end
def show
#blog = Blog.friendly.find(params[:id])
end
def new
#blog = Blog.new
end
def create
#blog = Blog.new(blog_params)
if #blog.save
redirect_to blog_path(#blog), notice: "Successfully Created"
else
render :new
end
end
def edit
end
def update
if #blog.update(blog_params)
redirect_to blog_path(#blog), notice: "Successfully Update"
else
render 'edit'
end
end
def destroy
#blog.destroy
redirect_to blog_path(#blog)
end
private
def set_blog
#blog = Blog.friendly.find(params[:id])
end
def blog_params
params.require(:blog).permit(:title, :body, :image, :category_id)
end
end
i spent so much time to solve this.. please help
Related
I'm trying to do something like Instagram where you can see images of people you only follow. A user can follow another user and create new posts.
This is what i have for following and unfollowing in my Users controller.
def following
#user = User.find(params[:id])
current_user.mark_as_following #user
respond_to do |format|
format.html {redirect_to #user}
format.js
end
end
def unfollow
#user = User.find(params[:id])
#user.unmark :following, :by => current_user
respond_to do |format|
format.html {redirect_to #user}
format.js
end
end
Here is my my Posts controller
class PostsController < ApplicationController
load_and_authorize_resource
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
end
def create
#post.user_id = current_user.id
if #post.save
redirect_to #post
else
render :new
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update_attributes(update_params)
redirect_to #post
else
render :edit
end
end
private
def update_params
params.require(:post).permit(:caption, :image)
end
def create_params
params.require(:post).permit(:caption, :user_id, :image)
end
end
you can create a controller like this
class FollowingPostsController < ApplicationController
def index
#posts = current_user.following_posts
end
end
and in your User model
class User < ActiveRecord::Base
def following_posts
#assuming that following_users returns the list of following users
self.following_users.map{ |user| user.posts }.flatten(1)
end
end
Or you can get the list of posts with :
Post.where(user_id: self.following_users.ids)
I'm trying to add authorization to my rails app and want to redirect a non-user to root_url when they try to access posts/new, using rescue_from. However, there is no redirect to root or error message being displayed and I'm not sure why.
This is my application_controller.rb
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
rescue_from Pundit::NotAuthorizedError do |exception|
redirect_to root_url, alert: exception.message
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
end
end
This is application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
#user = user
#record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
user.present?
end
def new?
create?
end
def update?
user.present? && (record.user == user || user.admin?)
end
def edit?
update?
end
def destroy?
update?
end
def scope
record.class
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
#user = user
#scope = scope
end
def resolve
scope
end
end
end
This is post_policy.rb
class PostPolicy < ApplicationPolicy
def new
#post = Post.new
authorize #post
end
end
This is posts_controller.rb
class PostsController < ApplicationController
def index
#posts = Post.all
end
def show
#ApplicationController::Find
#post = Post.find(params[:id])
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(params.require(:post).permit(:title, :body))
if #post.save
flash[:notice] = "Post was saved."
redirect_to #post
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update_attributes(params.require(:post).permit(:title, :body))
flash[:notice] = "Post was updated."
redirect_to #post
else
flash[:error] = "There was an error saving the post. Please try again."
end
end
end
The issue was that I defined another new method in the post_policy.rb file, overwriting the new method in application_policy.rb. I also didn't include authorize #post in the new method in the posts_controller.rb file.
In my rails application I have made three models, User, Group and Post.
I am trying to make it so that #post.group is equal to #group.id
The post is posted from a render inside of the group#show controller and then redirects itself to the post#create controller. How do I set the #post.group to #group.id?
GroupsController
class GroupsController < ApplicationController
before_action :set_group, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#groups = Group.all
respond_with(#groups)
end
def show
#group_id = #group.id
respond_with(#group)
end
def new
#group = Group.new
respond_with(#group)
end
def edit
end
def create
#group = Group.new(group_params)
#group.save
respond_with(#group)
end
def update
#group.update(group_params)
respond_with(#group)
end
def destroy
#group.destroy
respond_with(#group)
end
private
def set_group
#group = Group.find(params[:id])
end
def group_params
params.require(:group).permit(:name, :description, :motto, :usercount, :group, :id, :groupid)
end
end
PostsController
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
#posts = Post.all
respond_with(#posts)
end
def show
respond_with(#post)
end
def new
#post = Post.new
respond_with(#post)
end
def edit
end
def create
#post.group = #group_id
#post = Post.new(post_params)
#post.save
respond_with(#post)
end
def update
#post.update(post_params)
respond_with(#post)
end
def destroy
#post.destroy
respond_with(#post)
end
private
def set_post
#post = Post.find(params[:id])
end
def set_group
#group = Group.find(params[:id])
end
def post_params
params.require(:post).permit(:body, :group, :id)
end
def group_params
params.require(:group).permit(:id, :groupid, :group)
end
end
PostModel
class Post < ActiveRecord::Base
belongs_to :group
end
GroupsModel
class Group < ActiveRecord::Base
has_many :posts
end
The current code that I have returns the error undefined methodgroup=' for nil:NilClass`
Any help is appreciated!
You should start from creating Post instance, because you don't do this. I would do it like this:
def create
#post = #group.posts.build(post_params)
if #post.save
# handle success
else
# handle error
end
end
What's more, you should set before_action :set_group in your PostsController.
I would like to create relationships between three models: user, post and comment.
User have many posts and comments
Post have only one user and many comments
Comment have one user and one post
so i create next migrations:
class Users < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
class Posts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :content
t.integer :user_id
t.timestamps
end
end
end
class Comments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :title
t.string :content
t.integer :user_id
t.integer :post_id
t.timestamps
end
end
end
=============================================
models are next:
user.rb
class User < ActiveRecord::Base
has_many :posts
has_many :comments
end
post.rb
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
end
comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
===============================================
My users_controller.rb
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
#posts = #user.posts.paginate(page: params[:page])
#comments = #user.comments.paginate(page: params[:page])
end
def new
#user = User.new(params[:user])
end
def edit
##user = User.find(params[:id])
end
def update
##user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
now i want to create some actions for next tasks:
For posts_controller.rb
1.1 create a post by user
1.2 delete a post by user
1.3 show user post with all comments
1.4 show all user posts
class PostsController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
#post = user.post.build(post_params)
#post = post.save
end
def destroy
#post.destroy
end
def show_user_post_with_all_comments
???
end
def show_all_user_posts
???
end
private
def post_params
params.require(:post).permit(:title, :content)
end
def correct_user
#post = current_user.posts.find_by(id: params[:id])
redirect_to root_url if #post.nil?
end
end
For comments_controller.rb
2.1 create a comment by user in post
2.2 delete a comment by user in post
2.3 show all user comments
2.4 find and show a post by user comment
class CommentsController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
#comment = user.comment.build(comment_params)
#comment = comment.save
end
def destroy
#comment.destroy
end
def show_comment
???
end
def show_all_user_comments
???
end
def find_and_show_post_by_user_comment
???
end
private
def comment_params
params.require(:comment).permit(:content)
end
def correct_user
#comment = current_user.comments.find_by(id: params[:id])
redirect_to root_url if #comment.nil?
end
end
Pls check for correct my migrations and models and help me with creating of actions with "???" in bodies
Thank you much for your answers.
PostsController
def show_user_post_with_all_comments
#post = Post.find(params[:id]).eager_load(:comments)
end
def show_all_user_posts
#posts = current_user.posts
end
CommentsController
def show_comment
#comment = Comment.find(params[:id])
end
def show_all_user_comments
#comments = current_user.comments
end
def find_and_show_post_by_user_comment
#comment = Comment.find(params[:id]).eager_load(:post)
#post = #comment.post
end
What I've done in the past in a similar situation would be to put all this work in the UsersController and add a few new actions to it:
class UsersController < ApplicationController
...
def new_post
#user = User.find(params[:id])
end
def create_post
#user = User.find(params[:id])
if #user.update_attributes user_post_params
redirect_to somewhere_path
else
render 'new_post'
end
end
def show_post
#post = Post.find(params[:id])
# Not sure how you are implementing sessions, but say you have current_user defined
# for sessions, then your view could have a delete link conditional on
# #post.user_id == current_user.id
#comments = #post.comments
end
def show_all_posts
#user = User.find(params[:id])
#posts = #user.posts
end
def new_comment
#user = current_user
#post = Post.find(params[:id])
end
def create_comment
#user = current_user
#post = Post.find(params[:id])
#comment = Comment.new(comment_params)
if #post.update_attributes comment_params
#user.comments << #comment
if #user.save
redirect_to somewhere
else
render 'new_comment'
end
else
render 'new_comment'
end
end
def show_comments
#user = User.find(params[:id])
#comments = #user.comments
end
...
private
def user_post_params
params.require(:user).permit(:id, posts_attributes: [:title, :content])
end
def comment_params
params.require(:post).permit(:id, comments_attributes: [:content, :user_id])
end
In show_post.html.erb:
<% if #post.user_id == current_user.id %>
<%= link_to 'delete', post, method: :delete, data: { confirm: "you sure?" }
<% end %>
in your routes.rb:
get '/user/:id/new_post' => 'users#new_post', as: :user_new_post
put '/user/:id/create_post' => 'test_takers#create_post', as: :user_create_post
...and similar lines for the other actions.
Hopefully this can get you started...
I am new in rails and I am getting ActiveModel::ForbiddenAttributesError. This is my controller for nested resource:
class PostsController < ApplicationController
respond_to :html, :xml, :json
def index
#post=Post.all
end
def new
#user = User.find(params[:user_id])
#post = #user.posts.build
respond_with(#post)
end
def create
debugger
#user = User.find(params[:user_id])
#post = #user.posts.build(params[:post])
if #post.save
redirect_to user_posts_path
else
render 'new'
end
end
def post_params
params.require(:post).permit(:title, :description, {:user_ids =>[]})
end
end
If you have the following models:
post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
user.rb
class User < ActiveRecord::Base
has_many :posts
end
You don't actually need to use nested attributes, just do the following in your controller:
class PostsController < ApplicationController
respond_to :html, :xml, :json
def index
#post = Post.all
end
def new
#post = Post.new
respond_with(#post)
end
def create
#user = User.find(params[:user_id])
#post = #user.posts.new(post_params) # This will automatically set user_id in the post object
if #post.save
redirect_to user_posts_path
else
render 'new'
end
end
def post_params
params.require(:post).permit(:title, :description)
end
end
Although I don't recommend that you user a user_id param in the url. Have a look at the devise gem to handle authentication.