return array in rails and storage it - mysql

I know that it could sound an "easy-question" but I am new in rails and I don't know if I am structuring correctly my app.
My app is "easy" it has to connect a webpage and collect all JPG links and store the links in a database.
In my "model folder" I have defined my functions:
class JPG < ActiveRecord::Base
acts_as_paranoid
validates :title, :link, presence: true
validates :link, uniqueness: true
attr_accessible :tag_list, :id, :title
#acts_as_taggable
def main_web
require 'rubygems'
require 'scrapi'
require 'uri'
Scraper::Base.parser :html_parser
scraper = Scraper.define do
array :items
process "div.mozaique>div", :items => Scraper.define {
process "div.thumb>a", :link => "#href"
}
result :items
end
uri = URI.parse(URI.encode(web))
return scraper.scrape(uri)
end
end
As you can see the function main_web returns an array.
Well my question is "easy". If I want to call the function and to storage the information in the database, how do I have to do it?
I don't want to show the information in the screen I only want to storage the data in the database but from where do I have to do the call? view? or controller?

I suggest you read more about the controller-view model. You need to call and store in the database from the controller.

If main_web returns an array then wouldn't #jpg = #jpg.main_web mean that #jpg is now an array instead of the Active Record model? That would seem to be why it wouldn't save. You might want to add a field to your database that holds the array you generate from main_web. Then instead of returning it you could just call save on your #jpg model.
Also a nice tip would be if you are having issues with models or other things really try typing 'rails console' on command line. You could run your 3 lines of code there to see if they worked. This wouldn't solve your issue but might allow you to play around with some things.
#jpg = JPG.new
#jpg = #jpg.main_web
#jpg.save

Replacing my initial answer after giving it more consideration...
You are doing this:
return scraper.scrape(uri)
which you assign to the #jpg instance. Thus, #jpg is no longer an instance of JPG and cannot be saved as such.
Also, it is not necessary to call and store from the controller. The controller is more a decision maker than anything. It determines state and routes control and information to the desired view or model. The model is where data should be managed. Though, that may be a matter of debate and is my opinion.
Recommended reading:
http://sirupsen.com/what-I-wish-a-ruby-programmer-had-told-me-one-year-ago/

Related

ActiveModelSerializers Polymorphic Json

