Stack Overflow-like tagging behavior in Rails - ruby-on-rails

I have a new application that contains a Modela called "Campaigns". Each campaign is able to have any number of tags associated with it.
What I am attempting to do is impliment a Stack Overflow-like behavior with these tags. Namely, that when you create a new campaign, it gives you a text-field that will auto-complete with tags that already exist, and start anew every time you put a space. Additionally, should the tag not exist, it should create a new tag.
This railscast is a step in the right direction, but it only allows for one "tag" at a time.
Can anyone point me in the right direction?

In the model layer I'd go for a plugin like: https://github.com/mbleigh/acts-as-taggable-on.
In the view you want an autocomplete plugin (personally I use this http://docs.jquery.com/Plugins/autocomplete). Then either generate a controller for the tags and fetch the autocomplete list remotely or just = them in the page.

Related

End user can edit the view of a recored in some sort of editor - rails

I'm looking for something like an editor but instead of the user editing just a post or page the user can edit the default template layout or view layout for all pages associated to something.
I'll give an example to get my question across because i really don't know what it would be called.
Say for example you have categories. (people, animals, etc..)
Now imagine there is a category of people, each person in the category has the keys 'height', 'weight' and 'age' and each key has values assigned to them (height: 120 cm, weight: 80 pounds, age: 25)
I want the user to be able to edit the layout of the people page (page template or view that each person is displayed on) and be able to add in the keys they want to be displayed on the page.
So say they add the keys ‘height’ and ‘weight’ it will only display the height and weight on every person page, plus whatever pre set text the user added in the template editor for the people pages to display.
I could probably find a good editor that can be customised and change it to my liking but there might already be gems out there made for this.
My question is, is there a gem for basically letting users set templates for record pages.
Even if there is something out there to change views for objects but the user cant set the keys on it, i'd still like to see it because I might be able to add the key/value functionality to it.
Hopefully you understand what I'm looking for.
UPDATE
Ok so i appears I'm after an editor that works with a template engine like liquid or one thats both an editor and template engine.
If you plan on building from scratch, it sounds like it could be done using rails generate scaffold this allows views/models/controllers to create pages for each of your categories.
Then you can use Associations to create associations between your categories.
You can also make different user roles by making a field called "Role" in your Users relation
Otherwise, there are also open-source software Active Admin to manage content for your categories.
EDIT: After looking around I found a gem you can use to have end-users edit your own views, feel free to check out Liquid.

Update attributes of embedded new record in Rails & Mongoid

I'm trying to write a piece of functionality that creates a record from a template in my Rails app, but with some customisations from the user.
The difficulty comes when trying to let the user override a field in an embedded document: the document is duplicated rather than updated.
I start with an object of type, let's say, ExternalLinkGroupTemplate, and it contains a number of ExternalLinks. It's used to create an ExternalLinkGroup which also contains ExternalLinks. The user should be able to edit the link text when it's cloned but not the URL, so the user is presented with a form When it's copied the user should be able to I can create a copy of it with (simplified because some of the code is in different files, remove tests for success etc):
#link_group = ExternalLinkGroup.new
#template.links.each do {|link| #new_link_group.links.push link.dup }
#link_group.update_attributes(params[:link_group])
When the link group is created, it contains twice as many links as the template, and only the second set has the changes. Clearly, Mongoid/ActiveWhatever is creating new items rather than updating existing ones.
I don't want to just pass through all the fields in the parameters without duplicating anything because there's actually some inheritance going on and some of the links will be of different types and have extra fields, and I don't want to code a partial for each of them that just has a bunch of hidden fields. Also, I don't want the user to be able to modify the hidden fields and submit whatever.
I can't reference them by _id because they're not saved yet. I was expecting the array index of template[links_attributes] to be sufficient but it's not.
What do?
Using Rails 3.2.13, MongoDB 2.2.x, Mongoid 3.0.5.

Ruby on Rails initial controller setup

I'm getting started with Ruby on Rails and have some questions. I currently have a website that is written in Perl/HTML/Javascript, etc. My goal is to convert this website to use Rails. I'm running into a stubmling block on how to get started.
Here is the general overview of the current website:
The main page has 3 selection lists that get populated on page load (via SQL). The user can select an option from one of these lists (say a date as one of the lists stores dates). Currently, using AJAX, this calls a Perl CGI script which queries the database with the chosen date and returns a table containing the appropriate records (fills in division next to the selection lists).
There are no other pages on the website (besides a changelog) as everything happens on the main page. The selection lists do not get refreshed after each selection due to AJAX.
My question is, would I have a controller called Selection to populate the lists and another called Output to create the table of records? Does that setup makes sense?
Thank you!
This is my understanding about your requirement.
1) You have a page where there are three selection boxes
2) If a user changes any one of the selection box, then you are posting data to backend to get output based on the selection (using Perl CGI script)
The output is loaded after you get response from backend.
If my understanding is right, below are my suggestion.
Suggestion :
You need not to have different controllers for each action, in Rails you may have multiple action within a single controller.
Say you can name your controller and action as below
Selection Controller (Can have multiple actions under it as below, you can define custom names for each action in controller and add routing information in app/config/routes.rb file)
- GenerateList
- CustomAction1
- CustomAction etc.,
EDIT :
You should not use single controller for all your actions in the website, you need to categorize
functionality and create multiple controller/actions accordingly.
Let me know if you face any difficulty in creating and running custom actions.

