Rails How to assign multiple values to an attribute - ruby-on-rails

I`m begginer in rails, so I am not even sure if this is possible, if not please write it to me.
My goal is to write a search function to search through db.
The form is based on the check_box_fields which sends two arrays clan and class. And then it search thorough a db. But I don`t know how to set more then one attribute value to record.
Search engine:
def self.school_search(clan, class)
School.where(clan: clan, class: class)
end
and in my seed file I created few objects:
schools = [
{ nazwa: "Smok Bushi",
clan: "Smok",
class: "Bushi"
},
{ nazwa: "Pajak Bushi",
clan: "Pajak",
class: "Bushi", "Shugenja"
}
]
schools.each do |school|
School.create(school)
end
Everything is well when I search for object one I send params clan: "Smok" and class "Bushi" and object is selected. But I want the second object to be found by either clan: "Pajak" class: "Bushi" or clan: "Pajak" class: "Shugenja". I tried to pass this value as an array but it didn`t help.
Edit: used english names for attributes

You can, actually, pass an array to the attribute, as you said. So maybe you're doing something else wrong.
Active Records' Documentation is clear about that (read the "conditions" sub-section).
Edit: Adding example code for clarification
# This works
Model.where(title: ['Hello', 'Rails'])

You can not assign multiple value for one attribute. Maybe you should create association school has many klasa and klasa belongs to school.
P.s. it is desirable to use english words instead of polish(klasa = class)

Related

Is it possible to refresh a property in Grails?

In order to refresh a domain object i.e to re-read the data from database we do refresh().
def b = Book.get(1)
…
b.refresh()
I am wondering whether we can refresh a property of the domain.
Suppose i have bound params to Book object and suppose i want to unbind the author property from the book object then is it possible to achieve that?
Let's consider the Book is defined as
class Book {
String title
String author
String category
}
Suppose I do bindData(bookInstance, params). This will bind to all properties. I want to unbind the author after bindData. Is this possible?
It sounds like you just want to exclude binding a particular property.
bindData(bookInstance, params, [exclude: 'author'])
will bind all of the Book properties except for those listed.
You can conversely use include to explicitly list which properties to bind from params.
bindData(bookInstance, params, [include: 'title', 'category'])
I solved this by using bookInstance.author = bookInstance.getPersistentValue('author').

Handling conditions at class level based on association

I'm not sure how to frame this question, I am looking to solve a design problem.
I'm using ActiveRecord.
An Agency can have multiple documents.
documents has a column additional_details of type jsonb. Contains hash details.
additional_details column has different set of key value pair based on agency.
Example:
doc1 = agency1.documents.first.additional_details => { xml_url: '', ... }
doc2 = agency2.documents.first.additional_details => { feed_url1: '', ... }
agency1 and agency2 are instance objects of Agency.
When I make a call to fetch the url like document.additional_details.get_url
I can write conditions like
def get_url
if agency1.name == 'Utah'
return additional_details[xml_url]
elsif
so on
elsif
so on
end
end
Which is not a good practice I feel.
I believe we can solve this at class level. Note I need to solve this on presentation layer, I'm using decorators .
Edit:
An particular agency will have same keys within additional_details column but values are certainly different.
I am assuming these are Active Record classes? Where is agency1 defined? You should almost never be hard coded based on specific instances, instead any such data should be part of the record and its instance.
It is especially unclear why you have different types of "URL" at all, and not just a simple url string column in the documents table. Why does agency1 use xml_url but agency2 uses feed_url1?
But as an example, if each agency has say a prefix defined (say the domain name / filestore, and the documents just the relative/local address), say:
agency1.document_root = "https://example.com/documents/"
agency1.documents.first.rel_url = "web/rails/rails_example.pdf"
Then in the Document class you might do:
def url
agency.document_root + rel_url
end
Which then gives you the:
agency1.documents.first.url
Add a field to your Agency model where you store the key to the url in the additional data hash. Let's say you name the field url_key. Then you can do
def get_url
additional_details[agency.url_key]
end
Note that I assume that get_url is a method on the Document model.

Extend array without creating new class in Rails 4

I am using an API and receiving a array of hashes. Lets say:
array = client.getObjects(123) //where 123 is some collection of object ID
I want to add some additional attributes to the array to use later in my view, like:
<%= array.getRequestor %> // return a string
What is the easiest way to do this? I was thinking about creating a new class that extends array but I wanted to know can I just add a string "requestor" attribute a lot easier?
Thanks
Extending a core class is not a good idea in general, especially when the additional responsibilities you want to add in are specific to your functional domain.
6 months down the line, somebody (perhaps yourself) will be trying to debug the code and wondering why does Array expose a random custom method.
It would be better to explicitly define your custom view object, perhaps by using a Struct, eg:
# my_view_object.rb
class MyViewObject < Struct.new(:hash)
def getRequestor
# manipulate / return specific hash data
end
end
# controller
#view_obj = MyViewObject.new(client.getObjects(123))
# view
#view_obj.hash # original hash
#view_obj.getRequestor # your custom attribute
Note that the intent of a Struct is to represent a custom data structure, not behaviour. If your custom method needs to do unrelated work, you might want to use a PORO (Plain Old Ruby Object) instead.
I'd say that extending Array sounds like a really bad idea. I would suggest you instead wrap the array in hash of your own. For example
my_hash = {getRequestor: ?, array: array}
and then use it like
<%= my_hash.getRequestor %>
as in your example code.

Where should method go (model?, somewhere else)

I've got a method in one of my models which returns data which will be fed into a charting gem.
class MyModel < ActiveRecord::Base
def ownership_data
format_data(item_ownerships.group(:owned).count)
end
end
I need to guarantee that the data return always has 2 values in the result. Something like this:
{ "yes" => 4, "no" => 2 }
In order to do this, I've written another method which is used in the first method:
def format_data(values)
values[false].nil? ? values = values.merge({ "no" => 0 }) : true
values[true].nil? ? values = values.merge({ "yes" => 0 }) : true
return values
end
My question is, where should this method go and how can I unit test it using rspec? I've currently got it in the model, however in trying to test it with rspec, my specs look like this:
let(:values) { { "yes" =>2 } }
it "it will return 2 values" do
result = MyModel.new.format_data(values)
expect(result.keys.count).to eq(2)
end
I'm not too happy about having to instantiate an instance of the model to test this. Any guidance is appreciated.
As AJ mentioned in the comment, we probably need more information to go on to give more specific advice. I'll give some anyway...
If you have a object that isn't necessarily depending on the model itself, you should consider moving it to a plain old ruby object or a service object. Those can live in a separate folder (lib/services) or in your models folder without inheriting from ActiveRecord::Base.
Your method could also be a class method def self.method_name(values, values_2) instead of a instance method (if you don't need specific values from the model).
When it comes to data manipulation for reporting for my projects, I've built specific folder of ruby service objects for those under 'lib/reports' and they take raw data (usually in init method) and return formatted data from a method call (allowing me to have multiple calls if the same data can be formatted in different output options). This makes them decoupled from the model. Also, this makes testing easy (pass in known values in Class.new expect specific values in method outputs.

Active record where query for value inside of an array

Question: Is it possible to build a class method scope that can query objects based on values inside an array in a table? If yes, how can I do this?
In my example, I have a “wells” table that has an array field called “well_tags”. I want to build a query that returns all objects that have a specified value (such as “ceramic”) in the wells_tags array. The basic query would be something like this:
#well = Well.all
#query = #well.where(“well_tags contains ceramic”)
And then the class method scope would look something like this, with the “well_tag_search” param passed in from the controller:
class Well < ActiveRecord::Base
def self.well_tag_filter(well_tag_search)
if well_tag_search.present?
where(“well_tags contains ceramic")
else
Well.all
end
end
I found another post that asks a similar question (see link below), but I cannot get the answer to work for me...the result is always 'nil' when I know there should be at least 1 object. I am a beginner using sqlite (for now) as my database and rails 4.0.
Active Record Query where value in array field
Thanks!
UPDATE: some progress
I figured out how to create an array of all the objects I want using the ‘select’ method. But I still need to return the results as an Active Record object so I create a class method scope.
#well = Well.select
{ |well| if well.well_tags.present?
then well.well_tags.include? ‘ceramic' end }
#well.class #=> array
Not sure where Show is coming from.
Can you try doing Well.all instead of Show.all?

Resources