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

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

Related

How do I add extra data to model before submit from form in Rails

I have a form that a user fills out that I need to add some extra 'behind the scenes' data to before creating the object in my DB. For instance, data like a referrer_url, clout_score etc. How do I go about doing it? Are the methods something that should sit in the Controller or the Model?
For instance, I need to be able to add what the method create_url returns to the :
users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "You've been added to the waiting list!"
render 'show'
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :use_type)
end
def create_url
url = SecureRandom.hex(4)
end
end
User Table in DB
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.integer :init_spot
t.integer :current_spot
t.string :referrer_url
t.integer :clout
t.timestamps null: false
end
end
end
Should I just do an #user.update_attributes in the same controller action and call my methods that way? Like:
if #user.save
#user.update_attributes(referrer_url: create_url, clout: calc_clout, etc.)
flash[:success] .....
render 'new'
What's the best way to accomplish this?
Thanks!
You can use the hash options of the ActiveRecord::Core#new method in your controller:
#user = User.new(user_params.merge(referrer_url: create_url))
Or move all that into a separate method for a clearer and more readable code:
#user = User.new(user_params_with_additional_data)
private
def user_params_with_additional_data
user_params.merge(referrer_url: create_url)
end
This worked for me:
user.rb
before_save :add_more_info
def add_more_info
self.referrer_url = create_url,
self.clout = calc_clout
end
note I don't usually use self in model, but somehow this is the only way I could make it work with before_save callback

NoMethodError (undefined method `posts' for nil:NilClass)

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.

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.

how to use this class method within my Rails 3 code?

I am really hoping to get this resolved tonight so any help would be great.
I added this class method into my post.rb model
def self.without_review
where(review: false)
end
What I am trying to do is ONLY show all posts on the site where review=false. If review=true, I want to manually approve them before they're displayed. Right now, all posts are getting displayed whether the review is true or false.
Here's my post controller
class PostsController < ApplicationController
before_filter :signed_in_user
before_filter :load_post, only: :destroy
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Shared!"
redirect_to root_path
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#post.destroy
redirect_to root_path
end
private
def correct_user
#post = current_user.posts.find_by_id(params[:id])
redirect_to root_path if #post.nil?
end
def load_post
#post = current_user.admin? ? Post.find(params[:id]) : current_user.posts.find(params[:id])
end
end
and here's the full post.rb model
class Post < ActiveRecord::Base
attr_accessible :content, :review
belongs_to :user
validates :user_id, presence: true
validates :content, presence: true
default_scope order: 'posts.created_at DESC'
def self.without_review
where(review: false)
end
end
The schema of the posts table to show how "review" is set up (last row)
create_table "posts", :force => true do |t|
t.text "content"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.boolean "review", :default => false
The Static Pages Controller
class StaticPagesController < ApplicationController
def home
if signed_in?
#post = current_user.posts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
def post1
if signed_in?
#post = current_user.posts.build
end
end
end
UsersController (def show)
def show
#user = User.find(params[:id])
#posts = #user.posts.paginate page: params[:page], :per_page => 15
end
You didn't show the controller/action where the actual listing of posts is generated, but I guess you have to replace Post.all with Post.without_review there.

Resources