Array search with ransack through a table - ruby-on-rails-4

I have a table called key_words which has one column called name.
Then I have another table called publications with a column called key_words which is of array type.
When I create a publication the value saved in key_words is something like this ["1", "29", "40"] (these are ids saved in key_words table)
How can I find a publication if I type for example computers in a searchable input?
In this moment I have a search_form_for to find by the publication title and description.
= search_form_for #search, url: publications_path do |f|
#custom-search-input
.input-group.col-md-12
= f.input :title_or_short_description_or_description_cont, input_html: { class: 'form-control input-sm' }, placeholder: 'Buscar', label: false

I would create a third table key_words_publications to store the relationship instead of the array column. Check out the docs for HABTM here.
class Publication
has_and_belongs_to_many :key_words
end
class KeyWord
has_and_belongs_to_many :publications
end
Then you should be able to do something like:
key_words_name_cont

Related

rails_admin get the current entity and display custom enum

I'm trying to customize an enum field with something else than only the name.
For example my entity record from database have columns as: name, postal_code, id etc ..
and I would like to have something like this in the dropdown "#{name} #{postal_code}, #{department}
I'm doing this:
field :city, :enum do
enum do
# Here I would like to get the entity from DB in order to have all
# columns to something similar as =>
entity.collect.each { |c| "#{c.name} (#{c.postal_code}), #
{c.department.name}"}
end
end
but I don't know how to get the active records (entity in my example) of the actual value of City entity.
How can I do this?
note: that department belongs to another model who is associated to City
Considering the OP comments i'm going to asume that the model in question has this association defined like this:
belongs_to :city
And the city field itself something like this
rails_admin do
edit do
field :city
end
end
Because this way rails admin will render a select drop down that will allow you to search the cities without loading them all.
After that on the City model you can define the title method, quoting the docs
By default it tries to call "name" or "title" methods on the record in question. If the object responds to neither, then the label will be constructed from the model's classname appended with its database identifier. You can add label methods (or replace the default [:name, :title]) with:
RailsAdmin.config {|c| c.label_methods << :rails_admin_title }
The title method can then be defined
class City < ApplicationRecord
def rails_admin_title
"#{self.name} (#{self.postal_code}), #{self.department.name}"
end
end
In a related issue, you will probably want to configure how rails admin searches for the city, i'll just link to the docs.
You can do it, but you need to define a name and a (stable)value for each select drop down, a simple hash out to do it like this:
field :city, :enum do
enum do
entity = bindings[:object]
City.all.map do |c|
{c.id => "#{c.name} (#{c.postal_code}), #{c.department.name}"}
end
end
end
Im assuming each city has an id, but you can use any value you want to store on that field on your DB.
So your users would see the nice formatted string, but rails admin would post the form with the city id on the city field.

Is it possible to apply the primary key of the row as an id attribute to each <td> when using django-tables2?

With django-tables2, i am trying to set the id of each element of my model as an "attribute" of every single <td> corresponding to a specific <tr>.
I'm using a dict in the Column Attributes definition like so:
class MainTable(tables.Table):
id = tables.Column()
Client = tables.Column(attrs={'td': {
'data-name': 'Client',
'data-type': 'text',
'data-pk': lambda record: record.pk,
'data-url': 'path/to/url',
'data-placeholder': 'New Client',
'data-title': 'New Client' }})
Every attribute is applying correctly except the 'data-pk'. Is there a way to get the primary key inside the dict? Or any other way to set this attribute using django-tables2 ?
Currently, you cannot do that on columns, but you can on rows:
class Table(tables.Table):
class Meta:
row_attrs = {
'data-pk': lambda record: record.pk
}
Which might make more sense anyway, since a record is mapped to a row, not to a single table cell in a row.
I can see the use for computable attrs with arguments on table columns, so if you decide you need it, you are welcome to open a Pull request.

Rails: Records of two models in one collection_select

Part 1: What i want is to fetch records of two tables in one collection select. Later, i want to perform search based on selected item.
So far i have managed to get the records in this manner in one select:
Controller:
#result1 = Model1.all
#result2 = Model2.all
#all = #result2 | #result1
View:
<%= collection_select :id,:id,#all, :id, :id,{prompt: "All Templates"} %>
The problem here is i want to display the name form Model1 and type from Model2.
Part 2 If the user selects the name, i want to get record from Model1 and if the type is selected, i want to get records form Model2.
All i am able to get is the id of both the models in one collection select. I am out of ideas. Let me know if any more details are required. Any help is appreciated. Thanks.
You've supplied :id to collection_select for the text_method. Check the docs to see how this helper works.
One solution would be to create an 'alias' method in each of your models which you can then call in collection_select:
model1.rb
class Model1
def text_value
name
end
end
model2.rb
class Model2
def text_value
type
end
end
I've named the method, text_value, for demonstration purposes. You may need to come up with a different name for that attribute.
Incidentally type as an attribute is reserved for Single Table Inheritance tables so it would be better to use a different attribute name.
in the view
<%= collection_select :id,:id, #all, :id, :text_value, {prompt: "All Templates"} %>

Retargeting the foreign key in Rails

tldr;
In Rails, how do you set the target column of a foreign key to be a column other than its parent’s id?
Efforts so far
This feels like it should be a simple operation, but I’m having little success. I have a parent model, Order, which has many OrderItems, but I want the foreign key of OrderItems to reference a composite of Order’s reference1 and reference2 fields.
I’ve looked at a few paths:
First try
class Order < ActiveRecord::Base
has_many :order_items, foreign_key: :order_reference,
primary_key: :unique_reference
inverse_of: :order
validates :reference1, uniqueness: { scope: :reference2 }
end
class OrderItem < ActiveRecord::Base
belongs_to :order, foreign_key: unique_reference,
primary_key: order_reference
inverse_of: :order_item
end
(Where I created a redundant-feeling unique_reference column, that we populated before creation with reference1+reference2, and gave OrderItem a corresponding order_reference column)
I tried a few variants of the above, but couldn’t persuade the OrderItem to accept unique_reference as the key. It managed to link records, but then when I called OrderItem#order_reference, instead of contents matching the corresponding Order#unique_reference field it would return a stringified version of its parent’s id.
Second try
I removed the unique_reference column from the Order class, replacing it with a method of the same name and a has_many block:
class Order
has_many :order_items, -> (order) { where("order_items.order_reference = :unique_reference", unique_reference: order.unique_reference) }
def unique_reference
"#{reference1}#{reference2}"
end
end
class OrderItem < ActiveRecord::Base
belongs_to :order, ->(item){ where("CONCAT(surfdome_archived_order.source, surfdome_archived_order.order_number) = surfdome_archived_order_items.archived_order_reference") }
end
This time, calling Order#order_items raises a SQL error:
Unknown column 'order_items.order_id' in 'where clause': SELECT order_items.* FROM order_items WHERE order_items.order_id = 1 AND (order_items.order_reference = 'ref1ref2')
Every SQL query I’ve thought to try has the same underlying problem - somewhere, Rails decides we’re still implicitly trying to key by order_id, and I can’t find a way to persuade it otherwise.
Other options
At the moment my options seem to be to use the Composite Primary Keys gem or just ignoring Rails' built-in associations and hacking our own with db queries, but neither seems ideal - and it seems like Rails would surely have an option to switch foreign keys. But if so, where is it?
Thanks,
Sasha

Group through joined tables Rails 4

I was hoping this would be simple, but in essence I would like to count the number of Users who have certain attributes through a join table in Rails 4.
I have a table called Views which holds three columns:
t.references :viewer
t.references :viewed
t.boolean :sentmessage, default: false
I then have the fields references as:
belongs_to :viewer, :class_name => "User"
belongs_to :viewed, :class_name => "User"
Each user record is then associated with a number of other records like Stats, Questions and a number of others. I'm interested in effectively counting how many viewers of a viewed record are Male or Female (and other search fields) which is data all held in User.stat.gender.name etc.
I'm trying to use a group statement but have no idea how to drill down and count the number of Males etc. I've tried:
#results = View.where(viewed: 63).group("viewer.stat.gender")
But this is so wrong it's frightening.
Any help to do this would be appreciated.
I worked it out finally. For anyone else who is interested:
View.where(viewed_id: 63).joins(viewer: {stat: :gender}).group("name").count
Didn't realise what an INNER JOIN was but some research and some trial and error means I can now show information about the users who have visited.