Simple question:
I've got two models: Show and Contact. What I'd like to do is search for either a Show#id or a Contact#name. So my models are set up as follows:
class Show < ActiveRecord::Base
searchable do
text :id
end
end
class Contact < ActiveRecord::Base
searchable do
text :name
end
end
Then I run searches as follows:
Sunspot.search(Contact, Show) do
keywords(MY_QUERY)
end
This works great for finding Contacts by their name, but never works with the Show#id field. Can anyone explain why this is?
Joe
The id field is an integer, so you should have integer :id in the model. You need to specify the correct type of database column. Check out the example at http://sunspot.github.com/.
Related
I have 2 classes with:
class User < ApplicationRecord
has_one :address
end
class Address < ApplicationRecord
belongs_to :user
I need to write code, which will print the value of attribute with the name 'postcode' of 100 users from database.
I have some code on this point, but not sure that it's a good way to solve the problem:
#users = User.all
#users.limit(100).each do |user|
puts "#{user.postcode}"
end
Who has better ideas?
I'd use pluck
puts User.limit(100).pluck('postcode')
# or
puts User.joins(:address).limit(100).pluck('addresses.postcode')
Pluck is best suited for your scenario.
User.where(condition).pluck(:postcode)
(#where condition is optional)
Event if you want to fetch other column with postcode you can simply include that in pluck. for e.g.
User.where(condition).pluck(:id, :postcode)
(#using multiple column inside pluck will only work with rails4 and above)
Hello I am new to rails and I'm creating an application to practice and learn. I have a issue which I don't know how to solve.
If I generate a model User and I want to include a section in the model where I name it investor_or_startup. When I create the form for a user to fill it out I want the user to only be able to fill in the blank with the word Investor or Startup. How would I go about this?
You could create a selector field in your form.
I would share some code but I think as a new rails developers, you should get used to reading and understanding the docs, as that is invaluable.
http://guides.rubyonrails.org/form_helpers.html#making-select-boxes-with-ease
Add a validation in your model for that specific attribute, if it's called investor_or_startup, then using validates specify this attribute, use the format option, and optionally you can add a message for the user, like:
class User < ApplicationRecord
validates :investor_or_startup,
format: {
with: /Investor|Startup/,
message: 'Two valid options are Investor or Startup'
}
end
The with option inside format accepts a regular expression, in this case to check for the specific word Investor or (|) Startup, it's case sensitive, so lowercase letters would make an invalid input. If you want to change to case insenstive then consider adding i at the end of your expression, like /investor|startup/i.
The message options accepts an string which you can use to display a message for the user.
You can keep reading about this here.
The most common way of doing thin in rails would be to add a role attribute to your User model. In this case, role replaces start_up_or_investor. You would start by using a migration to add a field called role of type :integer to your users table.
Next you would add the following line to your User model:
enum role: [:investor, :start_up]
You can read more about enum here.
Finally, you can use a select_tag in a Rails form helper to select one of the enum options. There are many ways to use a select_tag with an enum. A quick internet search will reveal many blogs and SO posts on the subject.
Bottom line: I recommend using an enum for this sort of thing.
So you have a User model and that user could possibly be an investor or a startup. To start off you could add some kind of "type" attribute that will query whether the user is a startup or an investor. User.type #=> "startup" or User.type #=> "investor". From there you could set up your form_for user and use a select field that would allow the user to select their value for the type attribute <%= f.select(:type, ...) %>
Like Sam suggested, I encourage you to study the rails guides,(particularly form helpers) to help you understand how a form works.
Adding roles to uses is a common programming problem. There are two decent ways to solve this (and many bad ways).
1. Use an ActiveRecord::Enum
class User < ApplicationRecord
enum role: [:investor, :start_up]
end
An enum is a integer column that maps to specific values. In this case investor = 0, start_up = 1.
To create an input based on this you can use the enum mapping:
<%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}) %>
While simple the major limitation is that a user can only ever have one role.
2. Setup a many-to-many association
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles
scope :with_role ->{|*names| joins(:roles).where(name: names) }
def has_role?(name)
roles.where(name: name).exist?
end
end
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
class Role < ApplicationRecord
has_many :user_roles
has_many :users, through: :user_roles
end
This lets you add and remove roles from a user seperately and often is a better fit for real world use cases. The Rolify gem is an excellent example of this pattern.
To allow a user to select roles you can use a checkbox:
<%= f.collection_check_boxes(:role_ids, Role.all, :id, :name) %>
I have a model called Topic and another called Product.
Here's how the Topic model looks,
class Topic < ActiveRecord::Base
belongs_to :product
end
Topic has columns "title" and "body".
And here's Product,
class Product < ActiveRecord::Base
has_many :topics
end
Product has columns "name" and "desc". Name is unique.
When I create a new Topic, I want the title of Topic to be stored in Name of Product, only if Name doesn't exist yet. If it does, it should not make any change.
But how do I do this?
UPDATE:
User comes to /topics page, enters Title and Body.
What the Topics_controller should do,
1. Read the Title that has been given by the user.
2. Check if that Title already exists in the Products.
3. If it doesn't add it.
4. If it does, don't do anything.
I don't understand how these two models are linked together and how I can access records from the model.
You can achieve this by using one of the callbacks, which ActiveRecord provides.
I'm not sure if I understand your requirements perfectly, so maybe you need to alter the following example:
class Topic < ActiveRecord::Base
belongs_to :product
before_save :add_product_name
private
def add_product_name
self.product.name ||= self.title if Product.find_by(name: self.title).nil?
end
end
You can write a callback like before_create :add_topic_name
Where that method will find product name of topic and assign it to the title of product.
Your requirements are a bit unclear here. Can you specify what your end goal is, from a Behaviour point of view?
If i understand correctly though, why not just overwrite the title method for Topic. This way you are not duplicating data in the DB.
within your Topic class:
class Topic < ActiveRecord::Base
def title
read_attribute(:title) || product.name # will get title of #topic if not nil, else product name
end
end
I have a MongoID User model
class User
include Mongoid::Document
field :name
embeds_many :watchlists
end
which embedded one to many
class Watchlist
include Mongoid::Document
field :description
embedded_in :user
end
I want to search full text into :description field which is in Watchlist child embedded in User. The most heavy search goes through 1.5k descriptions, with a max of 30, 40 words each.
The constrain here, is that I'll deploy on Heroku and they have not free plan for indexing currently.
Then I've tried with mongoid_fulltext (as well as mongoid_search and mongoid-searchable) but without success.
Does anybody have an idea how to do that ?
UPDATE:
This is an example of mongoid_fulltext. The User model embeds many Watchlist(s). I'm searcing a string in :description field, which is in Watchlist child doc :
class Watchlist
include Mongoid::Document
field :description
...
embedded_in :user
end
Watchlist is embedded in User :
class User
include Mongoid::Document
include Mongoid::FullTextSearch
field :name
...
embeds_many :watchlists
def search_in_description
self.watchlists.map{ |w| w.description }.join(' ')
end
fulltext_search_in :search_in_description
end
... but in that way, running User.fulltext_search("a presentation framework based on the power of CSS3") gives me back just the parent doc causing the match (a user instance) and not the watchlists doc ( the child instance ).
See the output: http://pastie.org/3226179
How can I get just the matching "watchlists"? ( I tryed few ways without success )
In MongoDB you cannot query directly for embedded documents. You can query they way you explained in the example to get the parent document, then query on the returned top document user for the desired embedded document among current user watchlists.
If you're going to do that frequently, perhaps you might want to consider using relational has_many rather than embeds_many.
Ruby: 1.9.2
Rails: 3.0beta3
I need some help with associations in Rails 3.
I have the following models (see excerpts below):
School, State, SchoolLocale
The schools table has the following fields:
id, name, state_id, school_locale_id
The states table has the following fields:
id, abbr, name
The school_locales table has the following fields:
id, code, name
Unfortunately, my data-source didn't have IDs for school_locales. Thus, the data stored in the 'school_locale_id' field in the schools table actually maps to the 'code' field in the school_locales table.
school.rb:
class School < ActiveRecord::Base
belongs_to :state
belongs_to :school_locale
end
state.rb:
class State < ActiveRecord::Base
has_many :schools
end
school_locale.rb:
class SchoolLocale < ActiveRecord::Base
has_many :schools
end
I would like a query for a given school, let's say School.find(1), that would output the school name, the state name and the school-locale name. I assume that I need to add an index to the 'code' field in the school_locales table and somehow specify it as a foreign key, but I'm not certain. Any help would be appreciated.
This doesn't exactly answer your question, but I think it is a useful bit of information. Regarding your use of a states table, let me refer to Surrogate Vs. Natural/Business Keys.
#Ted says here:
Remember there is nothing special about a primary key, except that it is labelled as such. It is nothing more than a NOT NULL UNIQUE constraint, and a table can have more than one.
If you use a surrogate key, you still want a business key to ensure uniqueness according to the business rules.
There's no point in having a state_id foreign key that links to a states table. Each state already has a unique id; its 2-letter abbreviation. This unique id is just as good as a numeric one. And because this data doesn't change often, there's no harm in having it statically defined within your application somewhere.
I'm not really sure about it, but you could try using this:
class SchoolLocale < ActiveRecord::Base
has_many :schools, :primary_key => :code
end
Let me know if it works :]