NoMethodError (undefined method `posts' for nil:NilClass) - ruby-on-rails

I'm very new to rails and was using the gem griddler to hopefully parse some incoming emails. I used all the code from the github site, and it provides an example emailprocessor.rb here:
class EmailProcessor
def initialize(email)
#email = email
end
def process
//re-done with help from #Kris
user = User.find_or_create_by(email: #email.from[:email]) do |u|
u.email = #email.from[:email]
u.name = #email.from[:name]
end
user.posts.create!(
subject: #email.subject,
body: #email.body,
attachment: #email.attachments,
from: #email.from[:email]
)
end
end
I know i need to declare posts somehow and somewhere, but I have looked around on here and on the rails site and havent found anything to help me create it. I get the error in the title when running heroku logs -t when the email server tries to post to the page.
here are the rest of my files that may be needed and what I've tried:
User.rb:
class User < ActiveRecord::Base
has_many :posts
end
Post.rb:
class Post < ActiveRecord::Base
belongs_to :user
end
create_posts.rb
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :subject
t.string :body
t.string :from
t.string :attachment
t.timestamps
end
end
end
users_controller.rb
class UserController < ApplicationController
def list
#users = User.find(:all)
end
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to :action => 'list'
else
render :action => 'new'
end
end
end
post_controller.rb
class PostController < ApplicationController
def list
#posts = Post.find(:all)
end
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
end
def edit
end
def create
#post = Post.new(params[:post])
if #post.save
redirect_to :action => 'list'
else
#post = Subject.find(:all)
render :action => 'new'
end
end
end
Any help is really appreciated, I'd like to know what I'm doing wrong so I can avoid it in the future

The e-mail address is not found in the database and therefor user is nil. You can create a user on the fly with the following code:
def process
user = User.find_or_create_by(email: #email.from[:email]) do |u|
# todo: set some other properties on the new user u, e.g. the name
end
user.posts.create!(
subject: #email.subject,
body: #email.body,
attachment: #email.attachments,
from: #email.from[:email]
)
end
See also ActiveRecord::Relation::find_or_create_by.

Related

undefined method `get_access_token' while implementing koala gem in rails app

I want to implement koala gem in rails app
But i am getting an error "undefined method get_access_token'
My facebook controller code is
class FacebookController < ApplicationController
before_filter :authenticate_user!
def index
unless current_user.facebook_oauth_setting
#oauth = Koala::Facebook::OAuth.new("app-id", "secret", "http://#{request.host}:#{request.port}/callback")
session["oauth_obj"] = #oauth
redirect_to #oauth.url_for_oauth_code
else
redirect_to "/facebook_profile"
end
end
def callback
unless current_user.facebook_oauth_setting
#oauth = session["oauth_obj"]
Rails.logger.info("**************#{#oauth}***************")
Rails.logger.info("**********#{params[:code]}*************")
FacebookOauthSetting.create({:access_token => #oauth.get_access_token(params[:code]), :user_id => current_user.id})
redirect_to "/facebook_profile"
else
redirect_to "/"
end
end
def facebook_profile
if current_user.facebook_oauth_setting
#graph = Koala::Facebook::API.new(current_user.facebook_oauth_setting.access_token)
#profile = #graph.get_object("me")
#picture = #graph.get_picture("me")
#feed = #graph.get_connections("me","feed")
#friends = #graph.get_connections("me", "friends")
else
redirect_to "/"
end
end
end
My model to store access token is
class TwitterOauthSetting < ActiveRecord::Base
belongs_to :user
end
My migration to store access_token is
class CreateFacebookOauthSettings < ActiveRecord::Migration
def change
create_table :facebook_oauth_settings do |t|
t.string :access_token
t.integer :user_id
t.timestamps null: false
end
end
end
Create the #oauth object inside the callback method rather than bringing it from the session. So do this:
#oauth = Koala::Facebook::OAuth.new("app-id", "secret", "http://#{request.host}:#{request.port}/callback")
FacebookOauthSetting.create(:access_token => #oauth.get_access_token(params[:code]), :user_id => current_user.id)
It should solve your problem.
type of object should be Koala::Facebook

Rails: Struggling with Associations (nested comments)

First off, I apologize for the amount of code and for what I'm asking. But I need help desperately. I can't wrap my head around this concept whatsoever.
I have a basic CRUD (projects) and I'm trying to nest another CRUD (discussions) to projects so that there can be a discussion for each project. Now, I have been trying to do this for five days straight. I can't figure it out for the life of me. I've read and researched everything there is to be read and researched. I can't figure it out on my own.
So, I've started fresh. I've set up a new project and got the basics, but I have no clue where to go from here. I would be so incredibly appreciative if someone could take the time to write me step by step instructions. Or, if you're able to do it quick, perhaps even finish my code for me? Because I'm going to have to do about 5 more of these, so if I were to have 1 fully completed one I could reference that would be so amazing.
projects_controller.rb
class ProjectsController < ApplicationController
def index
#projects = Project.all
end
def show
end
def new
#projects = Project.new
end
def create #no view
#projects = Project.new(project_params)
if #projects.save
redirect_to projects_path, :notice => "Your project was sent!"
else
render "new"
end
end
def edit
#projects = Project.find(params[:id])
end
def update #no view
#projects = Project.find(params[:id])
if #projects.update_attributes(project_params)
redirect_to projects_path, :notice => "Your project has been updated."
else
render "edit"
end
end
def destroy #no view
#projects = Project.find(params[:id])
#projects.destroy
redirect_to projects_path, :notice => "Your project has been deleted."
end
private
def project_params
params.require(:project).permit(:title, :description)
end
end
discussions_controller.rb
class DiscussionsController < ApplicationController
def index
#discussion = Discussion.all
end
def show
#discussions = Discussion.find(params[:id])
#projects = #discussions.Project.all
end
def new
#discussions = Discussion.new
end
def create #no view
#discussions = Discussion.new(discussion_params)
if #discussions.save
redirect_to discussions_path, :notice => "Your discussion was submitted."
else
render "new"
end
end
def edit
#discussions = Discussion.find(params[:id])
end
def update #no view
#discussions = Discussion.find(params[:id])
if #discussions.update_attributes(discussion_params)
redirect_to discussions_path, :notice => "Your discussion has been updated."
else
render "edit"
end
end
def destroy #no view
#discussions = Discussion.find(params[:id])
#discussions.destroy
redirect_to discussions_path, :notice => "Your discussions has been deleted."
end
private
def discussion_params
params.require(:discussion).permit(:title, :description)
end
end
routes.rb
Rails.application.routes.draw do
resources :homes
resources :projects
resources :discussions
root "homes#index"
Models:
discussion.rb
class Discussion < ActiveRecord::Base
belongs_to :project
end
project.rb
class Project < ActiveRecord::Base
has_many :discussions
end
Migrates:
_create_projects.rb
class CreateProjects < ActiveRecord::Migration
def change
create_table :projects do |t|
t.string :title
t.text :description
t.date :due_date
t.timestamps null: false
end
end
end
_create_discussions.rb
class CreateDiscussions < ActiveRecord::Migration
def change
create_table :discussions do |t|
t.string :title
t.text :description
t.timestamps null: false
end
end
end
_create_nested_discussions
class NestedDiscussion < ActiveRecord::Migration
def change
add_column :discussions, :project_id, :integer
end
end
One thing I noticed is that you don't permit project_id attribute in your strong parameters. So add :project_id in your params in discussions_controller.rb:
private
def discussion_params
params.require(:discussion).permit(:title, :description, :project_id)
end
You probably want your routes to be as such:
resources :projects do
resources :discussions
end

1v1 game system rails

I am a beginner with Rails so bear with me haha. I am trying to create a 1v1 type match system in Rails. The process I am trying to create is listed below with the current code I have attempted.
Allow user to create game.
Allow a different user to join that game.
If two users are in one match don't allow others to join.
Match model:
class Match < ActiveRecord::Base
belongs_to :user
end
Match controller:
class MatchesController < ApplicationController
before_filter :find_match, only: [:show, :join]
def index
#matches = Match.all
end
def new
#match = Match.new
end
def create
#match = current_user.matches.new(match_params)
if #match.save
redirect_to root_url, notice: 'created.'
else
render('new')
end
end
def join
if #match.update_attributes(:opponent_id => current_user.id)
redirect_to root_url, notice: 'joined.'
else
render('new')
end
end
private
def find_match
#match = Match.find(params[:id])
end
def match_params
params.require(:match).permit(:user_id, :opponent_id)
end
end
User model:
class User < ActiveRecord::Base
has_many :matches
end
Match migration:
create_table :matches do |t|
t.string :match_title
t.integer :user_id
t.integer :opponent_id
t.boolean :joinable
t.timestamps
Thank you.
Your code has some small error. In 'join' method you should change condition:
def join
if #match.joinable
#match.update_attributes(:opponent_id => current_user.id, :joinable => false)
redirect_to root_url, notice: 'joined.'
else
render('new')
end
end
And add one line to 'create' method:
def create
#match = current_user.matches.new(match_params)
#match.joinable = true
if #match.save
redirect_to root_url, notice: 'created.'
else
render('new')
end
end
Now, user can't join to matchs which has already 2 players.

rails 4. how to create actions using relationships between three models?

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...

rails:Sqlite:how to make date only with two foreign key?

One of my database table(feedback) have 2 key
class CreateFeedbacks < ActiveRecord::Migration
def change
create_table :feedbacks do |t|
t.string :strengths
t.string :weaknesses
t.string :recommendations
t.string :rating
t.integer :user_id
t.integer :subject_id
t.timestamps
end
end
end
I want one user to only have one feedback for one subject.How to add code
def create
#feedback = Feedback.new(params[:feedback])
#feedback.user_id=current_user.id
if #feedback.save
flash[:success] = "Welcome #{current_user.name}!"
redirect_to #feedback
else
render 'new'
end
end
class FeedbacksController < ApplicationController
def new
#feedback = Feedback.new
##user = Subject.find_all_by_teacher_id(current_user.id)
user_subject
end
def create
#feedback = Feedback.new(params[:feedback])
#feedback.user_id=current_user.id
if #feedback.save
flash[:success] = "Welcome #{current_user.name}!"
redirect_to #feedback
else
render 'new'
end
end
def show
#feedback_user_all= Feedback.find_all_by_user_id(current_user.id)
end
def user_subject
#course = Course.find(current_user.course_id)
#subject = #course.subjects
end
end
Use this in your Feedback class:
class Feedback < AR::Base
validates :user_id, uniqueness: {scope: [:subject_id]}
end
This will throw an error if you try to try to save two different Feedbacks with the same user_id and subject_id.
To let the user fix their submission, you should load the #subject and #course before rendering the edit form again:
def create
#feedback = Feedback.new(params[:feedback])
#feedback.user_id=current_user.id
if #feedback.save
flash[:success] = "Welcome #{current_user.name}!"
redirect_to #feedback
else
# Calling this method again should load the
# necessary instance variables for the form
# to work properly.
user_subject
render 'new'
end
end

Resources