I want to allow the admin to review the description. So, whenever user posts the description admin can either approve or reject it. If approved it'll display on the index page. At the moment the user can add the description but it can't be reviewed by admin. Is there any way I could do this?
index.html.erb
<% #posts.each do |post| %>
<p> <%= post.description %> </p>
<% end %>
admin/post.rb
ActiveAdmin.register Post do
permit_params :description
index do
id_column
column :description
end
form do |f|
f.inputs do
f.input :description
end
f.actions
end
end
add new boolean field to post called reviewed with default value false:
class AddReviewedToPosts < ActiveRecord::Migration
def self.up
add_column :posts, :reviewed, :boolean, default: false
end
def self.down
remove_column :posts, :reviewed
end
end
then create on AA under index page a button the set it as reviewed:
index do
id_column
column :description
column "" do |post|
link_to 'Mark as reviewed', admin_posts_reviewed_path(post)
end
end
then the last thing create a reviewed action on admin/posts.rb:
def reviewed
#post = Post.find(params[:id])
if #post.present?
#post.update_attribute(:reviewed, true)
flash[:notice] = 'Post marked as reviewed'
else
flash[:error] = 'Could not find post'
end
redirect_to admin_posts_path
end
don't forget to add the action to routes.rb!
now you can display it if the boolean field is true.
code is not tested this is from my head.
Related
I have two associated models: Job and Candidate. The Candidate model is updated when a user applies to a job listing through the candidates 'new' view. Since I've associated Candidate with the Job model, I can't save any new instances of Candidate. I know that I have to pass job_id as a parameter so that any new instance of Candidate references a particular Job, but I just cant figure out what I'm doing wrong. Also, the Job model is associated with the Devise User model, but Candidate is not associated with the User model. Could that be the issue? Thanks in advance.
I've tried a ton of things in my candidates controller, but now I've put it back to how it was before I associated the Candidate model with Job model, so I can start over again as if I just ran the migration to AddJobToCandidate
candidates_controller.rb
class CandidatesController < ApplicationController
def index
#candidates = Candidate.all
end
def new
#candidate = Candidate.new
render layout: false
end
def single
#candidate = Candidate.find(params[:id])
end
def create
#candidate = Candidate.new(candidate_params)
if #candidate.save
redirect_to root_path
else
render "new"
end
end
private
def candidate_params
params.require(:candidate)
.permit(:first_name, :last_name, :email, :cover_letter, :ph, :job_id)
end
end
views/candidates/new.html.erb
<h1>Work at <%= current_user.company %></h1>
<%= simple_form_for #candidate do |form| %>
<%= form.input :first_name, label: "First Name" %>
<%= form.input :last_name, label: "Last Name" %>
<%= form.input :email, label: "Email" %>
<%= form.input :cover_letter, label: "Cover Letter" %>
<%= form.input :ph, label: "Phone Number" %>
<%= form.button :submit %>
<% end %>
routes.rb
Rails.application.routes.draw do
get 'candidates/index'
get 'candidates/new/:id' => 'candidates#new', :as => 'apply'
get 'candidates/single/:id' => 'candidates#single', :as => 'viewcandidate'
get 'jobs/index'
get 'jobs/new'
get 'jobs/listing/:id' => 'jobs#listing', as: 'listing'
get 'jobs/listings', :as => 'careerpage'
get 'jobs/dashboard'
get 'jobs/single/:id' => 'jobs#single', :as => 'viewjob'
devise_for :users, controllers: { sessions: "users/sessions" }
resources :candidates
resources :jobs
root 'jobs#dashboard'
end
views/jobs/listing.html.erb the only view that links to candidates/new.html/erb
<h1><%= #job.title %></h1>
<p><%= #job.description %></p>
<p><%= link_to "Apply", apply_path(#job.id) %></p>
Candidate/Job association migration
class AddJobToCandidate < ActiveRecord::Migration[5.2]
def change
add_reference :candidates, :job, foreign_key: true
end
end
jobs_controller.rb (don't think this is necessary but I'll include anyway)
class JobsController < ApplicationController
before_action :authenticate_user!
def index
#jobs = current_user.jobs.all
end
def dashboard
end
def new
#job = Job.new
end
def listing
#job = Job.find(params[:id])
render layout: false
end
def listings
#jobs = current_user.jobs.all
render layout: false
end
def single
#job = Job.find(params[:id])
#candidates = Candidate.all
end
def create
#job = current_user.jobs.new(job_params)
if #job.save
redirect_to jobs_index_path
else
render "new"
end
end
private
def job_params
params.require(:job)
.permit(:title, :description, :url, :user_id)
end
end
No error is shown, but model is not updated.
One of the things I tried in candidate_controller #create action was:
def create
#candidate = #job.candidates.create(candidate_params)
if #candidate.save
redirect_to root_path
else
render "new"
end
end
and the error I get is 'undefined method `candidates' for nil:NilClass'
Another thing I tried was adding this line in the #create action:
#job = Job.find(params[:id])
and the error I get is 'Couldn't find Job without an ID'
When you arrive at candidate#new you’re just discarding the Job ID. You’re not making it part of the data submitted by the form to be picked up in the create controller.
Given you have completely abandoned RESTful routes, the quickest solution would be to add this to the form:
<%= form.hidden_field :job_id, value: params[:id] %>
However, I highly recommend you look at RESTful routes and nested resources. You have a mess where the ID passed to Candidate#new is the ID of a different model. While you’re at it you may want to reconsider having a candidate belong to a job, what happens when a candidate is interested in multiple jobs? They create a new profile each time? In job sites one would normally have a Job, a Candidate (or User / Profile) and then a JobApplication, which joins the two.
What I want to achieve is that list each member with schools and thereafter list Schools with all belonging members. Schools can have many members and members can have many schools also. I have the following set up in the system, but have problems finding the solution for it. Here it is how my code looks like:
controller:
class MembersController < ActionController::Base
before_action :set_school
def index
#members = Member.all
end
def new
#member = Member.new
end
def create
#member = Member.new(member_params)
#member.school = #school
#member.save
redirect_to members_path
end
private
def set_school
#school = School.find(params[:school])
end
def member_params
params.require(:member).permit(:name, :email,:school)
end
end
This is my route:
Rails.application.routes.draw do
get 'schools/index'
resources :members
resources :school
end
My view looks like:
<% #members.each do |member| %>
<%= member.name %>
<%= member.email %>
<%= member.school %>
<% end %>
model for members:
class CreateMembers < ActiveRecord::Migration[5.0]
def change
create_table :members do |t|
t.string :name
t.string :email
t.timestamps
end
end
my School model :
class CreateSchools < ActiveRecord::Migration[5.0]
def change
create_table :schools do |t|
t.string :name
t.timestamps
end
and the reference:
class AddSchoolRefToMembers < ActiveRecord::Migration[5.0]
def change
add_reference :members, :school, foreign_key: true
end
Any help would be great! Thank you!
You have set before_action for all actions in controller. For, index and new there is no school_id, so you have to run before_action only for create.
Change below code
before_action :set_school
to
before_action :set_school, only: ['create']
<%= simple_form_for [#member] do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= f.collection_select :school_id, School.all, :id, :name %>
<%= f.submit %>
<% end %>
Change the strong params
def member_params
params.require(:member).permit(:name, :email, :school_id)
end
And you can remove the before_action :set_school
Also you need to change the action as school_id is already in params
def create
#member = Member.create(member_params)
redirect_to members_path
end
#imocsari to get the name of school change your view like
<% #members.each do |member| %>
<%= member.name %>
<%= member.email %>
<%= member.school.try(:name) %>
<% end %>
member.school will give you associated school of member with all column, if you want to show name of school this is way member.school.try(:name) or member.school.name
member.school.try(:name) this will return nil if there is not any school for member, It will by pass exception
member.school.name this will raise error if there is not any school for member.
I'm trying to do a simple task : I created a "magazine" scaffold, but I want it to have a specific relation : a user can have participate for the creation / redaction of a magazine, and it can take several users to create a magazine.
I checked the APIDock and did the following:
Specified the relation between the magazines and the users
model/magazine.rb
class Magazine < ApplicationRecord
mount_uploader :thumbnail, ThumbnailUploader
has_and_belongs_to_many :users
end
model/user.rb
class User < ApplicationRecord
has_and_belongs_to_many :magazines
# More code...
end
Created a migration to add a table to link both the models
class ManyToMany < ActiveRecord::Migration[5.0]
def change
create_table :magaziness_users, :id => false do |t|
t.integer :user_id
t.integer :magazine_id
end
add_index :magazines_users, [:magazine_id, :user_id]
end
end
Then I ran the migration
Added the list of all users ever recorded to the database to create a dropdown
<div class="field">
<%= f.label :users %>
<%= f.select :users, User.all_except(current_user).collect {|u| [u.username, u]}, {prompt: 'Add a creator?'}, { :multiple => true, :size => 3 } %>
</div>
But, when I'm saving a new magazine, the user doesn't get saved, and the "magazines_user remains empty.
edit 1
This is an auto-generated controller, since I use the scaffold command to create it. I didn't touch anything excepted the set_magazine function, where I added the Friendly_Id
class MagazinesController < ApplicationController
before_action :set_magazine, only: [:show, :edit, :update, :destroy]
def index
#magazines = magazine.all
end
def show
end
def new
#magazine = magazine.new
end
def edit
end
def create
#magazine = magazine.new(magazine_params)
if #magazine.save
redirect_to #magazine, notice: 'magazine was successfully created.'
else
render :new
end
end
def update
if #magazine.update(magazine_params)
redirect_to #magazine, notice: 'magazine was successfully updated.'
else
render :edit
end
end
def destroy
#magazine.destroy
redirect_to magazines_url, notice: 'magazine was successfully destroyed.'
end
private
def set_magazine
#magazine = magazine.friendly.find(params[:id])
end
def magazine_params
params.require(:magazine).permit(:titre, :description, :apercu, :users)
end
end
Did I forget any step?
so here is the answer with my code working:
I did two scaffolds:
rails generate scaffold user username:string email:uniq password:digest
rails generate scaffold magazine title:string description:text preview:string
Then added this to magazine migration:
create_table :magazines_users, id: false do |t|
t.belongs_to :magazine, index: true
t.belongs_to :user, index: true
end
In my form, I added:
<div class="field">
<%= f.label :users %>
<%= f.select :user_ids, User.all.collect { |u| [u.username, u.id] }, {include_blank: true}, {multiple: true} %>
</div>
And in my magazines controller I only modified magazine_params:
def magazine_params
params.require(:magazine).permit(:title, :description, :preview, :user_ids => [])
end
To see that it works, I added this in magazin show view:
<p>
<strong>Users:</strong>
<%= #magazine.users.map(&:username).join(" - ") %>
</p>
Of course I added "has_and_belongs_to_many" as you did in User and Magazine models.
And that's it :)
Tested with Rails 5 and it works just fine. :)
Also I strongly advice you to take a look at the simple_form gem. It has some great methods to handle associations (like has_and_belongs_to_many) easily, like this : <%= f.association :users, collection: User.all_except(current_user).order(:username) %>
Update: I've been trying to debug my files, so most of the files have changed recently
I am getting a strange error when trying to use a "new" action to my items_controller. Essentially, a wishlist has_many items and an item belongs_to wishlist. The error message is as follows:
Code
Here is my items_controller:
class ItemsController < ApplicationController
def show
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
def create
#item = Item.new(item_params)
if #item.save
redirect_to "/wishlist", :notice => "Success!"
else
redirect_to "/wishlist", :notice => "Failure, try again later!"
end
end
def edit
#item = Item.find(params[:id])
end
def update
#item = Item.find(params[:id])
if #item.update_attributes(item_params)
redirect_to(:action => 'show', :id => #item.id)
else
render 'edit'
end
end
private
def item_params
params.require(:item).permit(:name,:size,:qty,:priority)
end
private
def create_params
params.require(:item).permit(:name,:size,:qty,:priority,:wishlist_id)
end
end
And my routes.rb:
Rails.application.routes.draw do
get '/wishlist' => 'wishlists#index', as: :wishlists
get '/wishlist/:id' => 'wishlists#show', as: :wishlist
get '/wishlist_items/new' => 'items#new'
get '/wishlist_items/:id' => 'items#show', as: :items
get '/wishlist_items/:id/edit' => 'items#edit', as: :edit_items
patch '/wishlist_items/:id' => 'items#update'
resources :items
And finally, my new.html.erb for the items model:
<h1>New Item</h1>
<div class="wishlist-new">
<% if true %>
<%= form_for(#item) do |f| %>
<%= f.text_field :name, :placeholder => "Name" %>
<%= f.text_field :size, :placeholder => "Specifications" %>
<%= f.text_field :qty, :placeholder => "Quantity" %>
<%= f.text_field :priority, :placeholder => "Priority" %>
<%= f.text_field :id, :placeholder => "Wishlist ID" %> # changing :id to :wishlist_id doesn't seem to do anything
<%= f.submit "Create Item", class: "btn-submit" %>
<% end %>
<% end %>
</div>
My migration files (so you know how my databases are structured:
# Migration file for items
class CreateItems < ActiveRecord::Migration
def change
drop_table :items
create_table :items do |t|
t.string :name
t.string :size
t.string :qty
t.integer :priority
t.references :wishlist
t.timestamps
end
end
end
# Migration File for Wishlists
class CreateWishlists < ActiveRecord::Migration
def change
drop_table :wishlists
create_table :wishlists do |t|
t.string :title
t.timestamps
end
end
end
Attempts to Debug
It seems like the routes.rb is sending requests to different methods in the items_controller because the error seems to say that /wishlist_items/new is accessing a show method even though its new method takes priority. To support this, the page loads properly when I comment out get '/wishlist_items/:id' => 'items#show', as: :items in the routes file. What happens is the page loads properly, and the Item is created properly (when I fill out the form) except that when I go into the console, it says that the Item created has a property of wishlist_id: nil even though I specified for it to be 1 in the form.
The method mentioned above has two problems: (1) it doesn't work entirely correctly, and (2) it becomes impossible to show a specific Item in the wishlist.
The error occurs before the inner section of the form_for is loaded, so the problem either is (a) a weird routing thing (as mentioned above) or (b) something weird happening to the #item variable.
Thanks in advance!
I am new to ruby on rails,and I am learning by creating a blog. I am not able to save to my blogs table and I get this error "can't write unknown attribute url"
Blogs migration: db/migrate/
class CreateBlogs < ActiveRecord::Migration
def change
create_table :blogs do |t|
t.string :title
t.text :description
t.string :slug
t.timestamps
end
end
end
Blogs Model: /app/models/blogs.rb
class Blogs < ActiveRecord::Base
acts_as_url :title
def to_param
url
end
validates :title, presence:true
end
Blogs Controller: /app/controllers/blogs_controller.rb
class BlogsController < ApplicationController
before_action :require_login
def new
#blogs = Blogs.new
end
def show
#blogs = Blogs.find_by_url(params[:id])
end
def create
#blogs = Blogs.new(blogs_params)
if #blogs.save
flash[:success] = "Your Blog has been created."
redirect_to home_path
else
render 'new'
end
end
def blogs_params
params.require(:blogs).permit(:title,:description)
end
private
def require_login
unless signed_in?
flash[:error] = "You must be logged in to create a new Blog"
redirect_to signin_path
end
end
end
Blogs Form:/app/views/blogs/new.html.erb
Blockquote
<%= form_for #blogs, url: blogs_path do |f| %><br/>
<%= render 'shared/error_messages_blogs' %><br/>
<%= f.label :title %><br/>
<%= f.text_field :title %><br/>
<%= f.label :description %><br/>
<%= f.text_area :description %><br/>
<%= f.submit "Submit Blog", class: "btn btn-large btn-primary" %><br/>
<% end %><br/>
and I have also added "resources :blogs" to my routes.rb file.
I get this error in controller at
if #blogs.save
The error states exactly what your issue is: "can't write unknown attribute url" Implies that the url variable you are trying to access in def to_params of your Blogs model to which is unknown as you wish to store this in slug. The acts_as_url method is added and used by the stringex gem and because you aren't getting an error regarding an unknown method acts_as_url, the gem must successfully be installed, just misconfigured.
Looking further into the documentation for the gem, the gem sets the value of the url to a db column that should already exists in your model. From your database schema, the url should use the column slug and not url (the default of stringex). Changing your Blogs Class to the following should fix the issue:
class Blogs < ActiveRecord::Base
acts_as_url :title, url_attribute: :slug
def to_param
slug
end
validates :title, presence:true
end