Ruby on rails noob here.
User fields relevant to this question: id (prim. key). Post fields relevant to this question: id, user_id (fk). The foreign key is user_id of Posts which is connected to id of Users. Is the following the right syntax? I want to grab the User object who posted the current post:
(this is in controllers/posts_controller.rb)
#id = Post.find(params[:id]).user_id
#user = User.find(#id)
You can see the context of the code below:
def sendMessage
##user = current_user
#id = Post.find(params[:id]).user_id
#user = User.find(#id)
UserMailer.welcome_email(#user).deliver
respond_to do |format|
format.html { render :nothing => true, :status => :ok }
end
end
The reason I'm asking is because an email is not getting sent to the user who created the post. Now, I know that this isn't an email issue because, as a test, I tried commenting out the two lines in question and simply using:
#user = current_user
...and this sends an email to the user who's logged in (but this isn't what I want).
Thanks in advance,
Matt
You should have your models set up as follows:
class Post < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
Then in your controller you can do:
#post = Post.find(params[:id])
#user = #post.user
You should set the proper relations in the model.
I guess 'has_many :posts' in User and 'belongs_to :user' in Post.
Then you'll be able to do:
#user = Post.find(params[:id]).user
Related
I have the following in my UsersController
def show
#user = User.find(params[:id])
if current_user.id != params[:id] #! need to fix this
#answer = Answer.new
else
#answer = Answer.find(params[:id])
end
where each user has_many answers through a quizzes model. How can I write the if statement so if the answers are blank for that particular user it'll jump to creating a new quiz? (and if they aren't, to display the information).
I am not clear what are you trying to achieve as your code is doing unwanted check.SO if you just want to check if any user(assuming signed_in users) want to go to show action conditionally,i think you may try this:-
##assuming user has_many answers
##answer belongs_to user
def show
##get the user
#user = User.find(params[:id])
##verify if answer is present
if #user.answers.present?
#answer = #user.answers
else
#answer = #user.answers.new
end
end
The above logic can be used to has many through associations as well,just need to change to through model
Hope it helps :)
I would like to have access to the parameters in nested attributes..... Below is the code.
<%= link_to "Invoice", user_invoice_path(#user, invoice) %>
How do I access the user and invoice in the Invoice controller show action.
def show
#user = User.find(params[:user_id])
#invoice = Invoice.find(params[:id])
end
User Model:
class User < ActiveRecord::Base
has_many :invoices
end
Invoice Model:
class Invoice < ActiveRecord::Base
belongs_to :user
end
I know how it works when it is not nested.... Can anyone, please help?
If I understand correctly, you can't find the #user or #invoice in this way.
Please debug your show action and you will find params as follows,
{"action"=>"show", "controller"=>"invoices", "user_id"=>"307", "id"=>"359"}
So now write your show action something like,
def show
#invoice = Invoice.find(params[:id])
#user = User.find(params[:user_id])
end
There may be better ways to find the objects in the controller action. But this is the basic approach you will have to consider instead of what you tried.
So i'm having this issue trying to figure out how to use the build method in rails to create an object once a user completely registers and still have that object connected to the users id. I'm using devise for authentication and the model that needs to be created is called "app".
This is the create method for "app".
def create
#app = App.new(app_params)
#app.id = current_user.id
respond_to do |format|
if #app.save
format.html { redirect_to #app, notice: 'Application successfully created.'}
else
format.html { render action: 'new' }
end
end
end
Im getting this error:
Couldn't find App with id=1
from my multi step form controller:
def show
#user = User.find(current_user)
case step
when :school, :grades, :extra_activity, :paragraph, :submit
#app = App.find(current_user)
end
render_wizard
end
You need an after_create callback in the User model. It makes no sense to mess with the AppController because no forms have been filled up for the app and you have no app_params.
class User < ActiveRecord::Base
after_create :build_initial_app
protected
def build_initial_app
self.create_app
end
end
You can read more about this at the Rails Guides page for ActiveRecord Callbacks.
The problem line in your code is here:
#app.id = current_user.id
Setting an ActiveRecord object's id is a no-no. Think of the id attribute like you would a pointer in C. The system creates it for you, and you can use it to refer to a unique model object.
What you probably want is something along the lines of:
#app.user_id = current_user.id
Or, even better:
#app.user = current_user
To do that, you need to set up an association between your App model and your User model. There's a good tutorial on that here.
I have a form for creating materials (title, description and content - all basic). The form saves these details just fine but it doesn't save the user_id, which should be the user_id of the current_user. How do I do this? It must be easy but nothing has worked so far.
def create
#material = Material.new(params[:material])
if #material.save
flash[:success] = "Content Successfully Created"
redirect_to #material
else
render 'new'
end
end
def create
#material = Material.new(params[:material])
#material.user_id = current_user.id if current_user
if #material.save
flash[:success] = "Content Successfully Created"
redirect_to #material
else
render 'new'
end
end
There are a few different ways to do it depending on how you have your application setup. If there is a relationship between the user and materials (User has many materials), you could use that in your controller:
def create
#material = current_user.materials.new(params[:material])
# ...
end
If you don't have that relationship, I would still recommend setting it in the controller as opposed to a hidden field in the form. This will be more secure because it won't let someone tamper with the user id value:
def create
#material = Material.new(params[:material].merge(user_id: current_user))
# ...
end
Assuming you are saving the login users's object in the current_user following will work for you
#material = Material.new(params[:material])
#material.user_id = current_user.id
if #material.save
With Rails 5 and parameters needing to be permitted before objects are created, this is the simplest way to merge the current_user into the params, kudos to #Peter Brown in his answer:
def create
#discussion = current_user.materials.new(new_material_params)
# ...
end
private
def new_material_params
params.require(:material).permit(:title, :description,: content)
end
If you have nested object creation using accepts_nested_attributes_for, you need to manually merge deep into the association parameters:
class User < ApplicationRecord
has_many :discussions # Used to associate User with Discussion later
end
class Comment < ApplicationRecord
belongs_to :user
end
class Discussion < ApplicationRecord
belongs_to :user
has_many :comments
accepts_nested_attributes_for :comments
end
class DiscussionsController < ApplicationController
def create
# Merge the params[:discussion][:user_id] by using the relationship's #new
#discussion = current_user.discussion.new(new_discussion_params)
end
private
# Sanitized params for creation, not editing
def new_discussion_params
params.require(:discussion)
.permit(:title, :user_id,
comments_attributes: [:id, :content, :discussion_id, :user_id])
.tap do |discussion_params|
# Require the association parameters, and if they exist,
# set :user_id for each.
discussion_params.require(:comments_attributes).each do |i, comment|
comment.merge!(user_id: current_user.id)
end
end
end
end
Heads up: Setting (or overwriting!) what will be params[:discussion][:comments_attributes]["0"][:user_id] works fine for creation. But if you allow editing deep hierarchies in addition to creation, make sure you don't accidentally overwrite all the :user_ids with the current user.
I would like to access "profiles" table from my Profile model which belongs_to :user "User model".
Firstly in my show action of the users_controller I'd like to grab data from the profiles table in order to show on the users profile page.
Secondly I'd like to make it possible for users to edit these things using a form. I know this is done in the update action? while edit action makes it possible to show a form on the edit view page..
Here is my controller:
class UsersController < ApplicationController
def new
#user = User.new
#title = "Practice"
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
#user.build_profile.save #same as Profile.new(:user_id => #user.id)
login #user
UserMailer.join_confirmation(#user).deliver
format.js { render :js => "window.location = '#{root_path}'" }
flash[:notice] = "Welcome!"
else
format.js { render :form_errors }
end
end
end
def show
end
def update
end
def edit
end
end
1) How would I access my profiles table?
The User has_one :profile
The Profile belongs_to :user
Advice will be appreciated. Took me half of the day to figure out how to have a row corresponding to a newly created user at sign up created in the profiles table and now the next step is to be able to grab data from the model in my users_controller. i know I could just create a profiles_controller and do things there but I don't want to attempt that right now as I'm sure there's a way to do it via the users_controller.
Thanks in advance for advice given.
View:
<%= #profile_data.first_name %>
<h4><%= current_user.username.capitalize %></h4>
<%= gravatar_image_tag(current_user.email, :alt => #title, :class => "gravatar", :gravatar => { :size => 150 }) %>
<br />
Trying to pull first_name from profiles table through users_controller
def show
#user = User.find_by_username(params[:username])
#profile_data = #user.profile
end
route:
match ':username' => "users#show"
I expect to see the name stored in first_name column of the profiles table when i visit localhost:3000/username
it doesn't show the users first name.
You can just do:
#user.profile
That will return the profile belonging to the User
Otherwise:
Profile.where('whatever condition you fancy')
will return A profile object based on conditions
You want a has_one:profile on the User model, and a belongs_to:user on the Profile model, making sure you have the appropriate user_id column in the profiles table. Add accepts_nested_attributes_for:profile to the User model and then you can create/edit the user's profile in the same form for editing users.
Read up on the rails release notes on nested attributes and guides: associations and forms.