Mapping relationships with custom names in Rails Admin - ruby-on-rails

I am using rails admin, and it works fine except for a pretty big issue. I have custom relationships in mongoid, and rails admin is not allowing me to edit that field.
My relationship definition in mongoid:
class Content
belongs_to :lesson, :inverse_of => :reading_material, class_name: "Lesson"
class Lesson
has_one :reading_material, :inverse_of => :lesson, class_name: "Content"
Note that it is a rather straight forward relationship. But this is what I see this in rails admin:
Surely there must be a way to tell rails admin what to do here?

Related

Rails Unconventional DB Structure, is this problematic for associations?

My company's old team leader had fairly little knowledge of Ruby on Rails and used weird convention for the db structure for associations.
Let's say I have a User model and a Role model, and that a user belongs to a role.
What I would consider typical:
rails g migration AddRoleToUsers role:references
# app/models/user.rb
belongs_to :role
# app/models/role.rb
has_many :users
But I can clearly see that something else has happened.
Whenever I User.new, I get something like:
#<User stuffs, role_id: nil>
In the models I've got
# app/models/user.rb
belongs_to :role, :class_name => 'Role', :foreign_key => :role_id
# app/models/role.rb
has_many :users
This pattern litters a good part of our application. I can tell that these columns are index, but don't actually have a foreign keys.
First question, is this problematic? To me, this implies referential integrity issues.
Second question, how can I add a foreign key after the fact and preserve existing data?
I'm using a gem called data-migration, which I hope can help me preserve the information.
This is just a verbose way of writing what Rails will do automatically by convention.
In the User.role relationship, this:
belongs_to :role, :class_name => 'Role', :foreign_key => :role_id
is equivalent to this:
belongs_to :role
Rails can infer the class_name and foreign_key based on the name of the relationship. It's just a redundancy that won't hurt in this case.
The foreign_key is actually the name of the field that's used to store the id value for the relationship, it's not a database foreign key at all.
You can add a database foreign key for these relationships by creating a migration or each table that you want to update. There's a great answer for that in Adding foreign key to a rails model that gives the step-by-step instructions to do it.

How to define dynamic has_many relationship depending on if another model/table exists in rails 3.2.12?

There are customers and projects model in our rails app. However project model may or may not present along with the customer model. Their relationship are:
class Project
belongs_to :customer, :class_name => 'Customer'
end
class Customer
has_many :projects, :class_name => 'Project', :conditions => if projects model exists
end
Basically we would like to make the has_many in customer model dynamic depending on if the project model exists. Is this something doable in rails 3.2.12? Thanks for the help.
I'm not sure I follow. If you need to have a dynamic association based on if the associated class is defined, then you'd write something along these lines:
class Customer
if defined? Project
has_many :projects, :class_name => 'Project'
end
end
If you meant a model like an object or record in database, then I'm not sure why the association can't stay where it is.
Update
Yes you can do that in one line. But take caution, that this woun't work as expected in development environment, since config.cache_classes is set to false, the 'defined? Project' will always return nil unless you explicitly call it.
If you need to test this behaviour then set config.cache_classes = true in your development.rb ( note that this will ignore code changes unless you restart your server ).
class Customer
has_many :projects, :class_name => 'Project' if defined? Project
end

Calling created Objects in Rails Scaffold

I am new to Rails and creating a football results app, I did a rails generate Scaffold Team name:string form:string then I added a few teams to the table, my next step I tried was to create a Fixtures table that stores teams, so I did rails generate Scaffold Fixture week:string homeTeam:team awayTeam:team homeScore:integer awayScore:integer when I tried to update the database doing a rake db:migrate I am getting an error undefined method:team I understand rails does not like the way I specify them teams as type team.
How can I go about getting this to work, as when creating a fixture I want to be able to choose from a list of teams already stored in a teams table?
As a random aside, the convention in ruby/rails is to use underscores as opposed to camelCase for variables and methods.
On to your actual question! You need to setup relationships yourself in the generated Team and Fixture models. Scaffolding can help you setup the relationships though by getting the correct foreign keys in place.
For the Fixture scaffold, generate it like this:
rails g scaffold fixture week:string home_team_id:integer away_team_id:integer home_score:integer away_score:integer
Note that g is a shortcut for generator and the generator doesn't need anything to be capitalized.
Now, in your Team model you'll want to define your relationship to the Fixture and vice versa (I'm no sports expert, but wouldn't naming it Game make more sense?):
class Team < ActiveRecord::Base
has_many :home_games, :class_name => Fixture, :foreign_key => :home_team_id
has_many :away_games, :class_name => Fixture, :foreign_key => :away_team_id
end
class Fixture < ActiveRecord::Base
belongs_to :home_team, :class_name => Team
belongs_to :away_team, :class_name => Team
end

Rails naming conventions when having two relations to the same model

My question is more related to naming conventions than programmation I guess.
Let's assume an application where users can create new articles (so they are the owner of these articles) and where you can add article "editors", who can only update the article content.
class User
include Mongoid::Document
has_many :articles # as owner of the articles
has_and_belongs_to_many :articles # as editor of the articles
end
class Article
include Mongoid::Document
belongs_to :user
has_and_belongs_to_many :editors, :class_name => 'User'
end
What I want to know is how I should call the articles association in my User model. I mean, an article has an author and editors, which seems strong naming conventions to me, but a user has articles he created and articles he is the editor. How would you call/name/declare the last 2 associations?
I would call them as :edited_articles, and :authored_articles or :owned_articles, or something similarly straightforward names. Just dont forget to add the :class_name and :foreign_key or :through qualifiers to them.
Update:
For has_and_belongs_to_many relation you need a connection table, which is by default, is named of the two joined table. E.g. articles_users in your case. In this table you will propably have two ids, user_id and article_id. This way rails connects your models automatically.
has_and_belongs_to_many :editors, :class_name => 'User', :foreign_id => 'user_id'
Of course if you call it editor_id in the join table then use that. And the opposite, on the user side should work too.

Rails using a join model attribute in a condition for a find

I'm using a :has_many, :through association to link two models, User and Place
It looks like this -
In User:
has_many :user_places
has_many :places, :through=>:user_places
In Place:
has_many :user_places
has_many :users, :through=>:user_places
In User_Place
belongs_to :user
belongs_to :place
belongs_to :place_status
On that last one note the place_status.
I want to write a find that returns all places associated to a user with a particular place_status_id.
Place_Status_id is on the join model, user_place.
So basically I want
User.places.where(:place_status_id=>1)
(in rails 3)
but i get an error with that because place_status_id isnt on the place model.
Any ideas? Thanks all.
I believe you can do your find this way
#user.places.joins(:user_places).where(:user_places => {:place_status_id => 1})
I've never used Rails 3, so I'm sorry if there's any errors.

Resources