Ror: Meaning of "User ||= User.New"

RoR: Meaning of user ||= User.new

If user is already set this does nothing, otherwise it will assign a new User object (created with User.new).

According to David A. Black, author of "The Well-Grounded Rubyist":

x ||= y means: x || x = y

The difference is that x ||= y won't complain if x is undefined,
whereas if you type x || x = y and there's no x in scope, it will.

For some added details, here's the relevant part of parse.y:

| var_lhs tOP_ASGN command_call
{
/*%%%*/
value_expr($3);
if ($1) {
ID vid = $1->nd_vid;
if ($2 == tOROP) {
$1->nd_value = $3;
$$ = NEW_OP_ASGN_OR(gettable(vid), $1);
if (is_asgn_or_id(vid)) {
$$->nd_aid = vid;
}
}
else if ($2 == tANDOP) {
$1->nd_value = $3;
$$ = NEW_OP_ASGN_AND(gettable(vid), $1);
}
else {
$$ = $1;
$$->nd_value = NEW_CALL(gettable(vid), $2, NEW_LIST($3));
}
}

NEW_OP_ASGN_OR is defined in node.h:

#define NEW_OP_ASGN_OR(i,val) NEW_NODE(NODE_OP_ASGN_OR,i,val,0)

NEW_NODE looks like this:

#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))

Looking for NODE_OP_ASGN_OR leads to compile.c, where the interesting part looks like this:

case NODE_OP_ASGN_OR:{
LABEL *lfin = NEW_LABEL(nd_line(node));
LABEL *lassign;

if (nd_type(node) == NODE_OP_ASGN_OR) {
LABEL *lfinish[2];
lfinish[0] = lfin;
lfinish[1] = 0;
defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
lassign = lfinish[1];
if (!lassign) {
lassign = NEW_LABEL(nd_line(node));
}
ADD_INSNL(ret, nd_line(node), branchunless, lassign);
}
else {
lassign = NEW_LABEL(nd_line(node));
}

COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
ADD_INSN(ret, nd_line(node), dup);

if (nd_type(node) == NODE_OP_ASGN_AND) {
ADD_INSNL(ret, nd_line(node), branchunless, lfin);
}
else {
ADD_INSNL(ret, nd_line(node), branchif, lfin);
}

ADD_INSN(ret, nd_line(node), pop);
ADD_LABEL(ret, lassign);
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
ADD_LABEL(ret, lfin);

if (poped) {
/* we can apply more optimize */
ADD_INSN(ret, nd_line(node), pop);
}
break;
}

I think this is more than I ever wanted to know about assignment in Ruby, but it was rather entertaining to look this up.

RoR Devise create user

Try this instead

def create_user
self.user = User.create({ :email => self.email, :password => '123456' })
end

My guess is that the association is not being registered because after the User.new call the object has not been saved to the database and has not been assigned an id attribute, and the id attribute is what is required to record the association. User.create initializes the object and saves it to the database in one step (assuming all validations pass).

I have an ldap connection on my RoR app but now how do I check users on login?

You could create a service that handles that process:

app/services/authenticate_user.rb

class AuthenticateUser
def initialize(user, password)
@user = user
@password = password
end

def call
user_is_valid?
end

private
def user_is_valid?
ldap = Net::LDAP.new
ldap.host = your_server_ip_address
ldap.port = 389
ldap.auth(@user, @password)
ldap.bind
end
end

Then use it in your controller:

class SessionsController < ApplicationController
def new
end

def create
username = params[:NumeroEmpregado]
password = params[:password]
name = "Some Name" # Change "Some Name" to set the correct name

if AuthenticateUser.new(username, password).call
user = User.create_with(nome: name).find_or_create_by(NumeroEmpregado: username)
session[:user_id] = user.id
redirect_to '/'
else
flash[:error] = "Erro! \nNúmero de Empregado e/ou password incorrecto(a)"
redirect_to '/login'
end
end

def destroy
session[:user_id] = nil
redirect_to '/index/new'
end
end

AuthenticateUser.new(user, password).call will return true when valid user and password are provided, and will return false otherwise.

This is a basic example covering only the LDAP authentication, you will need to adapt it for your specific needs, including exception handling.

What does ||= (or-equals) mean in Ruby?

This question has been discussed so often on the Ruby mailing-lists and Ruby blogs that there are now even threads on the Ruby mailing-list whose only purpose is to collect links to all the other threads on the Ruby mailing-list that discuss this issue.

Here's one: The definitive list of ||= (OR Equal) threads and pages

If you really want to know what is going on, take a look at Section 11.4.2.3 "Abbreviated assignments" of the Ruby Language Draft Specification.

As a first approximation,

a ||= b

is equivalent to

a || a = b

and not equivalent to

a = a || b

However, that is only a first approximation, especially if a is undefined. The semantics also differ depending on whether it is a simple variable assignment, a method assignment or an indexing assignment:

a    ||= b
a.c ||= b
a[c] ||= b

are all treated differently.

Save current user with created object

At first you need add user_id index to the childrens table.

Then

If you have login & logout functionalities, I mean session is working currently then how you manage the user session? Something like this?

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

If yes then go to create method and edit like below

@child = Child.new child_params
@child.user = current_user
@child.save

And remove this .merge(user: current_user) from child_params, it will work I hope.

If above solution does not work somehow then pass user_id manually with form like in the form

<%= f.hidden_field :user_id, value: current_user.id %>

Then the user_id add to the strong parameters like others attributes.

You can see the test like while user_id passing properly then what's happening like

Just For Testing Purpose

@child = Child.new child_params
@child.user = User.last
@child.save

Part 2

If you need to give permission to the children_controller like if user has parent then he/she access to the children_controller form then create a method like this

before_action :require_parants, only: [:new, :create] # top of the controller
private
# parant column on the users table is boolean true/false
def require_parants
if !logged_in? || (logged_in? and !current_user.parant?)
flash[:danger] = "Only parants can create child"
redirect_to root_url
end
end

The logged_in? based on this

# Returns true if the user is logged in, false otherwise.
def logged_in?
!current_user.nil?
end

then redirect to the root URL when the user is not a parent.

Hope it helps



Related Topics



Leave a reply



Submit