I am associating questions with users. Users has_many questions, and questions belongs to users. If I want to show on a user home page their own questions and only edit their own questions, how do I go about verifying this? I think a helper method is required to check whether the question does belong to the user and then, for example, (If question.belongs to user) then show edit link. Any ideas are appreciated!
Limit the scope of your find to the user whose questions you want to search.
Basically...
class QuestionsController < ApplicationController
def show
# instead of this...
#question = Question.find(params[:id])
# do this:
#question = current_user.questions.find(params[:id])
end
end
For showing a user's own questions you can make use of the collection rendering:
<%= render current_user.questions %>
Make sure you have a questions/_question.html.erb view, this is called by rails with a local variable passed to it (as the name of the model e.g. question).
This will only show the questions associated with the user.
edit
To add on meagars answer, you should redirect if the user tries to edit a question which doesn't belong to the user:
redirect_to :root if #question.blank?
Optionally show a notification to the user that they haven't got permission.
Related
I am trying to implement a retweet (repost) function for a Twitter clone. I initially thought I might need a separate retweet model, but I want to try and implement it using my existing tweet (micropost) model.
I'm having trouble wrapping my head around the schema and what migrations I would need to run. A Micropost would need a Repost column, but would a user need a repost_id? So I would add a Repost column to Micropost, and it would reference User? Or should I actually be adding the column to the User model?
Also if the repost function would work similar to create, would it not?
def repost
#micropost = Micropost.find(params[:id])
#repost = #micropost.repost by current_user
if #repost.save
flash[:success] = "Repost created!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
Is there any way to edit my current Micropost model, or do I need to utilize a specific Repost model?
The way I go about is asking if I need a one to many or a many to many relationship between reposts and users. A user can have (make) many reposts and a repost can be reposted by many users, so that would be a many to many relationship. Meaning you need a joint table between users and micropost - and the optimal name for it in this case is repost.
If you want to think about it the other way round - the way you proposed it: if you would reference the user id in the micropost table in a user_id column, there wouldonly be "enough space" to save one user id... so that would be a one to many association, which doesn't make that much sense for reposts.
For your question about the method, you will need to create a new repost instance once a user clicks on a button (submits a form) to repost. You should have a look at nested resources: https://guides.rubyonrails.org/routing.html#nested-resources
I have a column in my database called 'email'. I want to store the current logged in user's email address into this column when they submit a specific form.
At first I thought I should write something in the html to grab the current user's email address and hide it in the form somewhere but I realized that was probably a bad idea since anyone would be able to modify the html to put any email address that they want in there.
So my question is, would I go about this in the controller? If so, how would I go about doing that?
I'm naming that other model as Article(you can use yours)
Have a column called user_id instead of email in that table
Class User
has_many :articles
end
Class Article
belongs_to :user
end
class ArticlesController
def create
#article = current_user.articles.new(article_params)
#article.save
end
def article_params
params.require(:article).permit(:field1, :field2)
end
end
If you do something like this then automatically user_id will be saved in that table.
So it will be easy for you to get all articles which is belonged to that user.
user = User.first
user.artciles # you will get all articles belonged to that user
article = Article.first
article.user # you will get user of that article
Hope this helps
Figured it out
#request.email = current_user.email
#request.save
Requirement: I need to create an application where user can logged in and can change the background color of that page, can change the font of the page and it should persist with session. so I am trying to create form which accept those attributes from user and can save in database. I am using devise for authentication.
How can I create form for user who is successfully logged into application(authentication is done by devise gem, so user table is already existing) and upon submission of form those attributes should get updated in user table. Any suggestion will be appreciated.
Q1 .What should be the name of controller and view for this form ?
Q2. How the routes can be define.
Q3. Whether controller should have update action to update user table with the extra attributes present in the form.
Thanks. Please comment below if I missed some information needed to provide. You can suggest me if you think this can be achieve in easier way also.
Whatever you want. Sounds li?ke you are just updated user attributes, so i would just use the User#update action
resources :users, only: [:update, :edit] #and any other user routes
? see 1
Also you will want to make sure that people can only edit their own account. In a before action you will want to add.
redirect_to root_path unless current_user == user_you_are_editing
What I would do:
Create a Model called UserPreferences that belongs_to :user, give this Model the attributes 'background_color', etc...
Add statement to user has_one :user_preferences
Create a form for the prefs like any Rails Model, that can only be accessed by current_user.
Use current_user.user_preferences to refer to these values, you can enhance this by placing alias methods in User, for example:
class User < ActiveRecord::Base
def background_color
self.user_preferences.background_color
end
end
I'm putting together a side project for a teacher/student type of website where the student will share a dashboard with the teacher. The teacher and student can both upload files and leave comments in the dashboard.
The part that I'm stuck on is the permission. For student, I've set up the index controller to this method
def index
#Homework = Homework.where(:user_id = current_user)
end
With this, I'm able to have the student only see the work that they have, but I'm confused on how to get the teacher to see each individual student's work?
Suggestions? Thanks
Here's a simple solution if you only ever need to support a single class in your application:
def index
if current_user.teacher?
#homeworks = Homework.all
else
#homeworks = Homework.where(user_id: current_user)
end
end
Otherwise, your Homework schema does not seem to be correctly designed. See your query below:
Homework.where(:user_id = <student_id>)
This works to retrieve a student's homeworks, but it does not work to retrieve a teacher's students' homeworks. You may need a class_id for a teacher to see each individual student's work:
Homework.where(:class_id = <class_id>, :user_id = <student_id>)
A Class has_many Teachers and has_many Students. This design will allow you to support multiple classes.
Some more guiding questions:
Is teacher/student both kept in the same User model?
How do you differentiate between teacher/student in your current User model?
Is there a "user_type" column somewhere in User?
What happens if the current_user is of the "teacher" user_type?
For complex user permissions, use CanCanCan: https://github.com/CanCanCommunity/cancancan
Don't use uppercase instance variables. ex: #Homework should be #homework
Check out the gem CanCan. Install it (follow the instructions, you should have to put something in application controller), Then, put in your ability file:
class Ability
include CanCan::Ability
def initialize(user)
can :manage, Homework, user_id: user.id
end
end
Then at the top of your StudentController put
load_and_authorize_resource
And the index action should look like:
#homework = #student.homework
Now, you didn't post your whole controller so this is a much as I can help.
I believe you may have a bigger underlying issue. You have students and teachers has_many homework i read in your comment. Then in your example you use user_id. You are likely overriding your students and teacher ownership of homework. You would need a has_and_belongs_to_many relationship OR you would need a student_id and teacher_id columns on the homework table
Cancan automatically generate a number of instance variables which can make it feel like magic. Watch the free railscasts on cancan the same guy who made the video wrote the CanCan library.
Alright so this is another try at asking my question. I did rather poorly the first time. I have a relationship set up in my models so that users have many submissions and submissions belong to a user. I have a reference column in my submissions table that references :user and an index:
add_index :submissions, :user_id
I am using omniauth so that people can sign in with twitter. I simply want to be able to have a signed-in user be able to submit a submission and then have rails understand that there is a relationship between the current_user and the submissions they just wrote. Problem is I can't seem to store current_user in an instance variable like so:
#user = current_user
which I would like to use in my submissions controller (create) like so:
#user = current_user
#submission = #user.submissions.create(params[:submission])
I need this so that I could have a user create a submission on views/submissions/index.html.rb page and rails would understand the relation. Thank you so much for looking at this. Also I apologize in advance if I just missed something really obvious or that is common knowledge.
Your post does not really contain a question or did I miss something? What seems strange to me is that you want to assign #user = current_user. There is no need to do so, current_user should be a user anyway, therefore you could just write #submission = current_user.submissions.create(params[:submission]).
Maybe you can edit your post and provide more details on your helper methods (current_user), the error message you get with the code above. What do you get if you add Rails.logger.info current_user (or current_user.name if you have this field)?
If you want you can follow the link in my profile here on Stack Overflow, I have a couple of Rails tutorials there, including one with Omniauth.