I'm (very) new to ror and have read many tutorials for this issue but none seem to work. I'm trying to let one user create one booth to sell things.
This is my db migration:
class CreateBooths < ActiveRecord::Migration
def change
create_table :booths do |t|
t.string :name
t.references :user, index: true
t.timestamps null: false
end
add_index :booths, [:user_id]
end
end
Here is the booth controller:
class BoothsController < ApplicationController
before_action :logged_in_user
def new
#booth = Booth.new
end
def create
#booth = current_user.booths.build(booth_params)
if #booth.save
flash[:success] = "Congrats on opening your booth!"
redirect_to root_url
else
render 'new'
end
end
private
def booth_params
params.require(:booth).permit(:name)
end
end
And this is the booth model:
class Booth < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
end
I also added this to the user model:
has_one :booth, dependent: :destroy
When I include validates :user_id, presence: true it won't save to the db. When I exclude it, it saves but does not include a user id in the database. If you are still reading thank you and I hope you can help!
You need to change create method of your BoothsController to this:
def create
#booth = current_user.build_booth(booth_params)
if #booth.save
flash[:success] = "Congrats on opening your booth!"
redirect_to root_url
else
render 'new'
end
end
Here, you have one-to-one association between user and booth, and that's why you have to instantiate booth for current_user using build_<singular_association_name>, which is build_booth and pass params to it: build_booth(booth_params).
booths.build(booth_params) works for one-to-many association, for example: user has many booths, not vice a versa.
Related
I want to create a polymorphic model to favorite each objects I want to create to stock in my user page.
I am developing a web app to learn japanese and we can favorite different types of cards as kanas or kanjis and sentences.
So there are 3 objects and soon more to favorite.
I migrated a table which names Favorite :
create_table "favorites", force: :cascade do |t|
t.integer "user_id"
t.integer "favoritable_id"
t.string "favoritable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Here is the Favorite model belongs_to
class Favorite < ActiveRecord::Base
belongs_to :favoritable, polymorphic: true
belongs_to :user
end
Here are the Cards model has_many
class Symbole < ActiveRecord::Base
accepts_nested_attributes_for :kanji_attribute, :allow_destroy => true
has_many :sentence_symboles, :class_name => "SentenceSymbole", :foreign_key => "symbole_id"
has_many :favorites, as: :favoritable
end
and I added in sentence model too
class Sentence < ActiveRecord::Base
include Authority::Abilities
has_many :sentence_symboles, :class_name => "SentenceSymbole", :foreign_key => "sentence_id", dependent: :destroy
has_many :favorites, as: :favoritable
end
Now here is the Favorite controller and I don't really know how to write the create method. Here is the Controller I do:
class FavoritesController < ApplicationController
def index
#favorites = Favorite.where(user: current_user)
end
def create
#Favorite.create(user_id: User.last.id, favoritable_id: Symbole.last.id, favoritable_type:"Symbole")
#favorite = current_user.favoritable.favorites.create(symbole: #symbole, sentence: #sentence).first
if #favorite.present?
#favorite.destroy
else
#favorite = current_user.favorites.new(symbole: #symbole, sentence: #sentence)
if not #symbole.favorites.where(user: current_user).take
#sentence.favorites.where(user: current_user).take
#favorite.save
end
end
# redirect_to favs_path
# redirect_to :back
respond_to do |format|
format.js { render :ajax_update_favs }
end
end
def destroy
#favorite = Favorite.find(params[:id])
#favorite.destroy
redirect_to :back
end
end
Please could someone give me the right way to favorite all object I want and add in an favorite index#view.
Thank you for your help.
I think my question is simple but no. How to favorite each object I want with the def Create controller what is the best method?
I do that
def create
#Favorite.create(user_id: User.last.id, favoritable_id: Symbole.last.id, favoritable_type:"Symbole")
#favorite = #favoritable.favorites.build(favorite_params)
#favorite.user = current_user
#favorite.save
respond_to do |format|
format.js { render :ajax_update_favorites }
end
end
Not sure I understood the problem entirely. It looks like you're overcomplicating favoritesController#create. If a record only should be favorited once, you should add a uniqueness validation in the Favorite model.
Assuming that you have your user model set up like
class User < ActiveRecord::Base
has_many :favorites
# Rest..
end
def create
#favorite = current_user.favorites.create(favorite_params)
# This will create a new Favorite with user_id: current_user.id, favoritable_type: "Symbole", favoritable_id: 1337
# Is this the desired behaviour?
respond_to do |format|
format.js { render :ajax_update_favs }
end
end
private
def favorite_params
params.require(:favorite).permit(:favoritable_type, :favoritable_id)
end
If this is called from javascript with jquery pass the type and id that you wan't to favorite.
$.post( "/favorites", {
favorites: {
favoritable_type: "Symbole",
favoritable_id: 1337
}
});
these are my 3 models :
model for User:
class User < ActiveRecord::Base
has_many :patients, through: :treatments
has_many :treatments
.
.
.
model for patient:
class Patient < ActiveRecord::Base
has_many :user, through: :treatments
has_many :treatments, dependent: :destroy
.
.
.
model for treatment:
class Treatment < ActiveRecord::Base
belongs_to :patient
belongs_to :user
validates :patient_id, presence: true
default_scope -> { order(created_at: :desc) }
end
And this is my treatment table :
class CreateTreatments < ActiveRecord::Migration
def change
create_table :treatments do |t|
t.date :teartment_date
t.text :remark
t.float :fee
t.references :patient, index: true, foreign_key: true
t.timestamps null: false
end
add_index :treatments, [:patient_id, :created_at]
end
end
now i want to define a controller to create a new treatment that belongs to a specific user's patient.
this is my controller :
def new
#treat = Treatment.new
end
def create
#userpatient = current_user.treatments.build(treat_params)
if #userpatient.save
flash[:success] = "new treatment added"
redirect_to root_url
else
render 'new'
end
end
but this is the error that i receive, while i want to create a new treatment :
ActiveRecord::UnknownAttributeError in TreatmentsController#create
unknown attribute 'user_id' for Treatment.
and this is the current_user :
def current_user
if (user_id = session[:user_id])
#current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies[:remember_token])
log_in user
#current_user = user
end
end
end
i'm new to rails, the basic idea is i want my user to have treatment that belongs to a specific patient.
Thanks to replies i've over come with this issue by adding a reference column . now i receive no, but it does not save any treatments. i mean the part :
if #treat.save
flash[:success] = "new treatment added"
redirect_to root_url
else
render 'new'
end
it does not save and just render 'new' .
i have 2 questions :
1- how can i code my create controller ?
2- how to retrieve my treatments base on patient.what variable should i define in my patient 'show' method to have its treatments retrieved ?
When you say that User has_many :treatments and that Treatment belongs_to :user, both associations are expecting to find a user_id column in your treatments table. You might want to change your migration to include:
t.integer :user_id
and then drop your tables (if they have no data yet!) and rerun the migrations. Alternatively, you could create a new migration and simply run that:
add_column :treatments, :user_id, :integer
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
I am currently following Ryan Bates tutorial on activity feed from scratch.
**I added a originator_id to the database so that I can save the ID of the Owner who originated the post. But for some reason I can't get it to work.
My Database from Scratch
class CreateActivities < ActiveRecord::Migration
def change
create_table :activities do |t|
t.belongs_to :user
t.string :action
t.belongs_to :trackable
t.string :trackable_type
###I want to save the id corresponding to User who created the object
t.belongs_to :originator
t.string :originator_type
t.timestamps
end
add_index :activities, :user_id
add_index :activities, :trackable_id
add_index :activities, :originator_id
end
end
Here is my Code
Models
class Activity < ActiveRecord::Base
belongs_to :user
belongs_to :trackable, polymorphic: true
belongs_to : originator, polymorphic: true
attr_accessible :action, :recipient, :trackable
###how can i set the originator_id value
after_create :set_originator
def set_originator
self.originator.update_attribute(:originator, ???)
end
end
Controllers
class ApplicationController < ActionController::Base
###sets the action and trackable values
###how can i the originator here. i keep getting an error saying undefined method
###why is it that rails recognizes trackable?
def track_activity(trackable, action = params[:action])
current_user.activities.create! action: action, trackable: trackable,
originator: originator
end
end
class LikesController < ApplicationController
def create
#like = Like.create(params[:like])
#dailypost = #like.dailypost
###Used to call track activity method above
track_activity #like
respond_to do |format|
format.js
format.html { redirect_to :back }
end
end
end
Don't know how solid this answer will be as i add more models to the activities, but this worked for my likes model.
If anyone can provide another solution that will work with multiple models i would really appreciate it. :)
class ApplicationController < ActionController::Base
def track_activity(trackable, action = params[:action])
current_user.activities.create! action: action, trackable: trackable,
originator: originator
end
def originator
#like.dailypost.user
end
end
Currently I allow users to follow one another on my rails app (similar to twitter).
I would love if New Users that sign up to the site Automatically follow Admin User.
Similar to how MySpace use to automatically make Tom your first friend
Below is the code I use to create new users and allow users to follow one another.(i know this is a very broad question but .....)
(Can someone please point me in the right direction onto how I can get this started. Would I need to create a method....in my models or add code to the controller?)
New to Rails Please help)... :)
USER CONTROLLER
class UsersController < ApplicationController
before_filter :admin_user, only: [:destroy]
respond_to :html, :js
def new
#user = RegularUser.new
end
def index
#users = User.paginate(page: params[:page], :per_page => 100).search(params[:search])
end
def destroy
User.find_by_username(params[:id]).destroy
flash[:success] = "User destroyed."
redirect_to users_url
end
def create
#user = RegularUser.new(params[:regular_user])
if #user.save
UserMailer.registration_confirmation(#user).deliver
UserMailer.welcome_user(#user).deliver
sign_in #user
flash[:success] = "Welcome to the ClickOnComics!"
redirect_to (publishers_path)
else
render 'new'
end
end
private
def admin_user
redirect_to(root_path) unless current_user.admin?
end
def follow_admins
admins = User.find_by_admin(true)
admins.each do |admin|
self.follow!(admin)
end
end
class RelationshipsController < ApplicationController
before_filter :current_user
respond_to :html, :js
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_with #user
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_with #user
end
end
MODELS
class Relationship < ActiveRecord::Base
attr_accessible :followed_id
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
end
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
after_create :follow_admins
def follow_admins
admins = User.find_all_by_admin(true)
admins.each do |admin|
self.follow!(admin)
end
end
def following?(other_user)
relationships.find_by_followed_id(other_user.id)
end
def follow!(other_user)
relationships.create!(followed_id: other_user.id)
end
def unfollow!(other_user)
relationships.find_by_followed_id(other_user.id).destroy
end
end
I used this tutorial to help me establish privileged administrative users with a boolean admin attribute in the User model
http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-users#sec-administrative_users
SCHEMA
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.string "role"
t.string "username"
t.timestamp "created_at", :null => false
t.timestamp "updated_at", :null => false
t.boolean "admin", :default => false
t.string "password_reset_token"
t.timestamp "password_reset_sent_at"
end
Would I need to create a Method that defines user_admin?
In user.rb add a after_create filter
after_create :follow_admin!
def follow_admin!
relationships.create!(followed_id: admin_user.id)
end
In create action before sign_in add
#user.follow! admin_user
you need to fetch admin user first somehow.
Good idea would be to make follow!, following? and unfollow! methods to accept either id or object as in
def follow!(user_or_id)
id = (user_or_id.is_a?(User) ? user_or_id.id : user_or_id)
relationships.create!(followed_id: id)
end