mongoid splits nested attributes in two hashes? - ruby-on-rails

I've got a model List with nested attributes from another one, Article. What bugs me is I have Ruby request params having my first nested attribute in Article hash, and all the others(2nd,3rd article data, etc) in article_parameters.
I follow the standard mongoid tutorial here.
I have #list.articles.build in create method of List controller.
Can I influence what goes into build method? I've tried to call build(all_the_correct_hashes) but it does not seem to fix the issue.
So, in the nutshell I have 2 questions.
why articles gets only the first nested attribute, 2nd and next go to article_parameters hash?
why list.articles.build only creates _id in my Mongo document, but does not populate it with other fields?

I'll write up my solution, since I see people upvoting my question.
Frankly, I did not find any answer as to why such behaviour occurs.
The solution is a bit hackish.
In your save controller, call List.article.build(id => params[:id], someotherstuff => params[:someotherstuff])
Everything you pass to build in this case will populate article_parameters hash.
id and sometherstuff are fields of my Article model.
I feel this should be done implicitly by Mongoid, but it just does not work. Their development does not see anything wrong with it, either.

Related

Model Accepts Nesting Attributes without declaring that it accepts them

everyone. So, I'm working on a basic Rails 4 application for practice, and I have a model for FriendCircle and a model for FriendCircleMembership. (the FriendCircleMembership's corresponding table is basically a join table).
In the console, I'm able to create a new FriendCircle object while passing in :friend_circle_memberships_attributes. This successfully inserts a new FriendCircle row into my table as well as inserting the proper rows into the FriendCircleMembership table.
The WEIRD thing is that, even if i comment out that the FriendCircle accepts_nested_attributes for :friend_circle_memberships, it still works. Is this because i am whitelisting it as a permission in the controller?
The other issue is that, even though i can successfully make the nested objects via the rails console, when i try making it through my html form it says my friend_circle_memberships_attributes is an unpermitted parameter. Not sure why this is happening. I check the incoming parameters and they look fine.
any help would be SWEEEEET. thanks.
I determined what the error was: One of my controllers for a nested attributes was validating the presence of the id of the controller it was nested under.
I'm assuming the validation occurs before an id is created, which makes sense, but im not 100%. So i just took out the validator and things worked.

Rails: Get all associated models from has-many association

I need to get all associated models from the other associated model, on which I want to run query first.
For example, I got Post model and Tag model. I need to get all Posts, which associated with some Tags.
There's no problem, if I have only one Tag – just call 'tag.posts', but if I have more, then one Tag – for example, I need to do somethink like:
Post.where(id: PostTag.where(tag_id: some_ids).pluck(:category_id).uniq)
I belive that Rails have a built-in solution. So, anybody knows it?
My thought is:
Post.joins(:post_tags).where('post_tags.tag_id' => some_ids).uniq
You can make it a scope for easier reuse. I don't think there is a built-in method for this situation.

Using a select field with Rails nested object forms

