uninitialized constant PostsController::Post - ruby-on-rails

/config/routes.rb
Rails.application.routes.draw do
devise_for :users
root 'posts#hello'
resources :users
resources :posts
end
/app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_filter :authenticate_user! , except: [:hello]
def hello
end
def new
end
def create
#post = Post.create(inner)
redirect_to post_path(#post.id)
end
def index
#posts = Post.all.order('id desc')
end
def show
#post = Post.find_by(id: params[:id])
end
private
def inner
params.require(:post).permit(:title, :desc)
end
end
When I click posts_path link, I get an error: uninitialized constant PostsController::Post app/controllers/posts_controller.rb, line 17
def index
#posts = Post.all.order('id desc')
end
Whats wrong?
UPD
class Post < ActiveRecord::Base
belongs_to :user
validates :desc, presence: true
validates :title, presence: true, length: { maximum: 45 }
end
UPD2
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.string :desc
t.timestamps
end
end
end

As per Rails convention model names should be singular. So, model Post would be located under folder app/models and named post.rb and NOT Posts.rb. You are getting the error because Rails would look for a file named post.rb by convention and if not found it throws the error.

Related

association between two model in rails , controller

I can not find the issue with my association, but continuously getting error related to the association. I added has_many to Schools and belongs_to to members.
class CreateMembers < ActiveRecord::Migration[5.0]
def change
create_table :members do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
class CreateSchools < ActiveRecord::Migration[5.0]
def change
create_table :schools do |t|
t.string :name
t.timestamps
end
end
end
class AddSchoolRefToMembers < ActiveRecord::Migration[5.0]
def change
add_reference :members, :school, foreign_key: true
end
end
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
Instead of assigning the #school itself you should assign the id of that school:
def create
#member = Member.new(member_params)
#member.school = #school.id # here it is #school.id
#member.save
redirect_to members_path
end
The associations work with IDs not Arrays.
#school return the school record completely you just need the id to create the association.

Active Admin Name Error uninitializedconstant Resource::Users

So I have a couple of models in my app and they are all registered with ActiveAdmin. They all work great except for one and I can't figure out why. I keep getting the same error:
NameError at /admin/reports
uninitialized constant Report::Users
The model that it is happening on is called Report
class Report < ActiveRecord::Base
belongs_to :users
belongs_to :cars
enum reason: [:accident,:totaled,:stolen]
validates :reason, presence:true
end
The controller looks like this:
Class ReportsController < ApplicationController
before_action :authenticate_user!
def create
#car=Car.find(params[:car_id])
#report=#car.reports.build(report_params)
#report.user_id=current_user.id
#report.car_id=#car.id
if #report.save
redirect_to car_path(car)
else
render 'new'
end
end
def destroy
#report=Report.find(params[:id])
#report.destroy
end
private
def report_params
params.require(:report).permit(:reason)
end
end
This is the migration used to create the model:
class CreateReports < ActiveRecord::Migration
def change
create_table :reports do |t|
t.references :user, index: true
t.references :car, index: true
t.integer :reason, default: 0
t.timestamps null: false
end
add_foreign_key :reports, :users
add_foreign_key :reports, :cars
end
end
Lastly here is the active_admin app/admin/report.rb:
ActiveAdmin.register Report do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# permit_params :list, :of, :attributes, :on, :model
#
# or
#
# permit_params do
# permitted = [:permitted, :attributes]
# permitted << :other if resource.something?
# permitted
# end
end
I have been trying to figure it out for a couple of hours. Solutions that I saw on SO that don't work. I ran rails generate active_admin:resource Report to create it so it is singular. Why is it misbehaving?
NameError at /admin/reports uninitialized constant Report::Users
Association name for a belongs_to should be singular as per naming conventions.
class Report < ActiveRecord::Base
belongs_to :user #here
belongs_to :car #and here too
enum reason: [:accident,:totaled,:stolen]
validates :reason, presence:true
end

How to access current_user variable in controller or model?

I have 1:N relationship between user and post model. I want to access user_id in post model. I tried it by accessing current_user but it's throwing cannot find current_user variable.
My userModel class:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :validatable
has_many :post
validates_format_of :email, with: /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
end
MyPostModel class:
class Post < ActiveRecord::Base
belongs_to :user
before_create :fill_data
validates_presence_of :name, :message => 'Name field cannot be empty..'
def fill_data
self.is_delete = false
self.user_id = current_user # here I am getting the error
end
end
MyPostController class
class PostController < ApplicationController
before_action :authenticate_user!
def index
#post = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to action: 'index'
else
render 'new'
end
end
.....
private
def post_params
params.require(:post).permit(:name,:user_id,:is_delete)
end
end
I can access the before_action :authenticate_user! in Post controller but not current_user in post model or controller. What I am doing wrong here in Post.fill_data. self.user_id?
Rest of the code is working fine and I can see the new entry of :name and :is_delete in sqlite3 database (when I am commenting self.user_id line in Post class).
Edit-1
I already have migration class for post
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :name
t.boolean :is_delete
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
In Rails your models should not be aware of the apps current user or any other state. They only need to know about themselves and the objects they are directly related to.
The controller on the other hand is aware of the current user.
So the proper way to do this would be to remove the fill_data callback from Post. And do it in the controller:
class PostController < ApplicationController
before_action :authenticate_user!
def index
#post = Post.all
end
def new
#post = current_user.posts.build
end
def create
#post = current_user.posts.build(post_params)
if #post.save
redirect_to action: 'index'
else
render 'new'
end
end
private
def post_params
params.require(:post).permit(:name,:user_id,:is_delete)
end
end
You should also set the default for your is_delete column in the database instead, but if you want to rock it like a pro use an enum instead.
Create a migration rails g migration AddStateToUsers and fill it with:
class AddStateToUsers < ActiveRecord::Migration
def change
add_column :users, :state, :integer, default: 0
remove_column :users, :is_delete
add_index :users, :state
end
end
We then use the rails enum macro to map state to a list of symbols:
class Post
enum state: [:draft, :published, :trashed]
# ...
end
That lets you do Post.trashed to get all posts in the trash or post.trashed? to check if a specific post is trashed.
notice that I use trashed instead of deleted because ActiveRecord has build in deleted? methods that we don't want to mess with.
You are trying to add current_user.id in post model using before_create call back. but better to do is use this
In posts_controller.rb
def new
#post = current_user.posts.new
end
def create
#post = current_user.posts.create(posts_params)
end
This will create a post for the current user.
Your fill_data method would be
def fill_data
self.is_delete = false
end

Rails polymorphic # mentions create action

I'm trying to create a simple # mentions model similar to twitters for my app. I've started building it, but I don't know how I would handle the actual creation of the mention. I need some way to scan let's say a status before it's created for any # symbols, then checking the text following against the database for any matching usernames. If there's a match then a mention gets created along with the status. Can someone point me in the right direction?
Here's what I have so far:
db/migrate/create_mentions.rb
class CreateMentions < ActiveRecord::Migration
def change
create_table :mentions do |t|
t.belongs_to :mentionable, polymorphic: true
t.timestamps
end
add_index :mentions, [:mentionable_id, :mentionable_type]
end
end
models/mention.rb
class Mention < ActiveRecord::Base
belongs_to :mentionable, polymorphic: true
end
models/status.rb
class Status < ActiveRecord::Base
attr_accessible :content
has_many :mentions, dependent: :destroy
end
models/member.rb
class Member < ActiveRecord::Base
has_many :mentions, as: :mentionable, dependent: :destroy
end
controllers/mentions_controller.rb
class MentionsController < ApplicationController
before_filter :authenticate_member!
before_filter :load_mentionable
before_filter :find_member
def new
#mention = #mentionable.mentions.new
end
def create
#mention = #mentionable.mentions.new(params[:mention])
respond_to do |format|
if #mention.save
format.html { redirect_to :back }
else
format.html { redirect_to :back }
end
end
end
private
def load_mentionable
klass = [Status].detect { |c| params["#{c.name.underscore}_id"] }
#mentionable = klass.find(params["#{klass.name.underscore}_id"])
end
def find_member
#member = Member.find_by_user_name(params[:user_name])
end
end
config/routes.rb
resources :statuses do
resources :mentions
end
Thanks to this question: parse a post for #username I was able to get this working. My set up:
db/migrate/create_mentions.rb
class CreateMentions < ActiveRecord::Migration
def change
create_table :mentions do |t|
t.belongs_to :mentionable, polymorphic: true
t.belongs_to :mentioner, polymorphic: true
t.integer :status_id
t.integer :comment_id
t.timestamps
end
add_index :mentions, [:mentionable_id, :mentionable_type], :name => "ments_on_ables_id_and_type"
add_index :mentions, [:mentioner_id, :mentioner_type], :name => "ments_on_ers_id_and_type"
end
end
models/mention.rb
class Mention < ActiveRecord::Base
attr_accessible :mentioner_id, :mentioner_type, :mentionable_type, :mentionable_id, :status_id, :comment_id
belongs_to :mentioner, polymorphic: true
belongs_to :mentionable, polymorphic: true
end
models/member.rb
class Member < ActiveRecord::Base
has_many :mentions, as: :mentionable, dependent: :destroy
end
models/status.rb
class Status < ActiveRecord::Base
attr_accessor :mention
has_many :mentions, as: :mentioner, dependent: :destroy
after_save :save_mentions
USERNAME_REGEX = /#\w+/i
private
def save_mentions
return unless mention?
people_mentioned.each do |member|
Mention.create!(:status_id => self.id, :mentioner_id => self.id, :mentioner_type => 'Status', :mentionable_id => member.id, :mentionable_type => 'Member')
end
end
def mention?
self.content.match( USERNAME_REGEX )
end
def people_mentioned
members = []
self.content.clone.gsub!( USERNAME_REGEX ).each do |user_name|
member = Member.find_by_user_name(user_name[1..-1])
members << member if member
end
members.uniq
end
end
config/routes.rb
resources :statuses do
resources :mentions
end
helpers/mentions_helper.rb
module MentionsHelper
def statuses_with_mentions(status)
status.content_html.gsub(/#\w+/).each do |user_name|
member = Member.find_by_user_name(user_name[1..-1])
if member
link_to user_name, profile_path(member.user_name)
else
user_name
end
end
end
end

Why am I getting an infinite loop with pg_search?

When I point my browser at http://localhost:3000/searches, I get the following error:
Error 324 (net::ERR_EMPTY_RESPONSE): The server closed the connection without sending any data.
Why? And how do I fix this?
Relevant code below...
/config/routes.rb:
resources :searches, :only => [:index]
/app/controllers/searches_controller.rb:
class SearchesController < ApplicationController
respond_to :html
filter_access_to :all
def index
#term = params[:term]
#results = PgSearch.multisearch(#term) unless #term.blank?
redirect_to searches_path
end
end
/app/views/searches/index.html.haml:
.textbox
= render "shared/notice"
%h1 Advanced Search
= simple_form_for #searches do |f|
= f.input :term
= f.button :submit
- unless #results.blank?
- #results.each do |result|
%h3= result.searchable.header
%p= result.searchable.body
/config/authorization_rules.rb:
authorization do
role :admin do
has_permission_on [...snip... :searches], :to => [:index, :show, :new, :create, :edit, :update, :destroy, :print, :none, :audit]
end
end
/app/models/reference.rb:
class Reference < ActiveRecord::Base
has_paper_trail
include PgSearch
multisearchable :against => [:source_text, :citation]
attr_accessible :reference_ids, :question_ids
attr_accessible :url, :citation, :details, :veracity_id, :original, :source_text
has_many :footnotes
def header
self.citation
end
def body
self.details
end
end
/app/models/footnote.rb:
class Footnote < ActiveRecord::Base
has_paper_trail
include PgSearch
multisearchable :against => [:details]
attr_accessible :reference_id, :details, :page_range, :relevant
belongs_to :reference
def header
[self.reference.citation, " ", self.page_range].join
end
def body
self.details
end
end
/db/migrate/20130326110126_create_pg_search_documents.rb:
class CreatePgSearchDocuments < ActiveRecord::Migration
def self.up
say_with_time("Creating table for pg_search multisearch") do
create_table :pg_search_documents do |t|
t.text :content
t.belongs_to :searchable, :polymorphic => true
t.timestamps
end
end
end
def self.down
say_with_time("Dropping table for pg_search multisearch") do
drop_table :pg_search_documents
end
end
end
/db/migrate/20130326110723_rebuild_search_indexes.rb:
class RebuildSearchIndexes < ActiveRecord::Migration
def up
PgSearch::Multisearch.rebuild(Reference)
PgSearch::Multisearch.rebuild(Footnote)
end
def down
PgSearch::Reference.delete_all
PgSearch::Footnote.delete_all
end
end
You've got a cyclic redirect; redirect_to searches_path just sends the request back into the same action.
Try just taking the redirect_to line out. That way Rails will render app/views/searches/index.html.haml by default. Then posting to the form should request index again and produce what you want.

Resources