Bibek Sharma
Bibek Sharma

Reputation: 3330

Use string variable as field name in where condition in rails 4

I've a method in the controller which checks if a field's value already exist in database.In my case I've to check for the multiple fields such as username, email, and URL via AJAX.

So I wrote the function below

  def check_field_already_exist?(field, params )

    merchant_url = MerchantUrl.where(field: filter_params[field.to_sym]).first

     # here params[:id] is available only while editing the MerchantUrl
     is_available = if (params[:id] && merchant_url)
                 merchant_url.id == params[:id]
               else
                 merchant_url.blank?
               end
  end

and invoke this method as

  def is_name_available
    render json: check_field_already_exist?('username', params)
  end

  def is_url_available
    render json: check_field_already_exist?('url', params)
  end

  def is_email_available
    render json: check_field_already_exist?('email', params)
  end

but on execution it throws the error

Mysql2::Error: Unknown column 'merchant_urls.field' in 'where clause': SELECT merchant_urls.* FROM merchant_urls WHERE merchant_urls.field = 'http://localhost:3000'

So, Is there any method to use string variable as field name? Thank you.

Upvotes: 3

Views: 2306

Answers (4)

ReggieB
ReggieB

Reputation: 8257

It looks to me like you are doing this the wrong way round. As you are passing the id into the method (within params), why not use that to get the merchant_url and then check if the field has content:

def check_field_already_exist?(field, id=nil)
  if id && merchant_url = MerchantUrl.find(id)
    merchant_url.send(field).try('present?')
  else
    MerchantUrl.exists?(field => filter_params[field.to_sym])
  end 
end

You can then

def is_name_available
  render json: check_field_already_exist?('username', params[:id])
end

Though personally, I'd have a method that returned the model instance attributes hash as json, and then check through the contents of the hash with JavaScript client side. That way you can get the data you want with only one call back to the server (rather than one for each field).

Upvotes: 3

Shiva
Shiva

Reputation: 12592

I hope this works

def check_field_already_exist?(field, params )

    merchant_url = MerchantUrl.where("#{field}=?", filter_params[field.to_sym]).first

    is_available = if (params[:id] && merchant_url)
                     merchant_url.id == params[:id]
                   else
                     merchant_url.nil?
                   end
  end

But make sure field should not be something that end-user can set via params.. Other wise it would be extremely vulnerable.

Upvotes: 0

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230521

The proper way is to use the good old hashrocket syntax

merchant_url = MerchantUrl.where(field => filter_params[field])

Upvotes: 6

lx00st
lx00st

Reputation: 1596

In yor code field is a symbol that identifies column name. You should do like this:

merchant_url = MerchantUrl.where("#{field} = ?", filter_params[field.to_sym])

Upvotes: 1

Related Questions