Update attributes of embedded new record in Rails & Mongoid - ruby-on-rails

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.

Related

Ruby on rails AngularJS - create multiple models from direct upload

I recently am given a task by upper management to implement a mass upload coupon task. The goal is to allow users to upload an list of coupon codes (excel or csv), and subsequently giving these coupons codes attributes such as start date, expiry, quantity and so on.
I have already implemented a form to input these attributes. The current implementation method I am doing is as follows:
1.I upload a list of coupon codes (eg: 333245454dfee) and I do not write them directly to the database, instead I converted them to string and display on a page for the user to view. (done)
2.from that view page, there is a form with all the attributes. The user can then input these attributes. (done)
3.The user can create all of these coupons codes with the attributes set.
However, I am stuck now because I am unsure of how to mass create multiple codes and attach all the attributes to them. Right now, I can only create one coupon at a time.
So, to summarize, I would like to ask is it possible to
have a field that contains all the codes I have uploaded
I have others fields for different attributes
how to create all the codes I have uploaded as separate models.
I do not need the codes, I would like to hear what approach there are. I am thinking of creating a variable to store these coupons codes first, then loop them. But I have no idea how to do all of that by pressing one single button.
Thanks in advance.
Hmm, how I would approach this problem would be to have the user upload an csv file with 1 column and multiple rows of coupon. Using carrierwave to upload the file and parse the csv file. After parsing it, you should have an array of coupon and you can just input them into the database.
A good reference for your problem would be http://railscasts.com/episodes/396-importing-csv-and-excel

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.

Multiple File Uploads for a new record

I have implemented multiple file uploads for existing records as seen here https://github.com/websymphony/Rails3-Paperclip-Uploadify
I would like to know if it is possible to implement multiple file uploads when creating a new record.
Since we need flash to do the multiple file uploads, how would it be possible to associate the uploaded files with the record if the record has not yet been created.
I have thought of a hack-ish way to essentially make a "draft" and update it. However, I hope there is a better way to do this.
There is no better than the kind of hackish way you present:
creating orphans objects and give them parents later or delete them (sad huh? :) )
creating parent object by default, add some confirmation field in the form so that you know what objects really have an owner, delete the rest.
BTW, you don't "need" flash for multiple uploads, see here: http://blueimp.github.com/jQuery-File-Upload/
Yes, you can use http://blueimp.github.com/jQuery-File-Upload/. But there are still some points you need to be careful.
Don't forget to remove appended array after you define the file field with "multiple". For example: replace "photo[image][]" with "photo[image]".Otherwise file uploaders like "carrierware" will not be working.
If you are using rails 3.2.13, the appended array will always appear no matter whether you set the name to be without appended array. You can use "file_field_tag" to resolve this problem. Please refer this issue to: https://github.com/tors/jquery-fileupload-rails/issues/36.
For the association:
You need to create a hidden text field which contains IDs of images that will be associated to the record you are going to create.
Upload images by "jquery-fileupload"(it is ajax), then get IDs of images from response bodies.
Set these IDs to the hidden field.

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.

Stack Overflow-like tagging behavior in 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.

Resources