A user can create organization and then he can make other users as moderators to his organization. Below method shows how the organization is created.
def create
#organization = current_user.organizations.build(organization_params)
# Confirm organization is valid and save or return error
if #organization.save!
# New organization is saved
respond_with(#organization) do |format|
format.json { render :json => #organization.as_json }
end
else
render 'new', notice: "Unable to create new organization."
end
end
How should I create moderators for the organization. I tried using has_many through but it failed. Can somebody help me?
Update
Organization Model
class Organization < ActiveRecord::Base
has_many :moderators
has_many :users, :through => :moderators
end
UserModel
class User < ActiveRecord::Base
enum role: [:user, :moderator, :organization, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :user
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :moderators
has_many :organizations, :through => :moderators
end
Moderator Model
class Moderator < ActiveRecord::Base
belongs_to :user
belongs_to :organization
end
When I create new organization my organization user_id is nil?
Take look at has and belongs to many relation http://apidock.com/rails/v4.2.1/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many since one user can be moderator for many organization and organization can have many moderators. Also instead of calling #organization.save! you should call #organization.save because now it will throw error if save would be unsuccessful. You want to have boolean as result of save so your condition works properly
Related
I have a Course and Lesson models. Course has several lessons. I want to find all the lessons for currently logged in student to generate kind of timetable.
I have a method that returns all the courses that this student is studying. Now I want to get all lessons from all those courses in #courses into #lessons, something like:
def index
#courses = current_student.find_courses
#lessons = #courses.lessons
end
Is it possible to do it somehow simple on one line?
The find_courses method is implemented as following:
def find_courses
Course.where("id IN (?)", StudentAssignment.select("course_id").where('student_id == (?)', self.id))
end
The Models:
class Student < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :student_assignments
has_many :courses, :through => :student_assignments
....
class Lesson < ApplicationRecord
belongs_to :room
belongs_to :teacher
belongs_to :course
....
class Course < ApplicationRecord
has_many :lessons, dependent: :destroy
has_many :teacher_assignments
has_many :teachers, :through => :teacher_assignments
has_many :student_assignments
has_many :students, :through => :student_assignments
...
class Student < ApplicationRecord
has_many :courses
def active_lessions
Lession.joins(course: :students).where(students: {id: self.id})
end
end
In this way you can directly get all active lesssions for current_user
current_student.active_lessions
Try:
#lessons = #courses.flat_map(&:lessons)
It takes each course in #courses list and gets the list of lessons for that course.
So I have a blog I am trying to have a simple upvote/downvote feature for the posts. I have devise set up and I made all the associations between the models, votings, users, and home_blogs.
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :liked_home_blogs, through: :votings
end
class HomeBlog < ApplicationRecord
mount_uploader :image, ImageUploader
has_many :hashtaggings
has_many :hashtags, through: :hashtaggings
has_many :votings
has_many :votants, through: :votings
def all_hashes=(names)
self.hashtags = names.split(",").map do |name|
Hashtag.where(name: name.strip).first_or_create!
end
end
def all_hashes
self.hashtags.map(&:name).join(", ")
end
end
class Voting < ApplicationRecord
belongs_to :home_blog
belongs_to :user
end
and the controller looks like this at the moment:
class VotingsController < ApplicationController
before_action :authenticate_user!
def upvote
#votings = HomeBlog.find(params[:home_blog_id])
#votings.votings.build( :upvote => true, :downvote => false,
:user_id => current_user.id)
#votings.save!
redirect_to request.referrer, notice: "Thanks for the
vote!"
end
def downvote
#voting = HomeBlog.find(params[:home_blog_id])
#voting.votings.build( :downvote => true, :upvote =>
false, :user_id => current_user.id)
#voting.save!
redirect_to request.referrer, notice: "Thanks for the
vote!"
end
private
def voting_params
params.require(:voting).permit(:upvote, :downvote,
:home_blog_id, :user_id)
end
end
Sorry about the crappy copy and paste for the controller. My question is, how do I make a condition for the current_user in devise to limit them to one vote per home_blog post? Thanks!
I think you would add multicolumn unique index to the join table. Something like...
add_index :voting, [:user_id, :home_blog_id], unique: true
If im understanding your question correctly you would like there to be only one votings record for a home_blog per current_user ( user_id )
When trying to create a new Person I receive the following error on the line if #persons.save:
NoMethodError in PeopleController#create,
undefined method `save' for nil:NilClass
Any thoughts on how to fix would be much appreciated, thanks.
Controller
# GET /people/new
def new
#person = current_user.person.build
end
# GET /people/1/edit
def edit
end
# POST /people
# POST /people.json
def create
#person = current_user.person.build(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render action: 'show', status: :created, location: #person }
else
format.html { render action: 'new' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :person
end
Person model
class Person < ActiveRecord::Base
has_many :user
has_paper_trail
acts_as_taggable
#tags = Person.acts_as_taggable_on :tags
def admin_permalink
admin_post_path(self)
end
end
It seems like you want a relationship where a user can have many people and a person can have many users.
This requires a special association type called has_many through.
Basically a user can be associated to many people and vice versa, :through a third model called a join table.
e.g
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :people, through: :relationships # The model name(person) is pluralised for has_many associations
end
class Person < ActiveRecord::Base
has_many :users, through: :relationships # user needs to be pluralised here
has_paper_trail
acts_as_taggable
#tags = Person.acts_as_taggable_on :tags
...
end
class Relationship < ActiveRecord::Base # This is the join table
belongs_to :user
belongs_to :person
end
This requires you to create the relationship table in the database (Instead of relationship, call it whatever makes the most sense). It needs person_id and user_id integer columns.
In your controller you will then need to use the pluralised version too:
#person = current_user.people.build(person_params)
You should have a good read of the rails association guide. Particularly the has_many through section.
There is another type of association called a has_and_belongs_to_many which may be better for your case. In my experience it often seems like the easier approach but ends up causing headaches compared to has_many through.
I am new to Ruby on rails and I am creating simple website. I found out the rails 3 uses attr_accessible while rails 4 uses strong parameters. I am currently working with rails 4. I am not quite sure how to set up the accepts_nested_attributes_for.
This is what I have
User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
has_many :expense_pictures
has_many :income_pictures
accepts_nested_attributes_for: ExpensePicture ?
accepts_nested_attributes_for: IncomePicture ?
end
ExpensePicture model:
class ExpensePicture < ActiveRecord::Base
belongs_to :user
mount_uploader :image, ImageUploader
end
ExpenseText model:
class ExpenseText < ActiveRecord::Base
belongs_to :expense_pictures
end
IncomePicture model:
class IncomePicture < ActiveRecord::Base
belongs_to :user
mount_uploader :image, ImageUploader
end
IncomeText model:
class IncomeText < ActiveRecord::Base
belongs_to :income_pictures
end
My User controller
class UserController < ApplicationController
def create
User.create(user_params)
accepts_nested_attributes_for :IncomePicture ?
accepts_nested_attributes_for :ExpensePicture ?
end
private
def user_params
# required input for params
# permit - returns a version of the params hash with ony the permitted attributes
params.require(:user).permit(:name, :email, :password, :password_confirmation, ...not sure...)
end
end
Using accepts_nested_attributes_for for has_many relation with your models,your User model should look like this
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:rememberable, :validatable
has_many :expense_pictures
has_many :income_pictures
accepts_nested_attributes_for :expense_pictures
accepts_nested_attributes_for :income_pictures
end
Your new and create methods of usercontroller should look like this
def new
#user = User.new
#user.expense_pictures.build
#user.income_pictures.build
end
def create
#user = User.new(user_params)
if #user.save
redirect_to #user
else
render 'new'
end
end
And your user_params method should look something like this
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, expense_pictures_attributes: [:your_attr1,:your_attr2,..],income_pictures_attributes: [:your_attr1,:your_attr2,..])
end
Feel free to ask if you want any more information regarding to this.
Rails 4.1
Ruby 2.0
Credential.rb
class Credential < ActiveRecord::Base
belongs_to :category
has_many :user
validates :name, :login, :password, presence: true
attr_accessor :encryption_key
attr_encrypted :login, key: :encryption_key
attr_encrypted :password, key: :encryption_key
end
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :credentials
def you
"You are <b>#{email}</b>"
end
end
CredentialsController.rb
class CredentialsController < ApplicationController
before_filter :authenticate_user!
def create
#credential = current_user.credentials.new
#credential.encryption_key = session[:master_key]
#credential.update(credential_params)
if #credential.save
redirect_to credential_path(#credential), notice: "Password entry created successfully."
else
render "new"
end
end
The line:
#credential.update(credential_params)
throws an exception
undefined method 'each' for #<User:0x4de4f58>
You need to edit your associations. You have credentials that has_many :user and users that has_many :credentials. The one with the foreign key should be a belongs_to not has_many. If you're attempting to make a many-to-many relationship, then either use has_many_and_belongs_to or a join table. Further, it should be has_many :users and not has_many :user. That should resolve your error.