I want to make a article model.
A article belongs_to country
A article belongs_to region
A article belongs_to accomodation
So i want create listing like...give me articles from region X, give me articles from accomodation X.
The url structure looks like this:
/en/italy/articles
/en/italy/tuscany/articles
/en/italy/tuscany/accomodation_x/articles
ect
It is possibly in the a future that article has nothing todo with a accomodation, country or accomodation. By example company news ect
The url structure looks like this:
/en/articles
And on my homepage i want a show all new articles, with different paths. Point root_path of articles but also to the country_region_articles paths.
What is the best approach to setup the db relationsships?
Thanks..
remco
You might want to check these two casts too. On tagging and virtual attributes:
http://railscasts.com/episodes/167-more-on-virtual-attributes
http://railscasts.com/episodes/382-tagging
I can't see any content strategy in your question so my answer may be biased.
In common sense an article may be about an accommodation or completely not. It may be related to a region without specific accommodation. Or it may be about a country with nothing to do with either region or accommodation.
In this case, tagging would be much better than hard association.
Another point is, either association or tagging can has nothing to do with URL. You are not required to use nested url with association.
Related
I am working at a web app in Rails that behaves much like a CMS: there are articles, which have a text attribute that contains links to other articles (or other object classes). I'm currently storing the attribute as HTML.
Is there any good way to model those links in a way that is relative easy to change, and contain the reference to the object id, instead of the absolute url?
One of the solutons I was thinking was to use some kind of special mark-up, such as:
[link_to "Text for the link", Article:12]
where 12 is the id of the article it links to. This mark-up will be parsed when the text is rendered.
The downside of this is that I have to hack into TinyMCE (the editor I'm thinking of using to edit the HTML) so that it can insert links to other objects, by accessing the database and automatically assigning the object type and ID (the person who's editing the texts doesn't know the id's).
Is there any simple solution to this?
Or should I stick to using absolute urls (which, besides maintenance issues, is annoying in development, as they will always point to production and that is confusing for me)?
Additionally, does anyone have similar examples in other languages (php, Wordpress, other CMS, etc) that tackle this problem in a nice way? I'm thinking, this is pretty vital in CMS, and can reduce a lot of man hours if a nice system can handle all those links.
EDIT:
Another possible solution that I'm thinking about is letting the person copy the link of the article directly in the code, but it should, upon submission, generate the correct association id and make it so that if the url structure changes, the link is always up-to-date. I'd like to hear your opinions and experience with this approach, if you have tried it.
The challenge with this approach is parsing the link with Rails and finding out that it points to an Article, and that article has the id ##. Then I have to insert a shortcode that will always translate, upon parsing and rendering, to an actual link to that article.
I found a method that could make this feasible:
Rails.application.routes.recognize_path
But there may be some caveats that I don't see right now...
EDIT no. 2
I also want to specify that I chose CKEditor as the content editor, but I will consider other ones if there are clearer advantages.
I have built something similar using a shortcode system which would allow me to call specific methods on the model and replace the shortcode in the text:
Helper
def parse_shortcode(model)
text = model.text
text.gsub(/(\[#!\s?\w+\])/i) do |match|
result = model.try(match)
result.nil? '' : link_to(result[:text], result[:url])
end
end
Model
def contact_link
{ :text => self.name, :url => self.url }
end
View
<%= parse_shortcode(#article) %>
I haven't tested the above code and it is obviously a bit simplified but it explains my thought process behind this.
EDIT: Just to clarify my above example uses an invented shortcode syntax of [#! method]
An article can have many related_articles and at the same time this article can be related by many other articles, so it is best to model this as a many-to-many relationship.
One way to define this type of relationship in Rails is has_many :through.
To use has_many :through you have to create a join model, perhaps call it ArticleRelation. This model will have two fields, an article_id that represents the current article and a related_article_id that represents the article who’s being referred as related.
class Article < AR::Base
has_many :article_relations
has_many :related_articles, :through => :article_relations
end
class ArticleRelation < AR::Base
belongs_to :article
belongs_to :article_relation, :class_name => 'Article'
end
When creating self-referential relationships it’s important to remember that you’re only creating one side of the relationship. Although article_1 might list article_2 as related, there is no way to for article_2 to list article_1 as related. You'd need two ArticleRelation records to create a mutual relationship.
It’s difficult to think up appropriate names to define another side of the relationship so you can prefix both with the word “inverse” to give inverse_article_relations and inverse_related_articles. You also need to specify some additional options to make the relationships work. For inverse_article_relations you’ll have to specify the name of the other model as it can’t be inferred from the relationship name and you’ll also have to define the foreign key as related_article_id. For the inverse_related_articles relationship you need to specify the source as articles, as again it cannot be inferred from the name of the relationship.
has_many :inverse_article_relations, :class_name => "ArticleRelation", :foreign_key => "related_article_id"
has_many :inverse_related_articles, :through => :inverse_article_relations, :source => :article
Test it out, this should work for you per current requirement.
A solution I've seen in a lot of other CMSs is a combination of custom file browser in TinyMCE and page rewriting (similar to freakyDaz's answer).
TinyMCE has documentation and example code for implementing a custom browser. You'll have to provide the backend pieces, of course.
CKEditor has documentation for a similar feature as well.
Have your backend implementation return something that's easy to parse for the URLs (urlfor:Article:12, for instance), then have your rendering code replace those with actual URLs.
I just thought of another possible solution for the use case:
The admin user specifies the relationships before they edit the text (using Chosen.js, this can be done in a user-friendly way).
Then the person either submits the form to save the model or it can be done asynchronously.
When the relationships are saved, a shortcode is generated and displayed for each of them, and that short-code can easily be pasted in the text.
When displaying the text in the front-end, the text will be parsed for the shortcode, in a similar way to what #freakyDaz is suggesting.
In this way, I don't have to hack or create custom actions in the editor. I think it's a pretty pragmatical approach, but I'd like to hear your opinions. Of course, the admin who's making the text should be educated to follow the process in that order, but in my case very few persons can be admins (1 or 2), so it's manageable.
I have an Event model which I'm looking to add a list of attachable models too. This needs to include some kind of polymorphism as the list of attachables can be any one of Contact User Post Import and a couple of others.
I'm not entirely sure of how I would best achieve this. A single contact can be attached to many events, too. Take the following, for example:
event.attachables #=> [User, Contact, Contact, Import, ...]
user = event.attachables.first
user.attached_events #=> [Event, Event, Event, ...]
Any points in the right direction for best achieving this?
I've looked for the same thing yesterday.
I've found a blog post which describes everything in details and helped me implement this.
http://www.unixgods.org/~tilo/Rails/Rails_polymprphic_has_many_through_relationships.html
The key thing here is to define the attribute source in the has_many declaration of your event model, and as in the has_many declarations of Contact, User and Post
You just need to find a proper, descriptive name for source :)
I'd really recommend that you read this Rails guide: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations. It covers exactly what you're after.
This is more of a general design question, but it will be implemented in RoR to which I am very much a newcomer. Also, I think this is my first question so please be gentle :)
The scenario is:
I have an Asset model. Each asset is located in a particular room, so I would also like a one-to-many relationship with a Location model. Simple enough. However, some rooms (Locations) also go by an alias (eg. 123 is aka Library). When a user wants to update information about a particular Asset, I would like them to be able to just search without worrying about whether they know the exact room number, and be shown a list of assets in that room.
To clarify, there could be more than one alias.
So the question is:
Would you recommend an Alias model for which a Location would have a one-to-many relationship? Or, would a self-referential (sort-of hierarchical) association be better? Or something else maybe? From what I can envisage, the former would require querying columns on different tables for the same sort of information, and the latter just doesn't seem right (an Alias is not the same as a Location).
This might be a good area for using the tagging plugin acts-as-taggable-on:
https://github.com/mbleigh/acts-as-taggable-on
In your model you can do:
class Location < ActiveRecord::Base
acts_as_taggable_on :aliases
end
Then in your controller do:
Location.tagged_with("library", :on => :aliases)
So I am creating a db schema that will represent a library of articles. Each article, however, can have many translations. So, There is a base article, which contains the shared info, and translations for that article. I currently have an article table/class and a translation table/class. Every article has_many translations and so on. My question though, is if there is a good way to delegate methods and find articles with this system.
Should I make my own factory methods on the article class to retrieve the correct translation child? Should I add delegators on the translation so that I can reach back into the parent and get shared info about the article?
Another big concern is where named_scopes would go. Should they go on the article or its translation? I am trying to think of the best way to abstract away the difference between an article and its translation and just have a bunch of articles. Thoughts?
Thanks!
I think that i would use a scope to get an article and translation based on a language. It would be like that in the article model :
scope :translation, lambda { |language|
includes(:translation).
where("translations.language = ?", language )
}
I have this quiz rails app linked to an IRC bot who asks questions (yes, on IRC), where I have this Question model which contains, well, questions, answers, hints, and a few more things.
I started with Quiz model (like, say, the special Halloween or Christmas quiz) with a quiz_id in the questions table, then, I told myself, that it would be nice to be able to categorize the questions, so I added a Category model (like, say, Movies or Books), with a category_id in the questions.
Now, my users would like to be able to add a question to one or more quiz, and to assign one or more categories to questions…
So, I've been thinking about removing the Quiz and Category models and replace them with tags, so that, there will be a halloween tag, a movie tag, and a question can have "halloween movie christmas" for tags.
In my searchs, I've seen quite a few ways to include tags like acts_as_taggable, acts_as_taggable_on_steroids or whatever else someone has imagined :-)
Now, I'm wondering what I should do, and so, I'm asking, what you have done, how you've done it, why you did it this way.
acts_as_taggable_on_steroids is older, but it still works, and is still being maintained. Be sure you're visiting the primary repository for it:
http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids/
You can use acts_as_taggable_on_steroids with named_scopes, here's an article that shows how:
Speed Up and named_scope acts_as_taggable_on_steroids Finds
The actual addition to your model is pretty trivial (this is directly from the article above):
named_scope :tagged_with, lambda { |tags| YourModel.find_options_for_find_tagged_with(tags) }
I think Category can easily be replaced by tags, because they are both used to add metadata to a question.
However, I have my doubts about the Quiz model. If you only use the Quiz model to group your questions, it could be possible to replace it with tags. But I think the Quiz model will include more functionality than just grouping alone. For example, score keeping, picking the next question, etc. So I would keep the Quic model intact.
To implement tagging, acts_as_taggable_on_steroids does work, but is a bit old. It would be nice to have a tagging plugin that uses named_scope in the background, as it would make the plugin far more flexible.