Rails ActiveRecord: default scope on logged-in user - ruby-on-rails

I have a Post model that is associated to users (think of 'post owner').
class Post < ActiveRecord
belongs_to :user
(...)
end
In my Post#index action/view, I want to only display posts that belong to the currently logged-in user.
So first approach would have been to somehow set a default scope in the Post model, but as the current_user is known only at runtime, this does not fit in model (in the MVC sense) but rather in the controller.
So, what would be the rails way of implementing a "default scope" in the controller?

If your User class has an association to their posts like this:
class User < ActiveRecord::Base
has_many :posts
end
Then in your controller you can simply use
current_user.posts
to get all the posts of the current user

The easiest and cleanest way will be to scope for the current user's posts (right in the controller):
current_user.posts
You can chain multiple selects on top of it.

Related

Rails controller design help needed

I have this scenario.
My Models
class User
end
class Student
has_many :daily_records
end
class DailyRecords
belongs_to :student
end
What i am trying to archive
i want to create a form on the student's show page to enter data for his daily records.
i want the form to have the id for the user entering the data.
How can i design the controller for this scenario.
What i have done so far.
i added the user model using Devise
i have scaffold the two model (student, daily_record) and added the associations as seen above.
I know i need to work on the show action of the student controller to make this work. I need help. just new to rails
thanks
class StudentsController < ApplicationController
before_action :set_student
def show
<--help code--->
end
........

Rails unable to mass assign values to DB when delegation to getter/setter is used

In my rails app- I have 2 models, User and Post. A user has one post. I have a has_one to belongs relationship.
In my user controller, I update attributes of the post (say post_text) by calling user.update_attributes!(params[:post])
In the User model, I have
attr_accessible :post_text (The view accepts a post_text) which I can see being passed to the controller.
Also, I delegate the setter methods on
delegate :post_text, 'post_text=', :post_text?, to: :post
In Post class, I have implemented the above 3 methods eg -
def post_text=(input_text)
#logic
end
def post_text
#logic
end
def post_text?
#logic
end
When I try to persist the input from form, it does not get saved to the DB i.e. DB is always empty. I have tried debugging in the form of unit and controller level tests and they all work as expected. How can I go about debugging further?
models/user.rb
has_many :posts
models/post.rb
belongs_to :user
For more information Active Record Associations

Rails 5 - Best way to hold onto params for creating associations?

Here's the scenario to illustrate my question. I have 2 models:
# models/post.rb
belongs_to :user
validates_presence_of :comment
And we have a devise model called Users
# models/user.rb
has_many :posts
What I would like to achieve:
Person comes to the website, is able to create a Post, after creating the Post, they are prompted to create an account. After creating the account, the Post that they just created would be associated to the User they just created.
Usually i'd make use of routes to hold the params[:id] which can be accessed in the controller method. For example the URL may look something like this:
www.foo.com/foo/new/1
And then I can do this:
# foo_controller.rb
def new
#foo = Foo.new
#parent = Parent.find(params[:id])
end
And in the view I can simply access #parent and use a hidden field to fill the parent ID.
But when routing through so many different pages (such as creating a Devise User), how do I hold onto the parent/child ID such that I can still create that association?
Using an hidden field or the route to store the id, with no authorization in the process, would not be secure. What if I just use the browser inspector and change the value of the id ? Your cool post would be mine.
What you could do is, for instance, add a field called guest_id to the Post, in which the value is unique (like SecureRandom.uuid), and also store that value in the session.
Thus, after the user is created, you could do something like that
if (post = Post.find_by(guest_id: session[:guest_id])).present?
post.update(user_id: current_user.id)
end

Create User Account Settings Page in Ruby on Rails with devise

I am new to Ruby on Rails and I have created a project that contains a User table (generated by devise) and a AccountSetting table that contains user specific account settings (this table has a foreign key that relates to the id in the User table thus each User has zero or one AccountSettings). I have my seed data working fine, and I can seed the database with users that have user specific account settings. The User table is related to the AccountSetting table with a "has_one :accountsetting" and the AccountSettings table "belongs_to :user". This all works and makes sense. However, I have a method called "show_user_setting" in my UserSettings controller, and I do not know how to ONLY SHOW the account settings for that specific authenticated user.
So, how can I only display the user setting for the currently logged in user? Again, I am using devise.
My general idea of how to do this would be something like this. However I know this is incorrect, but for the purpose of an explanation, here it is.
def show_user_setting
#setting = AccountSetting.find(current_user)
end
My idea is that the #setting will contain the setting for the currently logged in user. Thanks in advance!
You should do this:
#app/models/account_setting.rb
class AccountSetting < ActiveRecord::Base
belongs_to :user
end
#app/models/user.rb
class User < ActiveRecord::Base
has_one :account_setting
end
This will allow you to call the following:
#setting = current_user.account_setting
Our Setup
For what it's worth, we do something similar:
#app/models/user.rb
class User < ActiveRecord::Base
before_create :build_profile #-> builds a blank profile on user create
has_one :profile
end
#app/models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
This allows us to put all sorts of different options inside the profile model (we have homepage etc):
The important thing to note here is that the above allows you to delegate various methods to the profile model, allowing you to call the following:
current_user.profile_name
current_user.profile_signin_redirect?
current_user.profile_avatar
etc
Have you tried
def show_user_setting
#setting = AccountSetting.find_by(user_id: current_user.id)
end
The way .find() works is it searches the model for the id passed. So, the way you currently have it is your going to try to search for the id of the model, when you want to find the foreign key. So use Model.find_by(column_name: param). You'll what to change user_id: to the column name of what you're storing the foreign key in, I'm just assuming it's something similar to that.
I'm guessing the show_user_setting function is part of a controller, if it is on a model then read this: accessing devise current_user within model
to set the #setting variable you should be able to do this
#setting = AccountSetting.find(user_id: current_user.id)
or
#setting = AccountSetting.find(user: current_user)

how set curren_user_admin.id in model Post ??? I'm using ActiveAdmin + Cancan

I'm using ActiveAdmin + Cancan, i have this models
AdmiUser
Notice
I want set the id of the current_user_admin in Notice model before save a notice
class Notice < ActiveRecord::Base
belongs_to :admin_user
belongs_to :category
before_save :set_admin_user_id
def set_admin_user_id
self.admin_user_id = ? # maybe..! : current_admin_user.id
end
...
end
here is the link on github activeadmin-cancan-roles
I don't know ..!!! :(
You don't! Doing so would violate the principles of Model-View-Controller. Only the controller should know about the current user.
If you need to store the current admin user in a Notice instance, then just set it when you create it (which you're doing in the controller anyway, where you have access to who the current admin user is).

Resources