Been wrestling with trying to get polymorphic serializers working and testing data via rspec. Just upgraded to 0.10+
I found this post, which makes a lot of sense, and does give me a entry into generating the serializations, however, when doing it for polymorphs, I never get the type and id properly named (expecting to see asset_id and asset_type nested)
{:id=>1,
:label=>"Today I feel amazing!",
:position=>0,
:status=>"active",
:media_container_id=>1,
:asset=>
{:id=>4
Test ActiveModel::Serializer classes with Rspec
class MediaSerializer < ApplicationSerializer
attributes :id,
:label,
has_one :asset, polymorphic: true
end
I noticed that the tests dont even seem to properly add the polymorphic identifiers either (ie asset_id, asset_type -- or in the test case imageable_id, imageable_type)
https://github.com/rails-api/active_model_serializers/commit/045fa9bc072a04f5a94d23f3d955e49bdaba74a1#diff-c3565d7d6d40da1b2bf75e13eb8e6afbR36
If I go straight up MediaSerialzer.new(media) I can poke at the .associations, but I cant seem to get them to render as if I was generating a full payload
From the docs
https://github.com/rails-api/active_model_serializers
serializer_options = {}
serializer = SomeSerializer.new(resource, serializer_options)
serializer.attributes
serializer.associations
Im pretty sure Im missing something/doing something wrong - any guidance would be great.
Thanks
It isn't easy to get the effect you are looking for, but it is possible.
You can access the hash generated by the serializer by overriding the associations method.
class MediaSerializer < ApplicationSerializer
attributes :id,
:label,
has_one :asset, polymorphic: true
def associations details
data = super
data[:asset] = relabel_asset(data[:asset])
data
end
def relabel_asset asset
labelled_asset = {}
asset.keys.each do |k|
labelled_asset["asset_#{k}"] = asset[k];
end
labelled_asset
end
end
I learnt alot about ActiveModelSerializer to get the hang of this! I referred to Ryan Bates' podcast on the topic:
http://railscasts.com/episodes/409-active-model-serializers
In there he describes how you can override the attributes method and call super to get access to the hash generated by the serializer. I guessed I could do the same trick for the associations method mentioned in your post. From there it takes a little bit of Ruby to replace all the keys, but, if I have understood correctly what you require, it is technically possible.
Hope that helps!

How to specify Node Label in Neo4jrb

I get a trouble about customize node label in Neo4jrb.
class Core::Product
include Neo4j::ActiveNode
id_property :id
property :name
property :code
property :stock_quantity, type: Integer
property :sale_price, type: Float
property :last_update, type: DateTime
end
When I create new node, it will has label as Core::Product. I want it to be Product instead.
According this post It seem that _classname property could resolve my problem but I have no idea how to implement it.
Any ideas?
Co-maintainer of Neo4j.rb here and author/responsible party for _classname. _classname is a very legacy option at this point, a holdover from when some DB responses didn't include node labels or relationship types. You can override automatic label assignment by calling self.mapped_label_name = in your model.
class Core::Product
include Neo4j::ActiveNode
self.mapped_label_name = 'Product'
# etc,...
end
You'll also want to be aware that the auto-location of association models won't work correctly, so instead of this:
has_many :out, :products, type: 'HAS_PRODUCT'
You'll need to do this:
has_many :out, :products, model_class: 'Core::Product', type: 'HAS_PRODUCT'
We have an open issue, https://github.com/neo4jrb/neo4j/issues/753, that discusses it. I namespace my models to organize code but want my labels to omit them, so I'd love a configuration option that handles this for me.
FOLLOW-UP
I just merged https://github.com/neo4jrb/neo4j/pull/790 into master. It lets you tell the gem to ignore module names when creating labels. I'm going to put it to work in some code this week but if you'd like to test it out, we always love feedback.

Using Prawn with Sinatra

How can I use Prawn to generate PDF of form data in Sinatra?
My form is at the index action of the site but Prawn doesn't recognize the variables passed in. I've found this code in the documentation at http://prawnpdf.org/docs/0.11.1/Prawn/Document.html.
get '/download' do
content = "Hello World"
Prawn::Document.generate "example.pdf" do |pdf|
pdf.font "Times-Roman"
pdf.draw_text content, :at => [200,720], :size => 32
end
end
Now this is great, but when I try to pass in my variables from the parameters like this:
post '/resume' do
#name = params.fetch 'name'
...
end
And then if I add that into the /download route like this:
get '/download' do
Prawn::Document.generate "example.pdf" do |pdf|
pdf.font "Times-Roman"
pdf.draw_text #name, :at => [200,720], :size => 32
end
end
It it will draw nothing. Also, weirdly, it generates a pdf file but doesn't redirect to it and I have to manually load it.
Really stuck on this one - advice?
Every request creates a new instance of your Sinatra app to serve it. Therefore, instance variables won't be the same across 2 different requests. You either need to persist the data using one of the many ways to do this (cookies, local storage, database, cache etc) or you need to put the Prawn logic in the POST route.

Ember.js with Rails accepts_nested_attributes_for and polymorphic has_many/belongs_to

On the Rails API side I have the following 2 models:
class Grower < ActiveRecord::Base
has_many :addresses, as: :addressable
accepts_nested_attributes_for :addresses
end
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
end
as well as a Growers controller which returns and can create/update Growers with embedded Addresses attributes. I also have an Addresses controller with proper routing so that Addresses can be viewed/created/updated for a specific Grower. The latter is more of an "in-case", and I'm not sure I'll be needing to return/update/create addresses as a separate payload.
I am starting to try and piece together an Ember app that would allow me to view/edit/create a Grower at the same time as its Address(es). Can anyone point me to an existing real or sample app that does this? I will be posting my code as I go along, but I already have an idea of some areas where I will be running into trouble:
Rails returns/expects nested params named addresses_attributes. Ember, I am sure, doesn't use that convention. What's the best approach of resolving this?
Because of the polymorphic association (objects other than Grower can be addressable), on the API/Address side, to get the correct belongs_to object, Rails uses addressable_id in conjunction with addressable_type. In this example the addressable_type would be "Grower", and the addressable_id would be the grower_id value. How would one go about translating that on the Ember side?
UPDATE:
I got it to work at least a couple different ways. My preferred solution, at least for this particular case, is in the answer section.
Here is a sample of code based #yuяi's strategy that worked well for me:
App.Post = DS.Model.extend
comments: DS.hasMany('comment')
App.PostSerializer = DS.ActiveModelSerializer.extend( DS.EmbeddedRecordsMixin,
attrs:
comments: {embedded: 'always'}
keyForAttribute: (attr) ->
if attr == "comments"
"comments_attributes"
else
#_super(attr)
)
This solution worked well with Ember 1.6.1 and Ember Data 1.0.0-beta.8.2a68c63a.
I found a couple ways to get it done, but the final approach doesn't require any changes on the Rails/API side.
On the client (Ember) side:
I added the addresses hasMany property to the App.Grower model. I also mapped it on the RESTAdapter to what's expected from the API, by setting the key for addresses to addresses_attributes.
I added the grower (for now - will change to addressable once I have other addressable models) belongsTo property on App.Address. It's not really required for what I'm doing, but it might be useful in the future.
I set the addresses on the RESTAdapter to be embedded: 'always'.
On the App.GrowersEditController, I just do a model.save (transaction.commit), and the child addresses are automatically saved via the API call.
On the App.GrowersAddController, I use the App.Address.createRecord and App.Grower.createRecord methods using the user-entered Grower and Address data. Then I use the pushObject method to append the Address to the Grower, and then call a save on the Grower (commit on transaction). Again, the address data gets submitted and saved automatically.

Rails : Benefit of URL path modification vs Namespace?

Many people talk about namespace as a way to change the URL that lead to their controller with a prefix (i.e. : /admin/movies instead of /movies)
Changing the URL path
The official doc explains that if we want to change the URL that lead to our controller with a prefix, we just have to change our resource in config/route.rb.
From this :
resources :movies
to this :
resources :movies, :path => "/admin/movies"
Implementing namespace
After a lot of googsearches, I'm wondering why so many people like to have namespace and what are the adavantages of namespace versus just modifying the URL path leading to a specific controller in the router file : myapp/config/route.rb
To implement a namespace, the official doc explains that you need rather the following modifications. You will see that this is a lot of work :
namespace :admin do
resources :movies
end
...and moves your movies_controller.rb controller to app/controllers/admin directory.
But if you follow these instructions, you'll get this error :
*"Expected /var/www/myapp/app/controllers/admin/movies_controller.rb to define Admin::MoviesController"*
*Then you realized that Rails expect this 'alien' writing at the begining of your movies_controller.rb : "Admin::"*
So you change the first line of your movies_controller.rb with :
class admin::MoviesController < ApplicationController
instead of :
class MoviesController < ApplicationController
But you again get another error :
"undefined local variable or method `admin' for main:Object"
Then you realized you forgot Ruby classes MUST be declared with a starting uppercase.
So you add a starting uppercase to your Ruby class :
class Admin::MoviesController < ApplicationController
But you still get an error :
*Missing template admin/movies/index, application/index with {:locale=>[:"fr-CH"], :formats=>[:html], :handlers=>[:erb, :builder, :rxls, :coffee, :haml]}. Searched in: * "/var/www/myapp/app/views"*
What the hell...? Oh did the doc forgot to say as well that controller's corresponding views must as well be moved to an admin directory within the app/view/ ?
So you create a directory and move your views to app/view/admin/
And you still get the same error.
Then you realized you forgot to include the movies folder itself within app/view/admin
So you did it.
You still got an error message :
*undefined method `movies_path' for #<#:0xa817c0c>*
This time you know that routing, controller and view work but you still have to change the pathes on all your views...
Moreover, if you are using the "respond_with" method in your controller file, you have to include the namespace as parameter. This is an example for the index operation :
def index
#movies = Movie.all
respond_with(:admin, #movies)
end
Moreover if you are using declarative_authentification gem (similar as cancan gem), you have to prefix the argument of your permited_to? method with the namespace. For example (with HAML syntax) :
- if permitted_to? :index, :admin_movies
// And prefix as well your path
= link_to 'Show all my movie", admin_movies_path
- if permitted_to? :show, :admin_movies
// And prefix as well your path
= link_to 'Show selected movie", admin_movie_path(#movie)
You realize you were going to create a namespace just for the url path conveniance, so you decide to give up, roll back your modif, and just add the following line in your route.rb file :
resources :movies, :path => "/admin/movies"
Which works immediately like a charm.
As testing purpose I created a new fake project "testapp" including namespace with the generator.
I performed a "rails generate scaffold admin/movie title:string" to check how does the generator handle namespace.
The resulting app/controller/admin/movies_controller.rb is rather different from what we expected it to be.
There are additionnal prefix "Admin::" in front of each instance variable declaration.
Here for instance the index method :
def index
#admin_movies = Admin::Movie.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #admin_movies }
end
end
I guess that this is because the generator as well moved the model movie.rb into app/models/admin directory
Moreover I see that there is another model in app/models : admin.rb
Which contains :
module Admin
def self.table_name_prefix
'admin_'
end
end
I have no idea how this method will be used nor by who ?
I notice as well that my table will be named "admin_movies" in the /db/migrate/2012blabla_create_admin_movies.rb
class CreateAdminMovies < ActiveRecord::Migration
def change
create_table :admin_movies do |t|
t.timestamps
end
end
end
Well, it seems there will have a lot more work (and mess-up) than I expected in order to put in place a namespace...
For what benefit/advantage ???
To use another url path ? This small modification in my controller
would be far more easier : resources :movies, :path =>
"/admin/movies"
To make it possible to use two different controllers using a same name ? Wouldn't it be easier to just put a prefix to my controler name than do all this mess-up ?
Of course some of the above errors could have been avoided by being more vigilant. But you know, we are just human, and when it's late in the evening while coding, maybe you wished this part of rails would have been, let's say, more human adapted...
I really don't understand why people get so excited to have namespace.
I woudld be gratefull, if an expert could explain what am I missing.
Many Thanks
If you have two different controllers with the same name but different functionality then you can use namespaced routes. You don't have to rename the controller for it. Check out "2.6 Controller Namespaces and Routing" at http://guides.rubyonrails.org/routing.html.
The idea is not to have a ton of controllers in one directory. Namespaces help you do that by grouping controllers in directories.
And as far doing all that work, it's a lot easier just to generate the controllers you need using the namespace paths, eg:
rake generate controller "Foo/Bars"
Then rails does all that heavy lifting so you don't have to.