Call method in model Rails - arrays

I have method called check_field, purpose of this method is for checking is there multiple value when input form.
I was think maybe I can check with multiple array on rails. I found some code on this link to check duplicate value inside array. So, I implement that method (difference) on my model
, but I got stuck when implement to my Model, the methot won't called.
NoMethodError (undefined method `difference' for ["vvvv", "vvvv", "xxxxxxxxx", "xxxxxxxxx"]:Array):
here my Code.
class Model < ApplicationRecord
has_many :child_models, -> { where(active: true) }, :foreign_key => :model_id, :dependent => :destroy
accepts_nested_attributes_for :child_models, :allow_destroy => false
before_validation :check_field, :before => [:create]
def check_field
all_field = Array.new
child_models.each do |data|
all_field << data.field
end
uniq_field = all_field.uniq
result = uniq_field - all_field.difference(uniq_field)
errors.add(:field, "Field must be Different")
end
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
the field that I want to validate is on child_models,
class ChildModel < ApplicationRecord
validates :field, presence: { message: "Field" + I18n.t("sys_err_is_required"), :if => :active?, :scope => [:active] }, :uniqueness => { :message => 'Field is already exist', :if => :active?, :scope => [:active], :case_sensitive => false }
end
I was try to put check_field method on ChildModel, it didn't work, because the parameters can be read on Model class.
so then any solution for this case?
thanks.

you should use self.difference to call your method, because it is a classmethod. see https://dev.to/adamlombard/ruby-class-methods-vs-instance-methods-4aje
...
result = self.difference(uniq_field)

Related

How to insert into a table based on an Eloquent relationship an array of foreign keys

I have two models TeamMember and ProjectRequest.
A TeamMember can have one ProjectRequest, that is why I created the following Eloquent relationship on TeamMember:
class TeamMember extends Model {
//
protected $table = 'team_members';
protected $fillable = ['project_request_id'];
// Relations
public function projectTeam() {
return $this->hasOne('\App\Models\ProjectRequest', 'project_request_id');
}
}
In my Controller I want to query both tables, however it returns the failure message.
What is important to know is that $request->projectTeam is an array of emails, looking like this:
array:2 [
0 => "mv#something.com"
1 => "as#something.com"
]
Meaning that I need to bulk insert into team_members table the project_request_ id for each team member where the emails are in the array.
How can I do that in the right way? The following is my attempt:
public function createProjectTeam(Request $request){
try {
$title = $request->projectTitle;
$TeamMember = $request->projectTeam;
$projectRequest = ProjectRequest::create(['project_title' => $title]);
$projectRequestId = $projectRequest->id;
$projectTeam = $this->teamMembers->projectTeam()->create(['project_request_id'=> $projectRequestId])->where('email', $TeamMember);
//$projectTeam = TeamMember::createMany(['project_request_id' => $projectRequestId])->where($TeamMember);
//dd($projectTeam);
return $projectRequest.$projectTeam;
} catch(\Exception $e){
return ['success' => false, 'message' => 'project team creation failed'];
}
}
There are a few things you can do.
Eloquent offers a whereIn() method which allows you to query where a field equals one or more in a specified array.
Secondly, you can use the update() method to update all qualifying team members with the project_request_id:
public function createProjectTeam(Request $request)
{
try {
$projectRequest = ProjectRequest::create(['project_title' => $request->projectTitle]);
TeamMember::whereIn('email', $request->projectTeam)
->update([
'project_request_id' => $projectRequest->id
]);
return [
'success' => true,
'team_members' => $request->projectTeam
];
} catch(\Exception $e) {
return [
'success' => false,
'message' => 'project team creation failed'
];
}
}
I hope this helps.

Symfony3 how to bind an array with Doctrine 2

I have an array $brands as parameter of my repository function public function getBrandsByFilter($brands). I rescue this array from an ajax POST method and it looks like at :
$brands = ["brand"
[
"caporal" => "caporal"
"adidas" => "adidas"
]
]
I'd like to pass each values (caporal, adidas) of my array as arguments of my WHERE query clause of my repository but I have this exception :
An exception occurred while executing 'SELECT a0_.brand AS brand_0 FROM article a0_ WHERE a0_.brand IN (?, ?) GROUP BY a0_.brand' with params ["caporal", "adidas"]:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
Here is my repository ArticleRepository.php :
public function getBrandsByFilter($brands)
{
$qb = $this->createQueryBuilder('a');
$qb
->select('a')
->andWhere('a.brand IN (:brandFilter)')
->setParameter('brandFilter', $brands, Connection::PARAM_STR_ARRAY);
return $qb->getQuery()->getResult();
}
UPDATE : THIS ISSUE IS RESOLVED, IT CAME OF THE WRONG FORMAT OF THE ARRAY AS SAID IN THE COMMENTS. BUT ON THE OTHER SIDE I HAVE A NEW FOLLOWING PROBLEM.
In my controller I retrieve well the result of my query getBrandsByFilter() but I don't get to send it in a jsonResponse()toward Ajax.
Here is my controller code :
/**
* #Route("/ajax/request", options={"expose"=true}, name="ajax_request")
* #Method({"POST"})
*/
public function ajaxRequestAction(Request $request)
{
if ($request->isMethod('post')) {
$brands = $request->request->get('brand');
$repository = $this->getDoctrine()->getRepository('ArticleBundle:Article');
/* I retrieve my query result */
$articles = $repository->getBrandsByFilter($brands);
/* And send it toward Ajax */
$response = new JsonResponse();
return $response->setData(array('data' => $articles));
}
}
And here my ajax function :
$('#submitFilter').click(function () {
$.ajax({
type: 'POST',
url: Routing.generate("ajax_request"),
data: { brand: selectedBrand },
dataType: 'json'
})
// HERE I WANT RETRIEVE MY JsonRESPONSE
.done(function( data ) {
console.log(data);
for ( var i = 0; i < data.length; i++ ) {
Object.keys(data[i]).forEach(function (key) {
var propertyData = data[i][key];
//console.log(key);
//
})
}
});
})
When I debug the $articles variable in my controller, I have an array of objects like this :
array:8 [▼
0 => Article {#612 ▼
-id: 203
-fosUserId: null
-name: "article 1"
-category: "sous-vêtements"
-brand: "caporal"
-model: "running"
-gender: "unisex"
1 => Article {#610 ▶}
2 => Article {#631 ▶}
3 => Article {#619 ▶}
4 => Article {#657 ▶}
5 => Article {#635 ▶}
6 => Article {#695 ▶}
7 => Article {#633 ▶}
]
But when I debug data in my ajax I have an array of empty objects :
data: Array(8)
0: {}
1: {}
2: {}
3: {}
4: {}
5: {}
6: {}
7: {}
I don't know why I retrieve an array of EMPTY objects while the one that I send in the JsonRESPONSE is filled. Thank you for helping me understand.
$brands array the content should be in this way;
$brands = [
["caporal" => "caporal"], ["adidas" => "adidas"]
];
Or;
$brands = [
["caporal"], ["adidas"]
];
It will work but i think you should not use ->andWhere, ->where working this case.
I find the solution in an other issue wich unfortunately I have not seen before.
You have to replace getResult by getArrayResult to get an array well formatted of the query result. See the solution of the issue
public function getBrandsByFilter($brands)
{
$qb = $this->createQueryBuilder('a');
$qb
->select('a')
->andWhere('a.brand IN (:brandFilter)')
->setParameter('brandFilter', $brands, Connection::PARAM_STR_ARRAY);
/* Here replace getResult() by getArrayResult() */
return $qb->getQuery()->getArrayResult();
}
And in teh controller :
/**
* #Route("/ajax/request", options={"expose"=true}, name="ajax_request")
* #Method({"POST"})
*/
public function ajaxRequestAction(Request $request)
{
if ($request->isMethod('post')) {
$brands = $request->request->get('brand');
$repository = $this->getDoctrine()->getRepository('ArticleBundle:Article');
$articles = $repository->getBrandsByFilter($brands);
return new JsonResponse($articles);
}
}

Multiple collections in an array (session variable) — Property does not exist

I'am trying to fetch a session variable if the user is a guest. The variable is called "cart" and is set like this:
$product = new Collection((object) [
'product_id' => $request->pId,
'amount' => $request->amount,
'variations' => $variations
]);
Session::push('cart', $product);
Then I later fetch it:
if(Auth::check()){
$cartProducts = ShoppingCartItem::where('user_id', '=', Auth::user()->id)->get();
}else{
$cartProducts = Session::get('cart');
}
foreach($cartProducts as $product){
dd($product);
$totalAmount += $product->amount;
$totalPrice += (PriceHelper::getProductPrice($product->product->id, $product->amount));
}
The problem here is that dd($product) still outputs an array (the session variable array I assume) which means that for example $product->amount does not exist.
This is the output from dd($product):
You can either access the values using get():
foreach ($cartProducts as $product) {
$totalAmount += $product->get('amount');
$totalPrice += PriceHelper::getProductPrice($product->get('product_id'), $product->get('amount'));
}
or as an array:
foreach ($cartProducts as $product) {
$totalAmount += $product['amount'];
$totalPrice += PriceHelper::getProductPrice($product['product_id'], $product['amount']);
}
or you could use sum() on the collection instead of using foreach:
$cartProducts = collect(Session::get('cart'));
$totalAmount = $cartProducts->sum('amount');
$totalPrice = $cartProducts->sum(function ($product) {
return PriceHelper::getProductPrice($product['product_id'], $product['amount']);
});
Edit
For a quick fix if you need $product to be an object you could do something like:
$cartProducts = collect(Session::get('cart'))->map(function ($item) {
return (object)$item->toArray();
});
Hope this helps!

How to exclude an array of id's from a find-method?

I'm calling an array of recommended products (based on the predictor-gem) and want to exclude the products of the current_user from that set. I think that I'm using the proper condition for it (" != ?") but just not in the correct way. #products_rec should give that final array.
Here's the specific code in my product_controller.rb:
recommender = ProductRecommender.new
products = current_user.products
#product_rec = (recommender.similarities_for("product-#{#product.id}")).map {|el| el.gsub(/(.*\-)[^\d]*/, "")}
#products_rec = Product.find(#product_rec, :conditions => ["id != ?", products.id])
and here's my model, product.rb:
class Product < ActiveRecord::Base
include Reviewing
include PublicActivity::Model
tracked
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
belongs_to :category
belongs_to :benefit
has_many :subscriptions
has_many :users, through: :subscriptions
has_many :benefits
has_many :projects, through: :benefits
belongs_to :user
validates :name, presence: true, length: { maximum: 200 }
validates :gtin, presence: false
validates :content, presence: false, length: { maximum: 2000 }
validates :video, presence: false
validates :tag, presence: false
validates :project, presence: false
validates :category, presence: false
validates :user, presence: false
has_attached_file :image, :styles => { :medium => "680x300>", :thumb => "170x75>" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
I want to exclude the products from the current_user, based on the users through subscriptions (see model).
How can I get this to work, any ideas?
Final code:
Based on the answer of #Humza, I've added the following working code to my product_controller.rb:
recommender = ProductRecommender.new
products = current_user.products.select("id")
#product_rec = (recommender.similarities_for("product-#{#product.id}")).map {|el| el.gsub(/(.*\-)[^\d]*/, "")}
#products_rec_array = Product.find(#product_rec)
#products_rec = Product.where(id: #products_rec_array).where.not(id: products)
To find products with id not in array, you must do this:
array = current_user.products.pluck(:id)
Product.where('id NOT IN (?)', array) # '?' is surrounded by paranthesis
But since a product belongs to a user, you can simply do
Product.where('user_id != ?', current_user.id)
You can also use the not method like so:
Product.where.not(id: array)
Product.where.not(user_id: current_user.id)
Edit:
If you want the base products to be from some other list, this can help:
base_product_ids = some_list.map(&:id) # assuming this is an Array
Product.where(id: base_product_ids).where.not(user_id: current_user.id)
If some_list was an ActiveRecord::Relation, you could have simply done:
some_list.where.not(user_id: current_user.id)

Return Image URL from Paperclip using RABL

I have a user model with Paperclip for avatars and I need to be able to return the image_url for each size (small, medium, large) using RABL.
In mongoid model i would simply do self.avatar(:original) but now nothing works, I just get an empty response in the attachment
"user" : {
"id" : "50b204e10eae9c55fa000028",
"paperclip::attachment" : {},
"name" : "My Name"
}
/models/user.rb
has_mongoid_attached_file :avatar,
:styles => {
:original => ['1000x1000>', :jpg],
:small => ['64x64#', :jpg],
:medium => ['250x250', :jpg],
:large => ['500x500>', :jpg]
}
/views/posts/base.json.rabl
child :user do
attributes :id, :name
child :avatar do
attributes :original
end
end
Try this:
child :user do
attributes :id, :name
node :avatar_original do |u|
u.avatar(:original)
end
end

Resources