rails activerecord _id suffix in property - ruby-on-rails-3

What is the implication of using a "_id" suffix for a field name in active record?
t.string :foo_id
Does this always presume that it is a foreign key to "foo" table?
Is it better to use something like
t.string :foo_id_value
to avoid ambiguity with rails?
The idea is that this id value has nothing to do with foreign keys and may not necessarily be unique.

You may wind up with a strange validation message.
Given a Rails 3 model with a validation like validates :foo_id, :presence => true,
when you leave foo_id blank and validate,
then you'll get the message "Foo can't be blank" instead of the expected "Foo id can't be blank".

It's a matter of convention. In my experience you won't have any problems unless you do belongs_to :foo
If you want to avoid ambiguity for other developers, then yes, it's a good idea to avoid it.

Related

ThinkingSphinx::SphinxError index item_core,item_delta: query error: no field 'deleted_at' found in schema

I have an Item model:
class Item < ActiveRecord::Base
...
define_index do
...
has deleted_at
indexes deleted_at
end
...
Then I stop the server, run rake ts:rebuild && rake ts:reindex && rake ts:restart, restart the server. And I still get the error.
The query that triggers the error is this:
Item.search({conditions: {deleted_at: nil}})
What's wrong ?
Note: I am using acts_as_paranoid. My database is migrated, the table items has the column deleted_at.
Somewhere in schema.rb:
...
create_table "items", :force => true do |t|
...
t.datetime "deleted_at"
There's a couple of related issues here:
You've got an attribute and a field with the same name (deleted_at) - you should alias one to have a different name using the :as option. Otherwise, Sphinx gets confused when reading the generated SQL data.
You've got a date column as a field, when it almost certainly isn't required - do you want users searching by deleted_at, or is it purely something for you to manage internally? I'm guessing the latter. So, remove the indexes deleted_at line.
You're setting a field condition in your search call when it should really be an attribute filter - which is done using the :with option.
Sphinx has no concept of nil, but should translate NULL values from the database into zeros.
So, with all that in mind, your index definition should rather be:
define_index do
# ...
has deleted_at
end
Run rake ts:rebuild to ensure Sphinx is aware of the changes and your index files are updated.
Then your search call is:
Item.search with: {deleted_at: 0}

What is the meaning in Rails of the name parameter in add_index :sections, [:name, :page_id]?

I am trying to understand what is the meaning in rails of the :name parameter in the context of adding an index. Does it always have to be like this? If so this seems very redundant, so I figured I am missing something. Rails 3.2.13
add_index :sections, [:name, :page_id]
This line adds a compound index to table sections, consisting of two columns, name and page_id.

Rails - how do I validate existence of a row referenced by foreign key

Given that the "Rails Way" seems to be not to use foreign key constraints, I'm looking for an alternative that will allow me to validate that the row a foreign key references does in fact exist in TableA before I save an object in TableB with table_a_id.
The only resource I've found to do this so far (can't find a link to the blog post it was mentioned in, was dated 2007) doesn't appear to be compatible with Rails 3.2, so can anyone suggest a way of doing this?
I'm currently looking at creating a validator to manually assign to the relevant attributes in my models, but I can't work out how to do it with validate_each(object, attribute, value).
Simply use like below,
validates :user, presence: true
It will automatically check the existence of user record in db.
Reference from the Active Record Validation - presence:
If you want to be sure that an association is present, you'll need to
test whether the associated object itself is present, and not the
foreign key used to map the association. This way, it is not only
checked that the foreign key is not empty but also that the referenced
object exists.
There is a plugin that helps you with this for belongs_to associations: Validates existence of. But, maybe you can add your own validation? What about something like this:
# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists
def user_id_exists
return false if User.find_by_id(self.user_id).nil?
end
I had problems with this piece of code:
return false if User.find(self.user_id).nil?
I had to catch the ActiveRecord exception when no matching record was found. nil? does not work when no record is found; the exception is thrown before nil? is executed.
# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists
def user_id_exists
begin
User.find(self.user_id)
rescue ActiveRecord::RecordNotFound
errors.add(:user_id, "user_id foreign key must exist")
false
end
end
This is useful when you use invalid? assertions in unit tests.
request.user_id = unknown
assert request.invalid?
request.user_id = 1
assert request.valid?
Note that as of Rails 3.2, the validates_presence_of works exactly the way you want it to in this case and you don't have to build a complicated structure like the above answers or even use the nice validates_existence_of gem.
You need to specify the inverse_of option and validate that it's presence is true.
From the Active Record Validations Guide:
In order to validate associated records whose presence is required,
you must specify the :inverse_of option for the association
I dislike exceptions. I solved this problem by doing this:
class Foo < ActiveRecord::Base
validate :bar_exists
protected
def bar_exists
if !User.where(bar_id: self.bar_id).exists? then
errors.add(:bar_id, 'A valid bar_id is valid.')
end
end
end