How to create a tagging system like on Stack Overflow or Quora

I want to create a tagging system like seen here on Stack Overflow or on Quora. It'll be its own model, and I'm planning on using this autocomplete plugin to help users find tags. I have a couple of questions:
I want tags to be entirely user-generated. If a user inputs a new tag by typing it and pressing an "Add" button, then that tag is added to the db, but if a user types in an existing tag, then it uses that one. I'm thinking of using code like this:
def create
#video.tags = find_or_create_by_name(#video.tags.name)
end
Am I on the right track?
I'd like to implement something like on Stack Overflow or Quora such that when you click a tag from the suggested list or click an "Add" button, that tag gets added right above the text field with ajax. How would I go about implementing something like that?
I know this is kind of an open-ended question. I'm not really looking for the exact code as much as a general nudge in the right direction. Of course, code examples wouldn't hurt :)
Note I am NOT asking for help on how to set up the jQuery autocomplete plugin... I know how to do that. Rather, it seems like I'll have to modify the code in the plugin so that instead of the tags being added inside the text field, they are added above the text field. I'd appreciate any direction with this.
mbleigh's acts_as_taggable_on gem is a feature-complete solution that you should definitely look into a little more closely. The implementation is rock-solid and flexible to use. However, it is mostly concerned with attaching tags to objects, retrieving tags on objects, and searching for tagged items. This is all backend server stuff.
Most of the functionality you are looking to change (based on your comments) is actually related more to your front-end UI implementation, and the gem doesn't really do much for you there. I'll take your requests one-by-one.
If user inputs a new tag, that tag
gets added, if user inputs an
existing tag, the existing tag gets
used. acts_as_taggable_on does this.
Click a tag from suggested list to
add that tag. This is an
implementation issue - on the
back-end you'll need to collect the
suggested list of tags, then display
those in your presentation as links
to your processing function.
Autocomplete as user enters
potential tag. You'll use the jQuery
autocomplete plugin against a list
of items pulled off the tags table.
With additional jQuery, you can
capture when they've selected one of
the options, or completed entering
their new tag, and then call the
processing function.
Restrict users to entering only one
tag. This will be your UI
implementation - once they've
entered or selected a tag, you
process it. If they enter two words
separated by a comma, then before or
during processing you have to either
treat it as one tag, or take only
the text up to the first comma and
discard the rest.
When you process the addition of a
tag, you will have to do two things.
First, you'll need to handle the UI
display changes to reflect that a
tag has been entered/chosen. This
includes placing the tag in the
"seleted" area, removing it from the
"available" display, updating any
counters, etc. Second, you'll need
to send a request to the server to
actually add the tag to the object
and persist that fact to the
database (where the taggable gem will take over for you). You can either do this via
an individual AJAX request per tag,
or you can handle it when you submit
the form. If the latter, you'll need
a var to keep the running list of
tags that have been added/removed
and you'll need code to handle
adding/removing values to that var.
For an example of saving tags while editing but not sending to server/db until saving a form, you might take a look at the tagging functionality on Tumblr's new post page. You can add/remove tags at will while creating the post, but none of it goes to the database until you click save.
As you can see, most of this is on you to determine and code, but has very little to do with the backend part. The gem will take care of that for you quite nicely.
I hope this helps get you moving in the right direction.
The more I try to force the acts-as-taggable-on gem to work the more I think these are fundamentally different types of problems. Specifically because of aliases. The gem considers each tag to be its own special snowflake, making it difficult to create synonyms. In some cases it doesn't go far enough, if you want the Tag to have a description you'd need to edit the given migrations (which isn't hard to do).
Here's what I'm considering implementing, given the trouble I've had implementing via the gem. Let's assume you want to create a tagging system for Technologies.
Consider the following psuedo code, I haven't yet tested it.
rails g model Tech usage_count::integer description:text icon_url:string etc. Run the migration. Note the
Now in the controller you will need to increment usage_count each time something happens, the user submits a new question tagged with given text.
rails g model Name::Tech belongs_to:Tech name:string
Name::Tech model
belongs_to :tech
end
Then you could search via something like:
search = Name::Tech.where("name LIKE :prefix", prefix: "word_start%")
.joins(:tech)
.order(usage_count: desc)
.limit(5)
This is starting point. It's fundamentally different from the gem, as each tag is just a string on its own, but references a richer data table on the back end. I'll work on implementing and come back to update with a better solution.

How to structure content in Ruby (RoR) app?

I am in the process of building a super simple CMS to handle smaller "static" page type projects (e.g. - small sites for friends). I have different "page types" that I would like to add. I built something similar in Coldfusion previously. Looked something like this:
table content_type:
content_type_code varchar(10)
content_type_name
table content:
content_id
content_type_code varchar(10)
content_name
content_desc
content_url
I would create a content type called "blog" or "photo" and each time a content was added, it'd get assigned the content_type_code. Then in /blog/ I'd query for all content that had a content_type_code of "blog".
Now that I'm using Ruby/RoR I am trying to think about things differently. I was thinking a better way might be to use nested pages with awesome_nested_set (https://github.com/collectiveidea/awesome_nested_set). But I'm not sure if that's the best solution.
Then I could create a page called "blog" and add to that many pages. So essentially the top level would take place of the "content_type" from my previous example.
Can someone steer me in the right direction on what the best method would be? I'm a newb looking for a kick in the right direction.
EDIT
I should add that the only real thing that I would change between the different "types" of content would be the layout and where they are displayed ("photo" content at /photos/, "blog" content at /blog/).
I try to recap:
You want to build a CMS
Your CMS manages a single web site
A web site is made of content
There are differenti type of contents, and I am assuming every type of content has its own behaviour
Contents are organized in a tree
Here is the plan I suggest you:
Create the Content resource; use the scaffold to have something already working, adding few field (title and body in example)
Add validations to your new model
Write a couple of unit tests against your validation (quite useless, just to see how it works)
Install awesome_nested_set and manage to make it working with your model
Work on the UI to make it quite easy to create new content, move content around, edit a single content
Now its time to implement the content types; STI is the Rails way, but I have to warn you it can be really hard. I suggest you to reiterate 1, 2, 3, 5 to create new models for Photo and BlogPost
Once you will be there, you will have hundreds of ideas to implement. Have fun :)
Instead of using content_type I would rather let the user choose a model on a selection page, like "photo" or "blog" and load an editing page based on that selection. So the user wants a new 'blog'-entry they get redirected to blog/new or 'photo' for photo/new. It's the easiest way to go in terms of usability and your controlling backend and you don't have redundant data (for example an empty photo url which is not necessary in a blog-type) in your database.

Resources