samedi 25 avril 2015

Rails 4 + Solr: Show search result from different model


I have search method in my controller:

def search
  @search = Sunspot.search [Post, Siri] do
    fulltext params[:q]
  end
  @posts = @search.results
end

Then i have this in my view:

- @posts.each do |p|
  %h5= p.title

My question is how to show separately in view if @posts from Post model & if @posts from Siri model.

The reason that i want it seperately is because there is some attr are not exists in Post model but exists in Siri model.

Thanks in advance!


Rails 4.2 / PostgreSQL and Test Database Preparation


We are using Rake::Task['db:create'].enhance to add a new schema and create an extension in the newly created schema as below.

Rake::Task['db:create'].enhance do
  ActiveRecord::Base.connection.execute('CREATE SCHEMA IF NOT EXISTS shared_extensions;')
  ActiveRecord::Base.connection.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp" SCHEMA shared_extensions;')
end

Can we enhance the test database preparation in the same way?


Join the associated object into the belongs_to object


I have an Event model which has many DateEntry because an event can have multiple datetimes.

I have a view where I see all the events with date entries for a specific day. For which I've made this class method in models/event.rb:

def self.by_date(date)
  includes(:date_entries)
  .where(date_entries: { begins_at: date.beginning_of_day..date.end_of_day })
end

And it works fine.

Now on the view I loop over the events I grabbed with that query:

@events.each do |event|
  # whatever

I am looking for a way to use the date from the selected DateEntry in the loop. I think I have to use ActiveRecords joins method, but I have tried in many ways and when I am not getting an error the output is still the same.

For clarifying, I want to do in the loop something like event.selected_date_entry_by_the_by_date_method.begins_at or something like that.


has_many through roles and scopes on the third model


Lets say I have movies, people and movies_people

class Person < ActiveRecord::Base
  has_many :movies_people
  has_many :movies, through: :movies_people

class Movies < ActiveRecord::Base
  has_many :movies_people
  has_many :people, through: :movies_people


class MoviesPerson < ActiveRecord::Base
  belongs_to :movie
  belongs_to :person
end

The table movies_people has a role attribute, where I want to store the person's job in the movie. Right now I can do things like this in the console:

u = User.first
m = Movie.first
m.people << u

then find the right movies_people entry and set 'role'

retrieving looks like this:

m.people.where(movies_people: {role: :actor})


Whats the best way to:

  1. Save the role (to the third table) when joining people to movies?
  2. Return all the actors in a movie vs. all the directors vs. all the writers?

Favouriting a picture in a Rails app


I am trying to figure out how to execute a "favourite a picture" method in a Rails app, which I am very new to, going from a JS/Meteor background.

The point is I have a User, FavPic, Pic classes:

class User < ActiveRecord::Base
  #some user oauth stuff would be here

  has_many :fav_pics
  has_many :pics_favorited,
    class_name: 'Pic',
    through: :fav_pics

end

class FavPic < ActiveRecord::Base
  belongs_to :user
  belongs_to :pic
end

class Pic < ActiveRecord::Base
  has_many :fav_pics
  has_many :fav_users,
    class_name: 'User',
    through: :fav_pics
end

and here's my template:

<% if current_user %>
  <%= form_tag(root_path, :method => "get") do %>
    <p>
      <%= text_field_tag :username, params[:username] %>
      <%= submit_tag "Search", :name => nil %>
    </p>
  <% end %>

  <ul>
    <% @mentions.each do |mention| %>
      <li>
        <%= mention.text %>
        <div class="row">
        <% mention.media.each do |media| %>

          <div class="col-xs-3">
            <%=image_tag(media.media_url, class:"img-responsive")%>
            <a href="#" class="fav-img"><i class="fa fa-star fa-2x"></i></a>
          </div>

        <% end %>
        </div>
      </li>
    <% end %>
  </ul>
<% else %>
  <p>
    Sign in to be able to use the app.
  </p>
<% end %>

current_user is a user signed in through Twitter and @mentions is a list of tweets that has the username inputed in the form mentioned. media.media_url is a picture url that is associated with that tweet.

I am trying to get that link (or whatever way it's done in Rails) to add that media URL into the DB so I can list all the images at a separate URL.


Querying a Postgres array of integers in Rails


my model has a pg array which I use to store integers

Querying using the methods I found from other questions yields errors or gives empty results

MyModel.where("? = ANY (myarray)", 42)

gives

PG::UndefinedFunction: ERROR:  operator does not exist: integer = text

and

 MyModel.where("myarray @> '{?}'", 42)

gives an empty results, yet I do have a model with 42 as one of the ints in the array

#<MyModel:0x007f9a77dd5608> {
                :id => 170,
      :myarray => [
    [0] 42,
    [1] 43,
    [2] 58,
    [3] 61,
    [4] 63
  ]

Is there a special way to query integers(or floats) within a postgres array in Rails?

the migration

class AddMyarrayToMyModel < ActiveRecord::Migration
  def change
    add_column :my_models, :myarray, :integer, array: true, default: []
    add_index  :my_models, :myarray, using: 'gin'
  end
end

and schema

t.integer  "myarray",                 default: [],              array: true


ActiveRecord complex calculation - how to solve it the rails way?


Currently I'm trying to figure out how to do a calculation the proper and best way using Rails 4.1.

(Simplified example)

Movement (ActiveRecord Model)

id: integer
paid_at: datetime
value: decimal
debit_account_id: references
credit_account_id: references
category_id: references
...

The Goal

I want a four column list as result, having:

  1. The paid_at date (grouped by)
  2. The sum of all values for the paid_at date, IF condition ONE is true
  3. The sum of all values for the paid_at date, IF condition TWO is true
  4. The difference of both values (Column 2 minus Column 3)

Conditions may be different, an easy case would be:

  • Condition 1: debit_account_id IN (3, 4)
  • Condition 2: credit_account_id IN (3, 4)
  • Just another one: Any field of a joined account must have a field match a value
  • ...

Example result

 date       | earnings | spendings |  total |
 -----------+----------+-----------+--------+
 2015-01-01 |   120.00 |     50.00 |  70.00 |
 2015-01-05 |     0.00 |     10.00 | -10.00 |
 2015-01-06 |   100.00 |      0.00 | 100.00 |
 ...

One possible (ugly) SQL way

SELECT
  DATE(`paid_at`) AS `date`,
  SUM(IF(credit_account_id IN(:credit_accounts), value, 0)) AS `earnings`,
  SUM(IF(debit_account_id IN(:debit_accounts), value, 0)) AS `spendings`,
  SUM(IF(credit_account_id IN(:credit_accounts), value, 0)) - SUM(IF(debit_account_id IN(:debit_accounts), value, 0)) AS `total`
FROM 
  movements
WHERE
  credit_account_id IN (:credit_accounts)
OR
  debit_account_id IN (:debit_accounts)
GROUP BY `date`
ORDER BY `date`;

The question

How can I get the expected result in a better way? And how to do it using Rails?

~~ Thank you in advance for any help! :D ~~