Is it possible to use select fields with nested object forms feature of Rails 2.3?
Example:
Suppose you have a Article model, Category model, and a ArticleCategories join model. Article has_many Categories through ArticleCategories.
On our Edit Article form, you want to have an HTML select list of all the available categories. The user can select one or more Category names to assign to the Article (multiple select is enabled).
There are lots of ways to do this, but I'm wondering if there is a simple way to accomplish this using the nested objects feature. What would the form look like in your view?
Check out the nested form example from Github:
http://github.com/alloy/complex-form-examples
It's been a while since I looked at it, so I'm not sure if it covers exactly what you wanna do, but its a nice source for ideas / patterns.
Assuming you have defined the models and their relationships so you can do this:
#art = Article.find(article_id)
#art.categories # returns list of category objects this article is assigned to.
Then I usually use http://trendwork.kmf.de/175
You need to copy the JavaScript file into public/javascripts but after that you can just create the form element with something like:
swapselect(:article,#art,:categories,Category.find(:all).map { |cat| [cat.name, cat.id] })
(I would tend to wrap that in a helper to make the call even cleaner)
One small gotcha is that for very long lists it can run a little slow in IE6 because there's quite a lot of appendChild calls in the js which is notorioulsy slow in IE6
Update: Apologies. This doesn't really answer your original question, which was specifically about the Rails 2.3 feature. The swapselect option is version independent and doesn't make use of newer Rails functionality.

Calling ActiveRecord's #relationship_ids = [1,2,3] saves immediately. Any workarounds?

I've come across an oddity in ActiveRecord's #relationship_ids method (that's added automatically when you declare 'has_many'), which saves immediately for existing records, which is causing me some issues, and I wonder if anyone had any useful advice.
I'm running Rails 2.3.5.
Consider this simple scenario, where an article has_many tags, say:
a = Article.first
a.name = "New Name" # No save yet
a.author_id = 1 # No save yet
a.tag_ids = [1,2,3] # These changes are saved to the database
# immediately, even if I don't subsequently
# call 'a.save'
This seems surprising to me. It's specifically causing problems whilst trying to build a preview facility - I want to update a bunch of attributes and then preview the article without saving it - but in this instance the tag changes do get saved, even though no other fields do.
(Of possible relevance is that if 'a' is a new article, rather than an existing one, things behave as I'd expect - nothing is saved until I call 'a.save')
I have a fairly nasty workaround - I can override the tag_ids= method in my model to instead populate an instance variable, and actually save the related models in a before_save callback.
But I'd love to know of a simpler way than me having to do this for every model with a has_many relationship I'd like to create a preview facility for.
Does anyone have any fixes/workarounds/general advice? Thanks!
There's a reason things are this way. It's called foreign keys. In a has many relationship, the information that links to the model that has many is stored outside of that model as a foreign key.
As in Articles, has many tags. The information that links a tag to an article is stored either in the tags table or in a join table. When you call save on an article you're only saving the article.
Active record modifies those other records immediately. Except in the case where you're working with a new article that hasn't been saved yet. Rails will delay creating/updating the associated records if it doesn't know which id to place in the foreign key.
However, if you're modifying existing records, the solution you've decided on is really all that you can do. There's an even uglier hack using accepts_nested_attributes_for, but it's really not worth the effort.
If you're looking to add this behaviour to many models but not all models, you might want to consider writing a simple plugin to redefine the assigment the method you need and add the call back in a single class method call. Have a look at the source of something like acts_as_audited to see how it's done.
If you're looking to add this behaviour to all models, you can probably write a wrapper for has_many to do that.

Building dynamic fields using ActiveRecord::Serialization.to_xml

I'm curious about people's experiences using AR's to_xml() to build non-entity fields (as in, not an attribute of the model you are serializing, but perhaps, utilizing the attributes in the process) from a controller.
to_xml seems to supply a few options for doing this.
One is by passing in references to methods on the object being acted on: during the serialization process, these methods are invoked and their results are added to the generated document. I'd like to avoid this path because some of the generated data, while depending on the object's attributes, could be outside of the scope of the model itself -- e.g., building a URL to a particular items "show" action. Plus, it requires too much forethought. I'd like to just be able to change the resultant document by tweaking the to_xml code from the controller. I don't want the hassle of having to declare a method in the object as well.
The same goes for overriding to_xml in each object.
The other two options seem to fit the bill a little better: one is by passing in procs in the serialization options that generate these fields, and the other is by passing in a block that will yielded to after serialization the objects attributes. These provide the kind of at-the-point-of-invocation customizing that I'm looking for, and in addition, their declarations bind the scope to the controller so that they have access to the same stuff that the controller does, but these methods seem critically limited: AFAICT they contain no reference to the object being serialized. They contain references to the builder object, which, sure I guess you could parse within the block/proc and find the attributes that have already been serialized and use them, but that's a harangue, or at least uneasy and suboptimal.
Correct me if I'm wrong here, but what is the point of having procs/blocks available when serializing one or more objects if you have to access to the object itself.
Anyway, please tell me how I'm wrong, because it seems like I must be overlooking something here.
Oh and yeah, I know that I could write my own view. I'm trying to leverage respond_to and to_xml to achieve minimal extra files/lines. (Though, that is what I resorted to when I couldn't figure out how to do this with AR's serialization.)
**EDIT 3.29.09 -- I just submitted a patch for this to Rails. If you're interested, show some support :) https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2373-record-sensitive-procs-for-to_xml
Actually the Proc is passed the same options hash (minus the procs option) you passed into to_xml. So you can pass in any extra objects the Proc needs to do it's job:
proc = Proc.new {|options| options[:builder].tag!('reverse-name', options[:object].name.reverse)}
object.to_xml :object => object, :procs => [ proc ]
Since you're getting the proc is getting the same options to_xml is, this is allows you to pass in whatever options you need.
Woo! My patch to handle this scenario was accepted: http://github.com/rails/rails/commit/c39151a84768397d3bb025c6e8f877eac59ebbf9 It's a part of ActiveModel now, and I'm not exactly sure what the release schedule for that is; I'm thinking Rails 3.

Resources