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.
Related
I'm trying to make that a subscriber, sub to an certain event
with the following url per example:
http://localhost:3001/events/1/subscribers/new
but I don't know how to associate event_id when creating a new subscriber
for the moment i'm getting this error:
Couldn't find Event with 'id'=
in the routes:
resources :events do
resources :subscribers #url/events/:events_id/subscribers/new
end
resources :events
root 'events#index'
in the subscribers controller:
def show
end
# GET /subscribers/new
def new
#puts "Look for me in console\n"
#puts params.inspect
#event = Event.find(params[:events_id])
#subscriber = #event.Subscriber.new
end
# GET /subscribers/1/edit
def edit
end
# POST /subscribers
# POST /subscribers.json
def create
#event = Event.find(params[:order_id])
#subscriber = #event.Subscriber.new order_params
##subscriber = Subscriber.new(subscriber_params)
respond_to do |format|
if #subscriber.save
SubsMailer.new_subscriber(#subscriber).deliver
format.html { redirect_to #subscriber, notice: 'Subscriber was successfully created.' }
format.json { render :show, status: :created, location: #subscriber }
else
format.html { render :new }
format.json { render json: #subscriber.errors, status: :unprocessable_entity }
end
end
end
in the new.html.erb:
<h1>New Subscriber</h1>
<%= render 'form', subscriber: #subscriber %>
<%= link_to 'Back', subscribers_path %>
model association:
event.rb:
class Event < ApplicationRecord
has_many :subscribers, dependent: :destroy
end
subscriber.rb:
class Subscriber < ApplicationRecord
belongs_to :event
validates :email, presence: true,
format: /\A\S+#\S+\z/,
uniqueness: { case_sensitive: false }
end
Well, I think this documentation will help you to understand what you need to do.
If briefly at first you need to change your models. You could have many to many for Event -> Subscriber association or one to many. One to many is the simplest to show so you need to add this to your Subscriber model:
belongs_to :event
And this to your Event model:
has_many :subscribers
Add new migration:
def change
remove_column :subscribers, :events_id
remove_column :subscribers, 'Event_id'
add_column :subscribers, :event_id, :integer
end
Then in your controller, you should change method calls, as Subscriber is a class, not the method.
def new
#event = Event.find(params[:event_id])
#subscriber = #event.subscribers.build
end
And you should be sure that in your database you have Event with this id.
To check it you can try to debug your controller code:
def new
puts "Event ids: " + Event.all.map(&:id).inspect
#event = Event.find(params[:event_id])
#subscriber = #event.subscribers.build
end
In your logs you should have something like:
Event ids: [1]
I think you just have a typo in your new method. You call params[:eventS_id] when it should be params[:event_id]. Also you don't properly reference your association. it should be event.subscribers.new:
def new
#puts "Look for me in console\n"
#puts params.inspect
#event = Event.find(params[:event_id])
#subscriber = #event.subscribers.build
end
Migration:
def up
change_table :subscribers do |t|
t.remove :Event_id
t.references :event
end
end
def down
change_table :subscribers do |t|
t.remove :event_id
t.add :Event_id, :integer
end
end
Keep me posted whether this helps and if you have any additional issues
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.
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
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
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.