Issue with pushing additional values in a embeds_many mongoid relation

I have been breaking my head around this for a long time now. Not sure if my approach is correct or if its not possible using mongoid. SO without further adieu, here is the problem:
I have the following 2 models:
def user
embeds_many :needs, :class_name => "Property"
embeds_many :skills, :class_name => "Property"
end
def property
end
Both these models of course have other code but I have skipped that for brevity.
With this structure I am able to access/add "Property" data as embedded "needs" & "skills" on my user model. Something like this works flawlessly
User.first.update_attributes(skills: [Property.first])
The problem is something like this doesn't work.
User.first.skills.push(Property.first)
User.first.skills << Property.first
There is no error. Both the above statements return true on console. But the values don't persist to the DB.
I basically want a Property model which can be maintained/created independent of the User model, thats why the "embedded_in" on Property is missing in my code.
The question is, am I doing it right? Or there is their a different way that I should go about the design of these models?
Cage is right. You will need to put the embedded_in on the Property model if you want the persistence to work properly. If you want to manage the lifecycle of Property outside the User model, you will have to use 'has_many'.
Please add more details as to what exactly is the purpose of doing what you are doing. I am going to make some assumptions-
Needs and skills are a global list of values, that should be maintained separately
User can have a subset of skills and needs
You want to store the needs and skills as 'plain string' and not references so you can query them without referencing the needs and skills collection. This reduces one query
If the above is correct, then you can use custom keys to store the needs and skills-
class Property
include Mongoid::Document
field :text, :type => String
field :_id, type: String, default ->{ text }
end
class User
include Mongoid::Document
has_many :needs, :class_name => "Property"
has_many :skills, :class_name => "Property"
end
Now you can do something like-
User.first.need_ids
This will give the text of the need and you can avoid another query.
Note- that this is potentially very risky if your 'Property' objects are mutable.
For solution try doing this
u = User.first
u.skills.push(Property.first)
u.skills << Property.first
it will work fine.

Testing route in controller

I have a Rails 3.0 web app that allow user to create own path to the application.
example : www.my_app.com/user_company_name
So I store a custom path in user DB field. User can changing path throught a input.
I have added this validation in model
validates_presence_of :custom_page
validates_format_of :custom_page, :with => /^([a-z]|[0-9]|\-|_)+$/, :message => "Only letter (small caps), number, underscore and - are authorized"
validates_length_of :custom_page, :minimum => 3
validates_uniqueness_of :custom_page, :case_sensitive => false
But I don't know how I can validate url to check it isn't in conflict with another route in my routing.
For example in my route.rb I have
resources :user
Validation need to don't allow using www.my_app.com/user, how I can do that?
Thanks, vincent
In your routes, you match the company name to a variable
match 'some_path/:company_name.format'
you can then do the lookup using company_name which rails will populate for you.
Validating the uniqueness of the custom_page variable should be enough to ensure there's no overlap. (note that validate uniqueness of doesn't scale -- if this will be big, you need a db constraint as well) as long as users can only specify one field.
If you're letting users specify
'some_path/:custom_path_1/:custom_path_2.format'
then you have to validate across both fields, and now it's getting messy. Hope you're not doing that.
You can try a custom validation to weed out "user"
validate :custom_page_cant_be_user
def custom_page_cant_be_user
errors.add(:custom_page, "can't be `user`") if self.custom_page =~ /^user$/i
end
assuming :custom_page comes in as a basic [a-z], if :custom_page has /user you need to update the regex a bit.