37086

Rails: build for difference between relationships

A doc has many articles and can have many edits.

I want to build an edit for each article up to the total number of @doc.articles. This code works with the first build (i.e., when no edits yet exist).

def editing @doc = Doc.find(params[:id]) unbuilt = @doc.articles - @doc.edits unbuilt.reverse.each do |article| @doc.edits.build(:body => article.body, :article_id => article.id, :doc_id => @doc.id) end end

But when edits already exist it'll keep those edits and still build for the @doc.articles total, ending up with too many edits and some duplicates if only one article was changed.

I want to put some condition against :article_id which exists in both edits and articles in to say (in <strong>pseudocode</strong>):

unbuilt = @doc.articles - @doc.edits unbuilt.where('article_id not in (?)', @doc.edits).reverse.each do |article| @doc.edits.build(...) end

Any help would be excellent! Thank-you so much.

Answer1:

You are doing something weird here:

unbuilt = @doc.articles - @doc.edits

You probably want this instead

unbuilt = @doc.articles - @doc.edits.map(&:article)

This works if @doc.articles and @doc.edits are small collections, otherwise a SQL solution would be preferred.

-- EDIT: added explanation --

this piece of Ruby

@doc.edits.map(&:article)

is equivalent to

@doc.edits.map do |edit| edit.article end

the previous one is much more compact and exploits a feature introduced in ruby 1.9

It basically takes a symbol (:article), calls on it the 'to_proc' method (it does this by using the '&' character). You can think of the 'to_proc' method as something very similar to this:

def to_proc proc { |object| object.send(self) } end

In ruby, blocks and procs are generally equivalent (kindof), so this works!

Recommend

  • Error faced while using TM package's VCorpus in R
  • How to get params from query object in CakePHP 3
  • How to get the embed url for google docs presentation?
  • CakePHP conditional query with controller that 'hasAndBelongsToMany'
  • Rails 3.1 limit the number of child models
  • Convert SQL to Eloquent to Join multiple table and Count
  • For each row of one table, count entries in another table pointing to each of those rows in Oracle
  • What means / happens when using the `INNER JOIN` with multiple database table statements?
  • Devise: Is it possible to NOT send a confirmation email in specific cases ?
  • schema.rb index different from individual migration index
  • Reset auto increment sequence pl-sql
  • How to cache images only in disk using Kingfisher?
  • Testing an AJAX POST using Rack::Test - how to pass in data?
  • inserting duplicate records with SQL
  • Why do native C++ projects have a TargetFrameworkVersion?
  • Replace rows by index
  • Vim ctags behaves strangely
  • Android libgdx prefs getting lost
  • Getting directory of input file (Applescript)
  • Finding parents in a tree hierarchy for a given child LINQ (lambda expression)
  • How to sort things out in ListView?
  • How to turn (A, B, C) into (AB, AC, BC) with Pig?
  • Invalid Date on validation Date of js
  • Diff between two dataframes in pandas
  • Alternative To body {overflow:scroll;} That Will Prevent Page Jostling/Wriggling?
  • Play WS (2.2.1): post/put large request
  • Java: can you cast Class into a specific interface?
  • Spring Data JPA custom method causing PropertyReferenceException
  • Why ng-show works with ng-repeat but ng-if doesn't? [duplicate]
  • AES padding and writing the ciphertext to a disk file
  • Excel - Autoshape get it's name from cell (value)
  • Updating server-side rendering client-side
  • How to extract text from Word files using C#?
  • How to apply VCL Styles to DLL-based forms in Inno Setup?
  • Warning: Can't call setState (or forceUpdate) on an unmounted component
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?