JDavydko
JDavydko

Reputation: 3

How to create new model entry with a reference to the parent model

I have two models: User and Dream. User has_many :dreams and Dream belongs_to :user. I have two controllers for users and dreams as well. I want to create new Dream with form_for with a reference to a particular User. But it shouldn't be specified by me, it should somehow (and this is where I'm stuck) track on which User's page I pressed "Create new dream", and create it for this User.

I managed to do this with using only Users Controller (for managing Dreams as well), with passing user_id parameter in URL, and with hidden field. But I realize this is not a great way to do it, because anybody can edit URL or hidden field's value and create new Dream for any User.

I'm looking for a way to make two controllers communicate with each other under the hood. Or maybe this is not what I need and I miss some conceptual nuance of MVC or whatever. I need someone to push me in the right direction.

Upvotes: 0

Views: 70

Answers (3)

Shiva
Shiva

Reputation: 12514

I think that is the way things are done of such kind.

For:

anybody can edit URL or hidden field's value and create new Dream for any User

  • If you have single user through out the app, he can do anything ; he is superAdmin
  • If multiple users
    • they must have different roles like; moderator, superadmin, admin
    • in such case; authentication alone cannot do all the things you have to use some method of authorizationmechanism like cancan, cancancan, pundit,etc.
    • these basically prevents any user to do something nasty they are unauthorized.

If any user modifies the hidden field value, you have to check if he is authorized to do so or not.

Upvotes: 0

Antarr Byrd
Antarr Byrd

Reputation: 26061

You can add an optional user_id param to the new action in the DreamsController. It that param build the new dream on that User.

def new
  user_id = params[:user_id]
  @dream = if params[:id].present?
             User.find(params[:id]).dreams.build
           else
             Dream.new
           end
end

Then your link will be something like

<%= link_to "Create New Dream", {:controller => "dream", :action => "new", user_id: user[:id]}%>

Upvotes: 1

mb_s88
mb_s88

Reputation: 392

If you have login functionality, then you can define a method in ApplicationController that returns the user that matches the session token provided by the request, and then do current_user.dreams.create(params) which will create the dream with reference to whichever user is returned by current_user and never put any information about the user into the client's view.

If you don't have login functionality, then I wouldn't worry about the fact that it can be edited, since at that point anyone would be able to create a dream for any other user anyway just by visiting that page.

edit: e.g. I've often used something like this:

def current_user
  @current_user ||= User.find_by(session_token: session[:session_token])
end

Upvotes: 1

Related Questions